canvas/pages/index/index.vue
2025-05-08 17:30:13 +08:00

173 lines
4.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view>
<!-- 定义canvas画布 // 设置canvas大小为200x200像素 -->
<canvas @touchstart="handleCanvasTouch" @touchmove="handleCanvasTouchMove" @touchend="handleCanvasTouchEnd"
canvas-id="canvas" id="canvas" style="border: 1px solid red;height: 600px;width: 1000px;"></canvas>
<!-- 添加一个按钮用于触发绘图 -->
<button @click="handleDraw">点击绘制圆形</button>
</view>
</template>
<script setup>
import {
ref,
onMounted,
getCurrentInstance
} from 'vue'
// 平移和缩放状态
const translateX = ref(0);
const translateY = ref(0);
const scale = ref(1);
const canvasWidth = ref(375) // 动态设置Canvas宽度
const canvasHeight = ref(400) // 动态设置Canvas高度
const instance = getCurrentInstance()
// 定义图形数组
const blocks = ref([{
points: [{
x: 50,
y: 50
}, // 左下角点
{
x: 150,
y: 50
}, // 右下角点
{
x: 200,
y: 100
}, // 右上角点
{
x: 100,
y: 100
}, // 左上角点
],
message: '点击了四边形',
type: 'quadrilateral'
}]);
async function draw() {
// 设置平移和缩放
const imgUrl = "https://assets.sx25.troyrc.com/sx25/images/events/XBDT.jpg"
const ctx = uni.createCanvasContext('canvas', instance) // 创建canvas绘图上下文
ctx.translate(translateX.value, translateY.value );
ctx.scale(scale.value, scale.value);
const res = await uni.getImageInfo({
src: imgUrl,
})
ctx.drawImage(res.path, 0, 0,canvasWidth.value ,canvasHeight.value);
// 绘制每个图形
blocks.value.forEach((block) => {
ctx.beginPath();
ctx.fillStyle = block.color;
switch (block.type) {
case 'quadrilateral': // 四边形
ctx.moveTo(block.points[0].x, block.points[0].y);
for (let i = 1; i < block.points.length; i++) {
ctx.lineTo(block.points[i].x, block.points[i].y);
}
ctx.closePath();
break;
}
ctx.stroke(); // 绘制边框
});
ctx.draw()
}
// 处理canvas触摸移动事件
function handleCanvasTouchMove(event) {
if (event.touches.length === 1) {
// 单指平移
translateX.value += event.touches[0].x - event.touches[0].startX;
translateY.value += event.touches[0].y - event.touches[0].startY;
} else if (event.touches.length === 2) {
// 双指缩放
const distance1 = Math.sqrt(
(event.touches[0].x - event.touches[1].x) ** 2 +
(event.touches[0].y - event.touches[1].y) ** 2
);
const distance2 = Math.sqrt(
(event.touches[0].startX - event.touches[1].startX) ** 2 +
(event.touches[0].startY - event.touches[1].startY) ** 2
);
scale.value *= distance1 / distance2;
}
draw(); // 重新绘制
}
// 处理canvas触摸结束事件
function handleCanvasTouchEnd(event) {
// 保存当前触摸点的初始位置
event.touches.forEach((touch) => {
touch.startX = touch.x;
touch.startY = touch.y;
});
}
// 处理canvas触摸事件
function handleCanvasTouch(event) {
// 获取触摸点的坐标
const x = event.touches[0].x;
const y = event.touches[0].y;
// 判断点击位置
blocks.value.forEach((block) => {
if (isPointInQuadrilateral(x, y, block.points)) {
uni.showModal({
title: '提示',
content: block.message,
showCancel: true, // 显示取消按钮
success: (res) => {
if (res.confirm) {
console.log('用户点击了“确定”按钮');
} else if (res.cancel) {
console.log('用户点击了“取消”按钮');
}
},
});
}
});
}
// 按钮点击事件处理函数
const handleDraw = () => {
draw(); // 调用绘图函数
}
onMounted(() => {
draw()
// 确保在组件挂载后可以获取到Canvas元素
})
// 判断点是否在四边形内
function isPointInQuadrilateral(px, py, points) {
let inside = false;
const n = points.length;
let p1 = points[0];
for (let i = 1; i <= n; i++) {
let p2 = points[i % n];
if (py > Math.min(p1.y, p2.y) && py <= Math.max(p1.y, p2.y) && px <= Math.max(p1.x, p2.x)) {
if (p1.y !== p2.y) {
let xinters = (py - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
if (p1.x === p2.x || px <= xinters) {
inside = !inside;
}
}
}
p1 = p2;
}
return inside;
}
</script>
<style scoped>
button {
margin-top: 10px;
}
</style>