简体   繁体   English

HTML5 画布 - 旋转对象而不移动坐标

[英]HTML5 canvas - rotate object without moving coordinates

What I have is this:我有的是这个:坦克

What I want is to rotate the red rectangle eg 20 degrees, but this is what I end up with:我想要的是旋转红色矩形,例如 20 度,但这就是我最终得到的:旋转不好

As you can see, the rectangle is rotated perfectly, but it's moved and doesn't match the black object anymore.如您所见,矩形已完美旋转,但它已移动且不再与黑色对象匹配。

My code is:我的代码是:

context.save();
context.rotate(angle * Math.PI / 180); // in the screenshot I used angle = 20
context.translate(angle * 4, 2);
context.fillStyle = "red";
context.fillRect(x + 14, y - 16, 5, 16);
context.restore();

I want to make the rectangle turn without moving from its position.我想让矩形转动而不从其位置移动。

Thanks.谢谢。

Sounds like you want to rotate the rect around its centerpoint.听起来您想围绕其中心点旋转矩形。

Red rectangle is original, Yellow rectangle is rotated around the centerpoint.红色矩形是原始的,黄色矩形围绕中心点旋转。

在此处输入图片说明

To do that you need to first context.translate to the rect's centerpoint before rotating.为此,您需要在旋转之前先将context.translate转换为矩形的中心点。

// move the rotation point to the center of the rect

    ctx.translate( x+width/2, y+height/2 );

// rotate the rect

    ctx.rotate(degrees*Math.PI/180);

Note that the context is now in its rotated state.请注意,上下文现在处于旋转状态。

That means drawing position [0,0] is visually at [ x+width/2, y+height/2 ].这意味着绘图位置 [0,0] 在视觉上位于 [ x+width/2, y+height/2 ]。

So you must draw the rotated rect at [ -width/2, -height/2 ] (not at the original unrotated x/y).因此,您必须在 [ -width/2, -height/2 ] 处(而不是在原始未旋转的 x/y 处)绘制旋转的矩形。

// draw the rect on the transformed context
// Note: after transforming [0,0] is visually [-width/2, -height/2]
//       so the rect needs to be offset accordingly when drawn

    ctx.rect( -width/2, -height/2, width,height);

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/z4p3n/这是代码和小提琴: http : //jsfiddle.net/m1erickson/z4p3n/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var startX=50;
    var startY=80;

    // draw an unrotated reference rect
    ctx.beginPath();
    ctx.rect(startX,startY,100,20);
    ctx.fillStyle="blue";
    ctx.fill();

    // draw a rotated rect
    drawRotatedRect(startX,startY,100,20,45);

    function drawRotatedRect(x,y,width,height,degrees){

        // first save the untranslated/unrotated context
        ctx.save();

        ctx.beginPath();
        // move the rotation point to the center of the rect
        ctx.translate( x+width/2, y+height/2 );
        // rotate the rect
        ctx.rotate(degrees*Math.PI/180);

        // draw the rect on the transformed context
        // Note: after transforming [0,0] is visually [x,y]
        //       so the rect needs to be offset accordingly when drawn
        ctx.rect( -width/2, -height/2, width,height);

        ctx.fillStyle="gold";
        ctx.fill();

        // restore the context to its untranslated/unrotated state
        ctx.restore();

    }

}); // end $(function(){});
</script>

</head>

<body>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

You can use a simple function to do this as an alternative to translate and rotate:您可以使用一个简单的函数来执行此操作作为平移和旋转的替代方法:

This function will let you draw a line starting at x and y, and end at length at angle:这个函数会让你画一条线,从 x 和 y 开始,以一定的角度结束:

function lineToAngle(ctx, x1, y1, length, angle) {

    angle *= Math.PI / 180;

    var x2 = x1 + length * Math.cos(angle),
        y2 = y1 + length * Math.sin(angle);

    ctx.moveTo(x1, y1);
    ctx.lineTo(x2, y2);

    return {x: x2, y: y2};
}

Usage:用法:

lineToAngle(ctx, x, y, length, angle);

Demo演示

 var canvas = document.querySelector('canvas'), ctx = canvas.getContext('2d'), x = 100, y =50, length = 40, angle = 0, dlt = -2; (function animate() { //clear ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.beginPath(); lineToAngle(ctx, x, y, length, angle); ctx.lineWidth = 10; ctx.stroke(); angle += dlt; if (angle < -90 || angle > 0) dlt = -dlt; requestAnimationFrame(animate); })(); function lineToAngle(ctx, x1, y1, length, angle) { angle *= Math.PI / 180; var x2 = x1 + length * Math.cos(angle), y2 = y1 + length * Math.sin(angle); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); return {x: x2, y: y2}; }
 body {background-color:#555557} canvas {background:#ddd;border:1px solid #000}
 <canvas></canvas>

在此处输入图片说明

In the specific case of a rectangle, you can just draw a line.在矩形的特定情况下,您可以只画一条线。

In HTML5 canvas, lines are drawn exactly like rectangles, as such, you can use this function:在 HTML5 画布中,线条的绘制与矩形完全一样,因此,您可以使用此功能:

 let canvas = document.getElementById('myCanvas') let ctx = canvas.getContext('2d') function drawRotatedRect(ctx, x, y, width, height, angle) { angle *= Math.PI / 180 ctx.lineWidth = height / 2 ctx.beginPath() ctx.moveTo(x, y) ctx.lineTo(x + width * Math.cos(angle), y + width * Math.sin(angle)) ctx.stroke() } drawRotatedRect(ctx, 30, 30, 200, 100, 20)
 canvas { border: 1px solid black; width: 100%; }
 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Rotated Rectangle</title> </head> <body> <canvas id='myCanvas'></canvas> </body> </html>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM