canvas 点击拾取要素

43 阅读1分钟

场景

  • canvas 绘制多个图形,点击不同得图形,需要做不同得拾取

  • canvas 本身没有提供要素(图形)拾取事件

  • 需要自己封装拾取事件,原理就是使用 canvas 提供得 isPointInPath 方法

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        #c {
            margin: 100px auto;
            display: flex;
            border: 1px solid #f00;
        }
    </style>
</head>

<body>
    <canvas id="c"></canvas>
    <script>
        const c = document.getElementById('c');
        c.width = 1000
        c.height = 800

        const ctx = c.getContext('2d');
        const list = []

        ctx.fillStyle = "blue";
        const rect_1 = new Path2D()
        rect_1.rect(10, 10, 150, 100);
        ctx.stroke(rect_1);//画出对象
        list.push({ name: 'rect_1', path: rect_1 })

        const rect_2 = new Path2D()
        rect_2.rect(300, 300, 150, 100);
        ctx.fill(rect_2);//画出对象
        list.push({ name: 'rect_2', path: rect_2 })

        ctx.fillStyle = "green";
        const rect_3 = new Path2D()
        rect_3.rect(320, 320, 150, 100);
        ctx.fill(rect_3);//画出对象
        list.push({ name: 'rect_3', path: rect_3 })

        const circle = new Path2D();
        circle.arc(200, 200, 50, 0, 2 * Math.PI);
        ctx.fill(circle);//画出对象
        list.push({ name: 'circle', path: circle })

        c.addEventListener('click', (e) => {
            const { offsetX, offsetY } = e

            let cur = ''
            list.forEach(v => {
                // 多个要素重合会触发多次
                if (ctx.isPointInPath(v.path, offsetX, offsetY)) {
                    cur = v.name
                }
            })
            console.log(cur)
        })
    </script>
</body>

</html>

image.png