如何在鼠标移动事件后围绕其中心旋转Canvas对象? [英] How to rotate a Canvas object around its center following mouse move event?

查看:125
本文介绍了如何在鼠标移动事件后围绕其中心旋转Canvas对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨我想在移动鼠标时围绕其中心旋转此形状,但目前它正在旋转(0,0)。如何更改我的代码?

Hi I want to rotate this shape around its center when I move my mouse, but currently it's rotating around (0, 0). How to change my code?

源代码(另见 jsfiddle ):

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

class Circle {
    constructor(options) {
    this.cx = options.x;
    this.cy = options.y;
    this.radius = options.radius;
    this.color = options.color;
    this.angle = 0;
    this.toAngle = this.angle;

    this.binding();
  }

  binding() {
    const self = this;
    window.addEventListener('mousemove', (e) => {
        self.update(e.clientX, e.clientY);
    });
  }

  update(nx, ny) {
    this.toAngle = Math.atan2(ny - this.cy, nx - this.cx);
  }

  render() {
    ctx.clearRect(0,0,canvas.width,canvas.height);

    ctx.save();

    ctx.beginPath();

    ctx.lineWidth = 1;

    if (this.toAngle !== this.angle) {
      ctx.rotate(this.toAngle - this.angle);
    }

    ctx.strokeStyle = this.color;
    ctx.arc(this.cx, this.cy, this.radius, 0, Math.PI * 2);

    ctx.stroke();
    ctx.closePath();

    ctx.beginPath();

    ctx.fillStyle = 'black';
    ctx.fillRect(this.cx - this.radius / 4, this.cy - this.radius / 4, 20, 20);

    ctx.closePath();
    ctx.restore();
  }
}

var rotatingCircle = new Circle({
  x: 150,
  y: 100,
  radius: 40,
  color: 'black'
});

function animate() {
    rotatingCircle.render();
    requestAnimationFrame(animate);
}

animate();


推荐答案

您需要:


  • 首先转换为旋转点(枢轴)

  • 然后旋转

  • 然后要么:


    • A:使用(-width / 2,-height / 2)作为相对坐标(对于居中图纸)在(0,0)处绘制

    • B:翻译并使用对象的绝对位置并减去居中绘图的相对坐标

    • first translate to the point of rotation (pivot)
    • then rotate
    • then either:
      • A: draw in at (0,0) using (-width/2, -height/2) as relative coordinate (for centered drawings)
      • B: translate back and use the object's absolute position and subtract relative coordinates for centered drawing

      修改后的代码:

      ctx.beginPath();
      ctx.lineWidth = 1;
      
      ctx.translate(this.cx, this.cy);               // translate to pivot
      
      if (this.toAngle !== this.angle) {
        ctx.rotate(this.toAngle - this.angle);
      }
      
      ctx.strokeStyle = this.color;
      ctx.arc(0, 0, this.radius, 0, Math.PI * 2);    // render at pivot
      
      ctx.closePath();                               // must come before stroke() btw.
      ctx.stroke();
      
      ctx.beginPath();
      ctx.fillStyle = 'black';
      ctx.fillRect(-this.radius / 4, -this.radius / 4, 20, 20);  // render at pivot
      

      修改小提琴

      Modified Fiddle

      奖金提示:你'目前正在使用 save() / restore()调用以维护转换矩阵。另一种方法是使用绝对值设置矩阵,最初替换 save() / restore() - 所以改为第一个 translate()

      Bonus tip: you're currently using save()/restore() calls to maintain the transformation matrix. Another way could be to set the matrix using absolute values initially replacing the save()/restore() - so instead of the first translate():

      ctx.setTranform(1,0,0,1,this.cx, this.cy);    // translate to pivot
      

      您还可以为每个样式设置样式。无论如何,它并没有改变核心解决方案。

      You can also set things like styles on an individual basis for each. Regardless, it doesn't change the core solution though.

      这篇关于如何在鼠标移动事件后围绕其中心旋转Canvas对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