旋转画布上的“注释”以始终触摸左上角

时间:2011-04-05 16:50:05

标签: javascript html5 canvas

对我有用的最终代码是:

    <canvas id="bg-admin-canvas" width="500" height="500" style="margin:15px; background:#09F;"></canvas>
    <script>
        var postit = function(width,height,angle){
            var canvas = document.getElementById("bg-admin-canvas");
            var ctx = canvas.getContext("2d");

            var radians = angle * Math.PI / 180;                
            var move = width*Math.sin(radians);
            if(angle < 0 ){ ctx.translate(0,-move); }else{ ctx.translate(move,0); }
            ctx.rotate(radians);

            var gradient = ctx.createLinearGradient(0,height,width/2,height/2);
            gradient.addColorStop(0.05,"rgba(0,0,0,0)");
            gradient.addColorStop(0.5,"rgba(0,0,0,0.3)");
            ctx.fillStyle = gradient;
            ctx.fillRect(0,0,width,height);

            ctx.beginPath();
            ctx.moveTo(0,0);
            ctx.lineTo(width, 0);
            ctx.lineTo(width,height);
            ctx.lineTo(width-width*.8,height-height*.02);
            ctx.quadraticCurveTo(0+width*.02,height-height*.02,0+width*.02,(height - height*.2));
            ctx.closePath();
            var gradient = ctx.createLinearGradient(0,height,width/2,height/2);
            gradient.addColorStop(0,'#f7f8b9');
            gradient.addColorStop(1,'#feffcf');
            ctx.fillStyle = gradient;
            ctx.fill();

            ctx.beginPath();
            ctx.moveTo(width-width*.8,height-height*.02);
            ctx.quadraticCurveTo(0+width*.02,height-height*.02,0+width*.02,(height - height*.2));
            ctx.quadraticCurveTo(width*.05,height-height*.05,width*.1,height-height*.1);
            ctx.quadraticCurveTo(width*.1,height-height*.07,width-width*.8,height-height*.02);
            ctx.closePath();
            ctx.fillStyle = '#ffffff';
            ctx.fill();
            var gradient = ctx.createLinearGradient(0,height,width*.1,height-height*.1);
            gradient.addColorStop(0,"rgba(222,222,163,0.8)");
            gradient.addColorStop(1,'#feffcf');
            ctx.fillStyle = gradient;
            ctx.fill();

        }
        postit(300, 300, 10);
    </script>

您好,

我用html5的画布和一些js做了一个快速而又脏的“post-it”音符。

我希望无论如何都能旋转它们,所以我尝试使用翻译。下面的例子我有一个0,250的翻译,所以你可以看到整个事情。

理想情况下,我知道如果我的画布是300,300,那么我会 ctx.translate(150,150); ctx.rotate(-30); ctx.translate(-150,-150);

当然,因为我正在旋转一个正方形,所以它会被切断。

我如何旋转方块并在画布上移动它以便整个画面显示但是在画布的左上角?

我添加了一张图片,我的想法只是得到一个三角形的高度并将它移动那么多,但是当翻译时,它似乎不能正常工作。

我会粘贴我的整个功能,以便您可以查看它,但如果您有任何想法,我将不胜感激。这并不重要,只是今天乱七八糟。

var postit = function(width,height,angle){
            var canvas = jQuery("#bg-admin-canvas").get(0);
            var ctx = canvas.getContext("2d");

            /*var area = (width*width*Math.sin(angle))/2;
            var h = (area*2) / width + 30;
            ctx.translate(0,h);
            */
            //ctx.translate(150,150);
            ctx.translate(0,250);
            ctx.rotate(angle*Math.PI / 180);
            //ctx.translate(-150,-150);

            var gradient = ctx.createLinearGradient(0,height,width/2,height/2);
            gradient.addColorStop(0.05,"rgba(0,0,0,0)");
            gradient.addColorStop(0.5,"rgba(0,0,0,0.3)");
            ctx.fillStyle = gradient;
            ctx.fillRect(0,0,width,height);

            ctx.beginPath();
            ctx.moveTo(0,0);
            ctx.lineTo(width, 0);
            ctx.lineTo(width,height);
            ctx.lineTo(width-width*.8,height-height*.02);
            ctx.quadraticCurveTo(0+width*.02,height-height*.02,0+width*.02,(height - height*.2));
            ctx.closePath();
            var gradient = ctx.createLinearGradient(0,height,width/2,height/2);
            gradient.addColorStop(0,'#f7f8b9');
            gradient.addColorStop(1,'#feffcf');
            ctx.fillStyle = gradient;
            ctx.fill();

            ctx.beginPath();
            ctx.moveTo(width-width*.8,height-height*.02);
            ctx.quadraticCurveTo(0+width*.02,height-height*.02,0+width*.02,(height - height*.2));
            ctx.quadraticCurveTo(width*.05,height-height*.05,width*.1,height-height*.1);
            ctx.quadraticCurveTo(width*.1,height-height*.07,width-width*.8,height-height*.02);
            ctx.closePath();
            ctx.fillStyle = '#ffffff';
            ctx.fill();
            var gradient = ctx.createLinearGradient(0,height,width*.1,height-height*.1);
            gradient.addColorStop(0,"rgba(222,222,163,0.8)");
            gradient.addColorStop(1,'#feffcf');
            ctx.fillStyle = gradient;
            ctx.fill();
        }
        postit(300, 300, -35);

