如何在不使用 `context.rotate` 的情况下在七巧板游戏中旋转形状
How to rotate the shapes in a tangram game without using `context.rotate`
在canvas 600 * 600
三角形的三个点是 (100, 100), (300, 100), (200,200)
旋转中心是 (200, 100)
我想实现拖动三角形旋转。但我不知道如何改变这些点的坐标。
ps:我已经知道怎么计算旋转角度了
var rotateRadian = Math.atan2(mouseY - center.y, mouseX - center.x) - Math.atan2(startDragPosition.y - center.y, startDragPosition.x - center.x);
[来自下方评论的附加信息]
我想拼七巧板,有长方形、三角形、平行四边形
你有一个好的开始!
首先计算mouse-to-centerpoint角度:
// calc mouse angle
var dx=mouseX-centerX;
var dy=mouseY-centerY;
radianAngle=Math.atan2(dy,dx);
因为你有一个等边三角形,所以你的三角形是一个正多边形。使用三角函数计算多边形的 3 个旋转点:
// vertex#1
var x1=cx+radius*Math.cos(rotationAngle);
var y1=cy+radius*Math.sin(rotationAngle);
// vertex#2
rotationAngle+=PI2/3;
var x2=cx+radius*Math.cos(rotationAngle);
var y2=cy+radius*Math.sin(rotationAngle);
// vertex#3
rotationAngle+=PI2/3;
var x3=cx+radius*Math.cos(rotationAngle);
var y3=cy+radius*Math.sin(rotationAngle);
然后只需监听 mousemove 事件并相应地重绘三角形:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var scrollX=$canvas.scrollLeft();
var scrollY=$canvas.scrollTop();
ctx.fillStyle='red';
ctx.strokeStyle='blue';
ctx.lineWidth=2;
var isDown=false;
var startX;
var startY;
var PI2=Math.PI*2;
var cx=150;
var cy=150;
var sideLength=50;
var originalAngle=0;
var radius=sideLength*Math.sqrt(3)/3;
draw(200,200);
$("#canvas").mousemove(function(e){handleMouseMove(e);});
function draw(mx,my){
//
var dx=mx-cx;
var dy=my-cy;
var currentAngle=Math.atan2(dy,dx);
var rotationAngle=currentAngle-originalAngle;
// vertex#1
var x1=cx+radius*Math.cos(rotationAngle);
var y1=cy+radius*Math.sin(rotationAngle);
// vertex#2
rotationAngle+=PI2/3;
var x2=cx+radius*Math.cos(rotationAngle);
var y2=cy+radius*Math.sin(rotationAngle);
// vertex#3
rotationAngle+=PI2/3;
var x3=cx+radius*Math.cos(rotationAngle);
var y3=cy+radius*Math.sin(rotationAngle);
ctx.clearRect(0,0,cw,ch);
ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.lineTo(x3,y3);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.arc(x1,y1,3,0,PI2);
ctx.closePath();
ctx.fill();
}
function handleMouseMove(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mx=parseInt(e.clientX-offsetX);
my=parseInt(e.clientY-offsetY);
draw(mx,my);
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>The triangle will rotate according to the mouse</h4>
<canvas id="canvas" width=300 height=300></canvas>
[根据提问者评论添加]
数学原理类似,但更复杂,因为七巧板的形状不规则。
对于每个形状,您需要:
找到形状的质心,这是它的旋转中心
cx=average of all x vertices.
cy=average of all y vertices.
求形状的 3 或 4 个径向长度
// for each radius
radial length=Math.sqrt(Math.pow(vx-cx,2)+Math.pow(vy-cy,2))
求形状的 3 或 4 个径向角
// for each radius
radial angle=Math.atan2(Math.pow(vy-cy,2),Math.pow(vx-cx,2))
现在在我的答案中使用相同的三角函数来围绕质心旋转顶点
在canvas 600 * 600 三角形的三个点是 (100, 100), (300, 100), (200,200) 旋转中心是 (200, 100)
我想实现拖动三角形旋转。但我不知道如何改变这些点的坐标。
ps:我已经知道怎么计算旋转角度了 var rotateRadian = Math.atan2(mouseY - center.y, mouseX - center.x) - Math.atan2(startDragPosition.y - center.y, startDragPosition.x - center.x);
[来自下方评论的附加信息]
我想拼七巧板,有长方形、三角形、平行四边形
你有一个好的开始!
首先计算mouse-to-centerpoint角度:
// calc mouse angle
var dx=mouseX-centerX;
var dy=mouseY-centerY;
radianAngle=Math.atan2(dy,dx);
因为你有一个等边三角形,所以你的三角形是一个正多边形。使用三角函数计算多边形的 3 个旋转点:
// vertex#1
var x1=cx+radius*Math.cos(rotationAngle);
var y1=cy+radius*Math.sin(rotationAngle);
// vertex#2
rotationAngle+=PI2/3;
var x2=cx+radius*Math.cos(rotationAngle);
var y2=cy+radius*Math.sin(rotationAngle);
// vertex#3
rotationAngle+=PI2/3;
var x3=cx+radius*Math.cos(rotationAngle);
var y3=cy+radius*Math.sin(rotationAngle);
然后只需监听 mousemove 事件并相应地重绘三角形:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var scrollX=$canvas.scrollLeft();
var scrollY=$canvas.scrollTop();
ctx.fillStyle='red';
ctx.strokeStyle='blue';
ctx.lineWidth=2;
var isDown=false;
var startX;
var startY;
var PI2=Math.PI*2;
var cx=150;
var cy=150;
var sideLength=50;
var originalAngle=0;
var radius=sideLength*Math.sqrt(3)/3;
draw(200,200);
$("#canvas").mousemove(function(e){handleMouseMove(e);});
function draw(mx,my){
//
var dx=mx-cx;
var dy=my-cy;
var currentAngle=Math.atan2(dy,dx);
var rotationAngle=currentAngle-originalAngle;
// vertex#1
var x1=cx+radius*Math.cos(rotationAngle);
var y1=cy+radius*Math.sin(rotationAngle);
// vertex#2
rotationAngle+=PI2/3;
var x2=cx+radius*Math.cos(rotationAngle);
var y2=cy+radius*Math.sin(rotationAngle);
// vertex#3
rotationAngle+=PI2/3;
var x3=cx+radius*Math.cos(rotationAngle);
var y3=cy+radius*Math.sin(rotationAngle);
ctx.clearRect(0,0,cw,ch);
ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.lineTo(x3,y3);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.arc(x1,y1,3,0,PI2);
ctx.closePath();
ctx.fill();
}
function handleMouseMove(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mx=parseInt(e.clientX-offsetX);
my=parseInt(e.clientY-offsetY);
draw(mx,my);
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>The triangle will rotate according to the mouse</h4>
<canvas id="canvas" width=300 height=300></canvas>
[根据提问者评论添加]
数学原理类似,但更复杂,因为七巧板的形状不规则。
对于每个形状,您需要:
找到形状的质心,这是它的旋转中心
cx=average of all x vertices.
cy=average of all y vertices.
求形状的 3 或 4 个径向长度
// for each radius
radial length=Math.sqrt(Math.pow(vx-cx,2)+Math.pow(vy-cy,2))
求形状的 3 或 4 个径向角
// for each radius
radial angle=Math.atan2(Math.pow(vy-cy,2),Math.pow(vx-cx,2))
现在在我的答案中使用相同的三角函数来围绕质心旋转顶点