canvas/pages/index/index.vue
2025-05-08 18:26:27 +08:00

259 lines
6.9 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像素 -->
<!-- // @touchstart="handleCanvasTouch" -->
<canvas @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd" :style="{
width: 1000 + 'px',
height: 800 + 'px',
transform: `translate(${offsetX}px, ${offsetY}px) scale(${scale})`
}" canvas-id="canvas" id="canvas"></canvas>
<!-- style="border: 1px solid red;height: 600px;width: 100vw;" -->
<image src="https://assets.sx25.troyrc.com/sx25/images/events/XBDT.jpg"></image>
<!-- 添加一个按钮用于触发绘图 -->
<button @click="handleDraw">点击绘制圆形</button>
</view>
</template>
<script setup>
import {
ref,
onMounted,
getCurrentInstance
} from 'vue'
import {
onReady
} from '@dcloudio/uni-app'
const canvasWidth = ref(375) // 动态设置Canvas宽度
const canvasHeight = ref(400) // 动态设置Canvas高度
const instance = getCurrentInstance()
const scale = ref(1)
const offsetX = ref(0)
const offsetY = ref(0)
const lastDistance = ref(-1)
const startX = ref(0)
const startY = ref(0)
const isDragging = ref(false)
const imgUrl = ref('https://assets.sx25.troyrc.com/sx25/images/events/XBDT.jpg'); // 修改为ref
// 定义图形数组
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 ctx = uni.createCanvasContext('canvas', instance) // 创建canvas绘图上下文
ctx.scale(scale.value, scale.value);
const res = await uni.getImageInfo({
src: imgUrl.value,
})
ctx.drawImage(res.path, 0, 0);
// 绘制每个图形
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.beginPath();
// ctx.moveTo(50, 50); // 左下角点
// ctx.lineTo(150, 50); // 右下角点
// ctx.lineTo(200, 100); // 右上角点
// ctx.lineTo(100, 100); // 左上角点
// ctx.closePath(); // 闭合路径
// ctx.stroke(); // 绘制边框
// 先不删
// let xoffset = 0, yoffset = 0, flag = false;
// polygonList.forEach((level, index) => {
// // console.log('level',level)
// ctx.moveTo(level.polygon[0] + xoffset, level.polygon[0] + yoffset)
// level.polygon.forEach((level2,level2Index)=>{
// ctx.beginPath()
// if(level2Index != level.polygon.length ){
// ctx.lineTo(level2 + xoffset, level.polygon[level2Index+1])
// console.log(level2 + xoffset, level.polygon[level2Index+1])
// }else{
// ctx.lineTo(level2 + xoffset, level.polygon[0])
// console.log(level2 + xoffset, level.polygon[0])
// }
// ctx.closePath()
// })
// if(polygonList.length == index){
// flag = true
// }
// })
ctx.draw()
}
// 处理canvas触摸事件
function handleCanvasTouch(event) {
// 获取触摸点的坐标
const x = event.touches[0].x;
const y = event.touches[0].y;
console.log(x, y, '12');
}
// 触摸开始
const handleTouchStart = (e) => {
const x = e.touches[0].x;
const y = e.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('用户点击了“取消”按钮');
}
},
});
}
});
if (e.touches.length === 1) {
// 单指拖动
startX.value = e.touches[0].clientX - offsetX.value
startY.value = e.touches[0].clientY - offsetY.value
isDragging.value = true
} else if (e.touches.length === 2) {
// 双指缩放
// const x1 = e.touches[0].clientX
// const y1 = e.touches[0].clientY
// const x2 = e.touches[1].clientX
// const y2 = e.touches[1].clientY
// lastDistance.value = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
// 双指缩放逻辑...
const x1 = e.touches[0].clientX,
y1 = e.touches[0].clientY;
const x2 = e.touches[1].clientX,
y2 = e.touches[1].clientY;
const distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
if (lastDistance.value > 0) {
scale.value = Math.min(Math.max(scale.value * (distance / lastDistance.value), 0.5), 4);
draw(); // 重新绘制Canvas内容
}
}
}
// 触摸移动
const handleTouchMove = (e) => {
console.log('handleTouchMove')
if (e.touches.length === 1 && isDragging.value) {
// 单指移动
const currentX = e.touches[0].clientX - startX.value
const currentY = e.touches[0].clientY - startY.value
offsetX.value = currentX
offsetY.value = currentY
} else if (e.touches.length === 2) {
// 双指缩放
const x1 = e.touches[0].clientX
const y1 = e.touches[0].clientY
const x2 = e.touches[1].clientX
const y2 = e.touches[1].clientY
const distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
if (lastDistance.value > 0) {
const newScale = scale.value * (distance / lastDistance.value)
scale.value = Math.min(Math.max(newScale, 0.5), 4) // 限制缩放范围
}
lastDistance.value = distance
}
}
// 触摸结束
const handleTouchEnd = () => {
console.log('handleTouchEnd')
lastDistance.value = -1
isDragging.value = false
}
// 按钮点击事件处理函数
const handleDraw = () => {
draw(); // 调用绘图函数
}
// onMounted(() => {
// setInterval(()=>{
// draw()
// },300)
// // 确保在组件挂载后可以获取到Canvas元素
// })
onReady(() => {
console.log('onReadyonReady');
uni.downloadFile({
url: imgUrl.value,
success: function(sres) {
console.log(sres, 'sres');
imgUrl.value = sres.tempFilePath || sres.path
draw()
},
fail: function(fres) {
console.log('fres', fres)
}
})
})
// 判断点是否在四边形内
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>