javascript - 在 Canvas 上旋转 'note' 以始终触摸左上角

标签 javascript html 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 的 Canvas 和一些 js 做了一个快速而肮脏的“便利贴”。

我希望能够以任何方式旋转它们,所以我尝试使用翻译。下面的例子我有一个 0,250 的翻译,这样你就可以看到整个事情。

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

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

我如何旋转正方形并将其移动到 Canvas 上,以便整个内容都显示在 Canvas 的左上角边缘?

我添加了一张图片,我的想法是只获取三 Angular 形的高度并将其移动那么多,但是在翻译时,它似乎并不能正常工作。

我将粘贴我的整个函数以便您查看,但如果您有任何想法,我将不胜感激。这不重要,今天就来凑热闹。

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 现在,唯一的问题是,我希望能够传入任何宽度、高度和 Angular ,并即时进行调整。

以如下代码为例:

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

据我发现,这是因为坐标不再水平和垂直。

所以,对于这个旋转坐标结构,我无法弄清楚如何将我的正方形(可以是任何大小并以任何 Angular 旋转)移回左侧和顶部(因此它适合尽可能小的空间)

这有意义吗?

最佳答案

简而言之:

  • 仅在 Y 方向平移上下文以将 Angular 放在应有的位置。
  • 围绕这个偏移点旋转上下文。
  • 在 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 点是右上角。我们将便利贴从正常 Angular 旋转了 -a 弧度(顺时针旋转为正,逆时针旋转为负)。

我们可以看到当便利贴旋转时,A 点保持在 y 轴上,所以我们只需要计算 y 向下多远 轴来移动它。此距离在图中表示为 BD。从三 Angular 学我们知道
sin(a) = BD/AB

重新排列这个公式可以得到
BD = **AB***sin(a)

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

  1. 因为我们的 Angular 会被表示为负数,而负数的sin会得到一个负数的结果,但是因为我们想要一个正数的结果,所以我们要么将结果取反
    BD = -AB***sin(-a)
    或者只是“作弊”并使用正 Angular :
    **BD
    = **AB***sin(a)

  2. 我们需要记住在旋转上下文之前对其进行翻译,以便我们首先直接沿着轴向下移动以在正确的位置建立我们的原点。

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

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

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

关于javascript - 在 Canvas 上旋转 'note' 以始终触摸左上角,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5555444/

相关文章:

javascript - 根据MongoDB中的条件为所有客户分配唯一价格的策略

html - 在 dom 变慢并变得不稳定之前,您可以拥有多少个 div?

java - 如何使用 Vaadin 将图像上传到 Canvas ?

html - CSS-向一个td添加填充会更改所有其他行的填充

html - 具有 CSS 网格和自动适应 minmax 的完全响应元素

javascript - Fabric js自定义图标旋转点

javascript - Pixi js 用 Canvas 上的纹理填充形状

javascript - Angular observable - 如何从订阅返回 true 或 false 到 observable

javascript - 为什么 html5-video 事件 timeupdate 在 Chrome 浏览器上触发两次?

javascript - 如何在Primefaces中通过PF('myDataTable')。filter()有效使用回调