Postit from HTML5 Canvas


更多信息

Phrog,我想你知道我在做什么。此图显示了我想要做的事情: enter image description here 现在,唯一的问题是,我希望能够传递任何宽度,高度和角度,并在运行中进行调整。

以下代码为例:

var canvas = document.getElementById("bg-admin-canvas");
var ctx = canvas.getContext("2d");
ctx.arc(0,0,3,0,360,true); ctx.fill();
ctx.translate(50, 50);
ctx.arc(0,0,3,0,360,true); ctx.fill();
ctx.translate(-25, -25);
ctx.arc(0,0,3,0,360,true); ctx.fill();

我得到以下图片: enter image description here 现在,如果我在这里添加一个旋转:

var canvas = document.getElementById("bg-admin-canvas");
var ctx = canvas.getContext("2d");
ctx.arc(0,0,3,0,360,true); ctx.fill();
ctx.translate(50, 50);
ctx.arc(0,0,3,0,360,true); ctx.fill();
ctx.rotate(30*Math.PI/180);
ctx.translate(-25, -25);
ctx.arc(0,0,3,0,360,true); ctx.fill();

我现在有一个倾斜的坐标,结果是: enter image description here

正如我发现的那样,这是因为坐标不再是水平和垂直的。

所以,通过这种旋转的坐标结构,我无法弄清楚如何将我的方块(可以是任何尺寸并以任何角度旋转)移回到左侧和顶部(因此它适合尽可能小的空间) )

这有意义吗?

2 个答案:

答案 0 :(得分:4)

简而言之:

  • 仅在Y方向上翻译上下文,以便将角落放在应该的位置。
  • 围绕此偏移点旋转上下文。
  • 将对象绘制为0,0。

这是一个互动的工作示例,您可以在此处在线查看:
http://phrogz.net/tmp/canvas_rotate_square_in_corner.html

<!DOCTYPE HTML> 
<html lang="en"><head> 
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
  <title>HTML5 Canvas Rotate Square in Corner</title> 
  <style type="text/css" media="screen"> 
    body { background:#eee; margin:2em; text-align:center }
    canvas { display:block; margin:auto; background:#fff; border:1px solid #ccc }
  </style> 
</head><body> 
<canvas width="250" height="200"></canvas>
<script type="text/javascript" charset="utf-8"> 
  var can = document.getElementsByTagName('canvas')[0];
  var ctx = can.getContext('2d');
  ctx.strokeStyle = '#600'; ctx.lineWidth = 2; ctx.lineJoin = 'round';
  ctx.fillStyle = '#ff0'
  document.body.onmousemove = function(evt){
    var w=140, h=120;
    var angle = evt ? (evt.pageX - can.offsetLeft)/100 : 0;
    angle = Math.max(Math.min(Math.PI/2,angle),0);
    ctx.clearRect(0,0,can.width,can.height); ctx.beginPath();
    ctx.save();
    ctx.translate(1,w*Math.sin(angle)+1);
    ctx.rotate(-angle);
    ctx.fillRect(0,0,w,h);
    ctx.strokeRect(0,0,w,h);
    ctx.restore();
  };
  document.body.onmousemove();
</script> 
</body></html>

分析

Diagram showing a rectangle rotated counter-clockwise, with corner A on the Y axis at 0,12 and corner B on the X axis at 20,0; construction D is at 20,12, and the angle DAB is labeled with a lowercase 'a'

在上图中,点 A 是我们便利贴的左上角,点 B 是右上角。我们从正常角度旋转了音符 -a 弧度(顺时针旋转为正,逆时针为负)。

我们可以看到 A 点在它后旋转时停留在 y 轴上,所以我们只需要计算 y的下降距离轴移动它。该距离在图中表示为 BD 。从三角学我们知道 罪(a)= BD / AB

重新安排这个公式给了我们 BD = ** AB *** sin(a)

我们知道 AB 是我们便利贴的宽度。一些细节:

  1. 因为我们的角度将表示为负数,而负数的 sin 会产生负数结果,但由于我们想要一个正数结果,我们必须否定结果
    BD = - AB ***罪(-a)
    或者只是'作弊'并使用正角度:
    ** BD
    = ** AB *** sin(a)

  2. 我们需要记住在旋转之前翻译我们的上下文,这样我们才能首先直接沿着轴向下移动,以便在正确的位置建立起源。

  3. 请记住,HTML5 Canvas中的旋转使用弧度(而不是度)。如果要旋转20度,则需要乘以Math.PI/180将其转换为弧度:

  4.    
        ctx.rotate( 20*Math.PI/180 );
    

    这也适用于arc命令;你应该做ctx.arc(x,y,r,0,Math.PI*2,false);整整一圈。

答案 1 :(得分:2)

您应该创建canvas元素,然后使用CSS旋转它。它会保持你的画布完整,只旋转元素本身。

以下是一些示例css规则:

-webkit-transform: rotate(-30deg); 
-moz-transform: rotate(-30deg);

请参阅http://snook.ca/archives/html_and_css/css-text-rotation