canvas学习 系列 1----------箭头随鼠标移动 蛇蛇大作战原理

1 构造箭头类

2 计算鼠标在canvas上的坐标

3 计算鼠标位置与箭头中心位置连线的角度

4 计算在x,y方向上的移动量

5重新渲染箭头

<!--箭头跟随鼠标转动案例-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
<canvas id="canvas"></canvas>

</body>
<script src="arrow.js"></script>
<script src="utils.js"></script>
<script>
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    let W = canvas.width = 800;
    let H = canvas.height = 600;
    const arrow = new Arrow({
        x: W/2,
        y: H/2,
        w: 140,
        h: 60,
        rotation:30
    }).render(ctx);
    let mouse = utils.getOffset(canvas);
    let speed=0.2
    //获取鼠标在canvas上的坐标,连线即可计算角度
    function move() {
        /**
         * 计算图形中心点与鼠标的连线
         * @type {number}
         */
        let dx = mouse.x - arrow.x;
        let dy = mouse.y - arrow.y;
        let angle = Math.atan2(dy, dx);
        //设置箭头的角度
        arrow.rotation = angle
        //计算向鼠标所在位置移动时,在x和y方向上的移动量,
        //speed为移动的系数,
        let vx = speed * Math.cos(angle);
        let vy = speed * Math.sin(angle);

        arrow.x += vx;
        arrow.y += vy;

        ctx.clearRect(0, 0, W, H);
        arrow.render(ctx);
        requestAnimationFrame(move);
    }
    move()



</script>
</html>

util.js

var utils={}
utils.getOffset=function (ele){
    let mouse = {x: 0, y: 0};
    ele.addEventListener('mousemove', function (e){

        let {x, y} = utils.eventWrapper(e);
        mouse.x = x;
        mouse.y = y;
    });
    return mouse;
};
// 坐标系转换
utils.eventWrapper = function (ev){
    /***
     * pageX 事件发生点当前文档横坐标
     * pageY 事件发生点当前文档纵坐标
     * target 事件发生的目标元素---最先触发的那一层
     * getBoundingClientRect
     * 事件发生节点元素的DOMRect对象,除去宽高外,都是相对于左上角的值
     * 简单可理解为文档流的pageX,pageY减去canvas相对于文档流向下,向
     * 右的偏移量,即可得到鼠标事件在canvas元素中的坐标
     */

    let {pageX, pageY, target} = ev;
    let {left, top} = target.getBoundingClientRect();
    return {x: pageX - left, y: pageY - top};
};

arrow.js
class Arrow {
    constructor(props){
        this.x=0//绘制箭头的初始坐标点x,y
        this.y=0
        this.w=0
        this.h=0

        Object.assign(this,props)
        return this
    }
    //创建图形
    createPath(ctx){
       let {w,h}=this
        ctx.beginPath();
        ctx.moveTo(-w/2, -h/2);
        ctx.lineTo(w/10, -h/2);
        ctx.lineTo(w/10, -h);
        ctx.lineTo(w/2, 0);
        ctx.lineTo(w/10, h);
        ctx.lineTo(w/10, h/2);
        ctx.lineTo(-w/2, h/2);
        ctx.closePath();
        return this;
    }
    //绘制图形
    render(ctx){
        let {fillStyle, strokeStyle, rotation, x, y,lineWidth} = this;
        ctx.save();
        ctx.fillStyle = fillStyle ? fillStyle:'rgba(255,0,0,1)';
        ctx.lineWidth=lineWidth?lineWidth:20
        ctx.strokeStyle = strokeStyle ? fillStyle:'rgba(255,0,0,1)';
        ctx.translate(x, y);
        ctx.rotate(rotation);
        this.createPath(ctx);
        ctx.fill();
        ctx.stroke();
        ctx.restore();
        return this;
    }

}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值