如何使用 class javascript 使线条跟随鼠标事件反正切

How to make a line follow mouse event arctanget with class javascript

大家好,我正在尝试按照鼠标移动事件制作一行。我可以使用 ctx.save 执行此操作并恢复,但如果我想使用 class 并绘制其他对象,我不知道该怎么做。事实上,使用保存和恢复它是有效的,但如果我想得到相同的结果 class,我不知道该怎么做,非常感谢

window.onload = function() {
    var canvas = document.getElementById("canvas"),
        context = canvas.getContext("2d"),
        width = canvas.width = window.innerWidth,
        height = canvas.height = window.innerHeight,
        arrowX = width / 2,
        arrowY = height / 2,
        dx, dy,
        angle = 0,
        a = 0;

    render();

    function render() {
        arrowX = width / 2 + Math.cos(a) * height * .4;
        arrowY = height / 2 + Math.sin(a) * height * .4;
        context.clearRect(0, 0, width, height);

        context.save();
        context.translate(arrowX, arrowY);
        context.rotate(angle);

        context.beginPath();
        context.moveTo(20, 0);
        context.lineTo(-20, 0);
        context.moveTo(20, 0);
        context.lineTo(10, -10);
        context.moveTo(20, 0);
        context.lineTo(10, 10);
        context.stroke();

        context.restore();
        requestAnimationFrame(render);
    }

    document.body.addEventListener("mousemove", function(event) {
        dx = event.clientX - arrowX;
        dy = event.clientY - arrowY;
        angle = Math.atan2(dy, dx);
    });


};
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body style="height: 100vh;">
    <Canvas id="canvas"></Canvas>
    <script src="main.js"></script>
</body>
</html>

如果我想使用 class,我会像下面的代码一样开始

    var canvas = document.getElementById("canvas");
        var c = canvas.getContext("2d");
        var width = canvas.width = window.innerWidth;
        var height = canvas.height = window.innerHeight;
        var arrowX = width / 2;
        var arrowY = height -20;
        var dx; 
    var dy;
        var angle = 0;

    
     class Player{
        constructor(x,y,radius,color)
        {
        this.x=x;
        this.y=y;
        this.radius=radius;
        this.color=color;
        }

        draw(){
            c.beginPath();
            c.arc(this.x,this.y,this.radius, 0, Math.PI *2,false );
            c.fillStyle=this.color;
            c.fill();
        }
    }

    class Shooter{
        constructor(x,y,xEnd,yEnd,color){
            this.x=x;
            this.y=y;
            this.xEnd=xEnd;
            this.yEnd=yEnd;
            this.color=color;
            
        }
        draw(){
        c.beginPath();
        
            c.moveTo(this.x, this.y);
            c.lineTo(this.xEnd, this.yEnd);
        c.strokeStyle=this.color;
            c.stroke();
        }

      

    }

   // const player= new Player(arrowX,arrowY,20,'white');
    const shooter= new Shooter(arrowX,500,arrowX,arrowY,'white');

    let animationId;
    
    function animate(){
    animationId=requestAnimationFrame(animate)
    c.fillStyle='rgba(0, 0, 0, 0.5)';
    c.fillRect(0,0,canvas.width,canvas.height);
    //player.draw();
    shooter.draw();
    }

    requestAnimationFrame(animate);
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body style="height: 100vh;">
    <Canvas id="canvas"></Canvas>
    <script src="main.js"></script>
</body>
</html>

我可以为此提供两种方法。第一种是简单地让矢量的末端与鼠标位置具有相同的坐标。这当然会改变向量的大小。

此方法不旋转或平移上下文。

var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var width = (canvas.width = window.innerWidth);
var height = (canvas.height = window.innerHeight);
let canvasBounds = canvas.getBoundingClientRect()

let mouse = {x: 0, y: 0}

class Shooter {
  constructor(x, y, color) {
    this.x = x;
    this.y = y;
    this.xEnd = mouse.x;
    this.yEnd = mouse.y;
    this.color = color;
  }
  draw() {
    c.beginPath();
    c.moveTo(this.x, this.y);
    c.lineTo(this.xEnd, this.yEnd);
    c.strokeStyle = this.color;
    c.stroke();
  }
  update() {
    this.xEnd = mouse.x;
    this.yEnd = mouse.y;
  }
}

const shooter = new Shooter(width/2, height/2, "white");

canvas.addEventListener("mousemove", e => {
        mouse.x = e.x - canvasBounds.x;
        mouse.y = e.y - canvasBounds.y;
    });

function animate() {
  animationId = requestAnimationFrame(animate);
  c.fillStyle = "rgba(0, 0, 0, 0.5)";
  c.fillRect(0, 0, canvas.width, canvas.height);
  //player.draw();
  shooter.draw();
  shooter.update();
}

requestAnimationFrame(animate);
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body style="height: 100vh;">
    <Canvas id="canvas"></Canvas>
    <script src="main.js"></script>
</body>
</html>

第二种方法在 (0, 0) 处绘制起点,但您可以使用 translate 将其定位在任何您想要的位置。这也会旋转上下文,但允许您保持大小不变​​。

var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var width = (canvas.width = window.innerWidth);
var height = (canvas.height = window.innerHeight);
let canvasBounds = canvas.getBoundingClientRect()

let mouse = {x: 0, y: 0}

class Shooter {
  constructor(x, y, color) {
    this.x = 0;
    this.y = 0;
    this.xEnd = this.x + 50;
    this.yEnd = this.y;
    this.translate = {x: x, y: y}
    this.color = color;
    this.angle = 0;
  }
  draw() {
     this.angle = Math.atan2(mouse.y - this.translate.y, mouse.x - this.translate.x)
    c.save();
    c.translate(this.translate.x, this.translate.y);
    c.rotate(this.angle);
    c.beginPath();
    c.moveTo(this.x, this.y);
    c.lineTo(this.xEnd, this.yEnd);
    c.strokeStyle = this.color;
    c.stroke();
    c.restore()
  }
  update() {
    
  }
}

const shooter = new Shooter(width/2, height/2, "white");

canvas.addEventListener("mousemove", e => {
        mouse.x = e.x - canvasBounds.x;
        mouse.y = e.y - canvasBounds.y;
    });

function animate() {
  requestAnimationFrame(animate);
  c.fillStyle = "rgba(0, 0, 0, 0.5)";
  c.fillRect(0, 0, canvas.width, canvas.height);
  //player.draw();
  shooter.draw();
}

requestAnimationFrame(animate);
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body style="height: 100vh;">
    <Canvas id="canvas"></Canvas>
    <script src="main.js"></script>
</body>
</html>