网页缩放时精准取到canvas内部触摸坐标

首先我们知道触摸事件拿不到鼠标点击事件的offsetX和offsetY,而canvas画图的时候经常需要用到这两个值,正常页面没有缩放的时候,取clientX,clientY减掉canvas距离顶部的值就可以了
网页缩放时精准取到canvas内部触摸坐标_第1张图片
也就是紫色盒子减去红色盒子的距离

  <div class="bvox">
        <div class="xxx" id="container" style="width: 300px;height: 400px;">
            <canvas id="myCanvas" width="300" height="400"></canvas>
        </div>
  </div>


<script>
    window.onload = function () {

        // 获取 canvas 元素
        const canvas = document.getElementById("myCanvas");
        const ctx = canvas.getContext("2d");

        // 添加 touchmove 事件监听
        canvas.addEventListener("touchmove", handleMouseDown, false);
        let p = document.querySelector('p')
        function handleMouseDown(event) {
            const container = document.getElementById("container");
            const containerRect = container.getBoundingClientRect();
            const canvasRect = canvas.getBoundingClientRect();
     
            const x = (event.touches[0].clientX - containerRect.left) 
            const y = (event.touches[0].clientY - containerRect.top) 
            console.log(x, y);
   
        }
    }
</script>

但是网页或者canvas的父盒子有缩放的时候,直接取就不准确了。要用getBoundingClientRect().width/canvas.width得到缩放倍数,然后再乘上刚才算好的距离(y值类似)

<!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>
<style>
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    html,
    body {
        width: 100%;
        height: 100%;
    }

    .bvox {
        width: 100%;
        height: 100%;
        position: absolute;
        border: 1px solid red;
        box-sizing: border-box;
        transform: scale(0.9);
        display: flex;
        align-items: center;
        justify-content: center;
    }


    .xxx {
        border: 1px solid blue;
        box-sizing: border-box;
        position: relative;
    }
</style>

<body>
    <div class="bvox">
        <div class="xxx" id="container" style="width: 300px;height: 400px;">
            <canvas id="myCanvas" width="300" height="400"></canvas>
        </div>
    </div>
</body>
<script>
    window.onload = function () {

        // 获取 canvas 元素
        const canvas = document.getElementById("myCanvas");
        const ctx = canvas.getContext("2d");

        // 添加 touchmove 事件监听
        canvas.addEventListener("touchmove", handleMouseDown, false);
        let p = document.querySelector('p')
        function handleMouseDown(event) {
            const container = document.getElementById("container");
            const containerRect = container.getBoundingClientRect();
            const canvasRect = canvas.getBoundingClientRect();
            const scaleX = canvas.width / canvasRect.width;
            const scaleY = canvas.height / canvasRect.height;
            const x = (event.touches[0].clientX - containerRect.left) * scaleX;
            const y = (event.touches[0].clientY - containerRect.top) * scaleY;
            // console.log(x, y);
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = "#000000";
            ctx.fillRect(x - 8 / 2, y - 8 / 2, 8, 8);
            // p.style.left = x + 'px'
            // p.style.top = y + 'px'
        }
    }
</script>

</html>

如果大家用vue3写的话,记得.value !!!

<template>
       <canvas ref="canvas"  class="mycanvas" @touchstart="touchstart"></canvas>
</template>

<script setup>
const canvas = ref();
//获取开始坐标
const touchstart = (e) => {
    let canvasY = Math.round(canvas.value.getBoundingClientRect().top);
    let canvasX = Math.round(canvas.value.getBoundingClientRect().left);
    let startX = e.targetTouches[0].clientX;
    let startY = e.targetTouches[0].clientY;
    let scaleX =
        canvas.value.getBoundingClientRect().width / canvas.value.width;
    let scaleY =
        canvas.value.getBoundingClientRect().height / canvas.value.height;
    let item = {
        x: (startX - canvasX) / scaleX,
        y: (startY - canvasY) / scaleY,
    };
    startCoordinate.value = item;
    endCoordinate.value = item;
    drawLine();
};
</script>

你可能感兴趣的:(javascript,前端,vue3,canvas)