canvas(十)图形交互

canvas图形交互

  • canvas 图形没有监听事件的方法
  • 比如用鼠标选择图形时,我们只能用canvas 画布监听事件,获取鼠标或触摸点在canvas 中的位置,再基于图形在canvas 中的位置和形状,判断鼠标在canvas中的点位是否在图形中。

获取canvas 中鼠标位置的方法

canvas.addEventListener('mousedown', getPos);

function getPos(event){
    const {clientX,clientY}=event;
    const {left,top}=canvas.getBoundingClientRect();
    const [x,y]=[clientX-left,clientY-top];                                                                                                                                                          
}      

获取触摸点点位的方法

canvas.addEventListener('mousedown', getPos);
function getPos(event){
    const {pageX, pageY}=event.changedTouches[0];
    const {left,top}=canvas.getBoundingClientRect();
    const [x,y]=[pageX -left, pageY -top];
    console.log(x,y);
}

实现矩形拖拽

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>矩形的拖拽</title>
    <style>
        body{margin: 0;overflow: hidden}
        #canvas{background: antiquewhite;}
    </style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
    const canvas=document.getElementById('canvas');
    canvas.width=window.innerWidth;
    canvas.height=window.innerHeight;
    const  ctx=canvas.getContext('2d');
    //矩形对象
    class Rectangle{
        constructor(width=0,height=0,color='#000'){
            this.width=width;
            this.height=height;
            this.color=color;
            this.x=0;
            this.y=0;
        }
        draw(ctx){
            const {x,y,width,height,color}=this;
            ctx.save();
            ctx.fillStyle=color;
            ctx.fillRect(x,y,width,height);
            ctx.restore();
        }
    }
    //实例化矩形对象
    const rect = new Rectangle(200,100);
    rect.x=100;
    rect.y=100;

    //鼠标位减图形位
    let subPos=null;
    //图形是否被选择
    let selected=false;
    //点击事件
    canvas.addEventListener('mousedown',mousedownFn);
    //移动
    canvas.addEventListener('mousemove',mousemoveFn);
    //鼠标抬起
    canvas.addEventListener('mouseup',mouseupFn);

    function mousedownFn(event){
        //鼠标位置
        const mousePos=getMousePos(event);

        //鼠标位减图形位
        subPos={
            x:mousePos.x-rect.x,
            y:mousePos.y-rect.y,
        }
        
        //判断鼠标是否在图形中
        selected=containPoint(rect,mousePos);
        console.log(selected);

    }
    function mousemoveFn(event){
        //鼠标位置
        const mousePos=getMousePos(event);
        /*如果鼠标选择了图形
        *   让图形跟着鼠标动
        *   按需渲染
        * */
        if(selected){
            rect.x=mousePos.x-subPos.x;
            rect.y=mousePos.y-subPos.y;
            render();
        }
    }
    function mouseupFn(event){
        //鼠标抬起,取消拖拽
        selected=false;
    }
    //判断点是否在图形中
    function containPoint(obj,mousePos){
        //解构图形位置和尺寸
        const {x,y,width,height}=obj;
        //解构鼠标位置
        const {x:mx,y:my}=mousePos;
        //计算鼠标和图形上、下、左、右边界的关系
        const l=mx>x;
        const r=mx<x+width;
        const t=my>y;
        const b=my<y+height;

        return l&&r&&t&&b;
    }
    //获取鼠标在canvas中的位置
    function getMousePos(event){
        //获取鼠标位置
        const {clientX,clientY}=event;
        //获取canvas 边界位置
        const {top,left}=canvas.getBoundingClientRect();
        //计算鼠标在canvas 中的位置
        const x=clientX-left;
        const y=clientY-top;
        return {x,y};
    }
    //渲染方法
    render();
    function render(){
        ctx.clearRect(0,0,canvas.width,canvas.height);
        rect.draw(ctx);
    }
</script>
</body>
</html>

判断一个点位是否在路径中

  • isPointInPath(x,y) 是canvas 2d中的内置方法,它可以判断一个点位是否在路径中。
  • isPointInPath(x,y) 面向的对象是路径,所以对文字、fillRect()、strokeRect()不好使。

回顾一下路径的基本概念:

  • 在我使用canvas 的getContext(‘2d’) 方法获取canvas 上下文对象ctx 的时候, ctx上便挂载了一个空的路径集合。
  • 在ctx.beginPath() 之后,所绘制的所有路径都会被添加到这个路径集合里,isPointInPath(x,y) 方法判断的就是x、y 点是否在这个路径集合的所有路径里。
  • 这个路径可以不用画出来,只要路径集合里有路径即可。

注意,在下一次ctx.beginPath() 时,路径集合会被置空。

示例

  • 用三个点画了一条折线,没有将其闭合,然后对其进行选择。
const ctx=canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(50,50);
ctx.lineTo(450,50);
ctx.lineTo(250,200);
console.log(ctx.isPointInPath(250,100)); //true
ctx.stroke();

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值