首先我们知道触摸事件拿不到鼠标点击事件的offsetX和offsetY,而canvas画图的时候经常需要用到这两个值,正常页面没有缩放的时候,取clientX,clientY减掉canvas距离顶部的值就可以了
也就是紫色盒子减去红色盒子的距离
<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>