1、增加调试模式,调试模式下显示鸭子范围和目标区域范围
2、canvas中所有元素定位需要使用rpx转换处理
3、鸭子放开后,需要自动恢复原来位置
This commit is contained in:
Wenzhe 2026-01-31 21:19:18 +08:00
parent c0897a3d86
commit fd020b935d
1 changed files with 194 additions and 65 deletions

View File

@ -44,25 +44,48 @@ const showDuck = ref(true) // 调试时默认显示鸭子
const deskImage = ref('/static/dzm/img_desk1.png')
const showGuideElements = ref(true)
// Canvas
const canvasDisabled = ref(false)
//
const debugMode = ref(false)
// Canvas
const ctx = ref(null)
//
const duckImagePath = ref(null)
// Canvas
const duckX = ref(275)
const duckY = ref(110)
// rpx
const rpxRatio = ref(0.5) // iPhone 6/7/8 375px / 750rpx = 0.5
//
const duckWidth = 36
const duckHeight = 70
// 使 rpx 750rpx 稿
const duckRpx = ref({
x: 550, // 275px * 2 = 550rpx
y: 220, // 110px * 2 = 220rpx
width: 72, // 36px * 2 = 72rpx
height: 140 // 70px * 2 = 140rpx
})
// px
const duckX = ref(0)
const duckY = ref(0)
const duckWidth = ref(0)
const duckHeight = ref(0)
//
const dragOffsetX = ref(0)
const dragOffsetY = ref(0)
// Canvas
// Canvas 使 rpx
const canvasRpx = ref({
x: 0,
y: 1550, // 800px * 2 = 1600rpx
width: 750, // 375px * 2 = 750rpx ()
height: 600 // 300px * 2 = 600rpx
})
// Canvas px
const canvasRect = ref({
left: 0,
top: 0,
@ -70,12 +93,20 @@ const canvasRect = ref({
height: 0
})
// () - Canvas
// () - 使 rpx
const targetAreaRpx = ref({
x: 0,
y: 160, // 80px * 2 = 160rpx
width: 400, // 200px * 2 = 400rpx
height: 300 // 150px * 2 = 300rpx
})
// px
const targetArea = ref({
x: 0,
y: 80,
width: 200,
height: 150
y: 0,
width: 0,
height: 0
})
// ID
@ -115,20 +146,70 @@ const loadDuckImage = () => {
})
}
// rpx px
const rpxToPx = (rpx) => {
return rpx * rpxRatio.value
}
// rpx px
const updateDuckPosition = () => {
duckX.value = rpxToPx(duckRpx.value.x)
duckY.value = rpxToPx(duckRpx.value.y)
duckWidth.value = rpxToPx(duckRpx.value.width)
duckHeight.value = rpxToPx(duckRpx.value.height)
}
// rpx px
const updateTargetArea = () => {
targetArea.value = {
x: rpxToPx(targetAreaRpx.value.x),
y: rpxToPx(targetAreaRpx.value.y),
width: rpxToPx(targetAreaRpx.value.width),
height: rpxToPx(targetAreaRpx.value.height)
}
}
// Canvas rpx px
const updateCanvasRect = () => {
canvasRect.value = {
left: rpxToPx(canvasRpx.value.x),
top: rpxToPx(canvasRpx.value.y),
width: rpxToPx(canvasRpx.value.width),
height: rpxToPx(canvasRpx.value.height)
}
}
// Canvas
const canvasBoundingRect = ref({
left: 0,
top: 0
})
// Canvas
const getCanvasPosition = () => {
// rpx / 750
const systemInfo = uni.getSystemInfoSync()
rpxRatio.value = systemInfo.windowWidth / 750
console.log('屏幕宽度:', systemInfo.windowWidth, 'rpxRatio:', rpxRatio.value)
// Canvas px
updateCanvasRect()
updateDuckPosition()
updateTargetArea()
console.log('Canvas 位置信息:', canvasRect.value)
}
// Canvas
const getCanvasBoundingRect = () => {
const query = uni.createSelectorQuery().in(instance)
query.select('#dragDuckCanvas').boundingClientRect(res => {
if (res) {
canvasRect.value = {
canvasBoundingRect.value = {
left: res.left,
top: res.top,
width: res.width,
height: res.height
top: res.top
}
console.log('Canvas 位置信息:', canvasRect.value)
} else {
console.error('无法获取 Canvas 位置信息')
console.log('Canvas 视口位置:', canvasBoundingRect.value)
}
}).exec()
}
@ -163,6 +244,8 @@ const drawCanvas = () => {
const drawTarget = () => {
const target = targetArea.value
if (debugMode.value) {
//
//
ctx.value.setFillStyle('rgba(52, 152, 219, 0.3)')
ctx.value.fillRect(target.x, target.y, target.width, target.height)
@ -184,43 +267,60 @@ const drawTarget = () => {
target.y + target.height / 2
)
}
//
}
//
const drawDuck = () => {
if (!showDuck.value) return
//
if (!debugMode.value && !isDragging.value) {
return
}
//
if (isDragging.value) {
ctx.value.globalAlpha = 0.6
} else {
ctx.value.globalAlpha = 1.0
}
//
if (duckImagePath.value) {
ctx.value.drawImage(duckImagePath.value, duckX.value, duckY.value, duckWidth, duckHeight)
ctx.value.drawImage(duckImagePath.value, duckX.value, duckY.value, duckWidth.value, duckHeight.value)
} else {
//
ctx.value.setFillStyle('#ffcc00')
ctx.value.fillRect(duckX.value, duckY.value, duckWidth, duckHeight)
ctx.value.fillRect(duckX.value, duckY.value, duckWidth.value, duckHeight.value)
//
ctx.value.setStrokeStyle('#333')
ctx.value.setLineWidth(2)
ctx.value.strokeRect(duckX.value, duckY.value, duckWidth, duckHeight)
ctx.value.strokeRect(duckX.value, duckY.value, duckWidth.value, duckHeight.value)
//
ctx.value.setFontSize(14)
ctx.value.setFillStyle('#FFFFFF')
ctx.value.setTextAlign('center')
ctx.value.setTextBaseline('middle')
ctx.value.fillText('鸭', duckX.value + duckWidth / 2, duckY.value + duckHeight / 2)
ctx.value.fillText('鸭', duckX.value + duckWidth.value / 2, duckY.value + duckHeight.value / 2)
}
//
if (isDragging.value) {
//
ctx.value.globalAlpha = 1.0
//
if (debugMode.value && isDragging.value) {
//
ctx.value.setFillStyle('rgba(231, 76, 60, 0.3)')
ctx.value.fillRect(duckX.value, duckY.value, duckWidth, duckHeight)
ctx.value.fillRect(duckX.value, duckY.value, duckWidth.value, duckHeight.value)
//
ctx.value.setStrokeStyle('#e74c3c')
ctx.value.setLineWidth(2)
ctx.value.setLineDash([5, 5])
ctx.value.strokeRect(duckX.value - 3, duckY.value - 3, duckWidth + 6, duckHeight + 6)
ctx.value.strokeRect(duckX.value - 3, duckY.value - 3, duckWidth.value + 6, duckHeight.value + 6)
ctx.value.setLineDash([])
}
}
@ -228,9 +328,9 @@ const drawDuck = () => {
//
const checkTouchInDuck = (x, y) => {
return x >= duckX.value &&
x <= duckX.value + duckWidth &&
x <= duckX.value + duckWidth.value &&
y >= duckY.value &&
y <= duckY.value + duckHeight
y <= duckY.value + duckHeight.value
}
//
@ -238,8 +338,8 @@ const checkDuckInTarget = () => {
const target = targetArea.value
//
const duckCenterX = duckX.value + duckWidth / 2
const duckCenterY = duckY.value + duckHeight / 2
const duckCenterX = duckX.value + duckWidth.value / 2
const duckCenterY = duckY.value + duckHeight.value / 2
//
return duckCenterX >= target.x &&
@ -250,6 +350,12 @@ const checkDuckInTarget = () => {
//
const handleTouchStart = (e) => {
// Canvas
if (canvasDisabled.value) {
console.log('Canvas 已禁用,忽略触摸事件')
return
}
console.log('触摸开始事件触发', e)
//
@ -259,17 +365,20 @@ const handleTouchStart = (e) => {
return
}
// Canvas
getCanvasPosition()
// Canvas
getCanvasBoundingRect()
// Canvas
setTimeout(() => {
// Canvas
const touchX = touch.clientX - canvasRect.value.left
const touchY = touch.clientY - canvasRect.value.top
// Canvas 使
const touchX = touch.clientX - canvasBoundingRect.value.left
const touchY = touch.clientY - canvasBoundingRect.value.top
console.log(`触摸点 client: (${touch.clientX}, ${touch.clientY})`)
console.log(`Canvas 视口位置: (${canvasBoundingRect.value.left}, ${canvasBoundingRect.value.top})`)
console.log(`触摸点相对 Canvas: (${touchX}, ${touchY})`)
console.log(`鸭子位置: (${duckX.value}, ${duckY.value})`)
console.log(`鸭子尺寸: (${duckWidth.value}, ${duckHeight.value})`)
//
if (checkTouchInDuck(touchX, touchY)) {
@ -296,9 +405,9 @@ const handleTouchMove = (e) => {
const touch = e.touches[0]
if (!touch) return
// Canvas
const touchX = touch.clientX - canvasRect.value.left
const touchY = touch.clientY - canvasRect.value.top
// Canvas 使
const touchX = touch.clientX - canvasBoundingRect.value.left
const touchY = touch.clientY - canvasBoundingRect.value.top
//
duckX.value = touchX - dragOffsetX.value
@ -308,8 +417,8 @@ const handleTouchMove = (e) => {
const canvasW = canvasRect.value.width || 400
const canvasH = canvasRect.value.height || 600
duckX.value = Math.max(0, Math.min(canvasW - duckWidth, duckX.value))
duckY.value = Math.max(0, Math.min(canvasH - duckHeight, duckY.value))
duckX.value = Math.max(0, Math.min(canvasW - duckWidth.value, duckX.value))
duckY.value = Math.max(0, Math.min(canvasH - duckHeight.value, duckY.value))
console.log(`鸭子新位置: (${duckX.value}, ${duckY.value})`)
}
@ -330,10 +439,27 @@ const handleTouchEnd = () => {
showGuideElements.value = false
//
showDuck.value = false
// Canvas
canvasDisabled.value = true
console.log('Canvas 触摸事件已禁用')
} else {
//
console.log('未放入目标区域,回归原始位置')
resetDuckPosition()
}
}
}
//
const resetDuckPosition = () => {
// rpx
duckRpx.value.x = 550
duckRpx.value.y = 220
// px
updateDuckPosition()
console.log('鸭子已回归原始位置:', duckX.value, duckY.value)
}
//
const startDrag = (e) => {
console.log('开始拖拽', e)
@ -343,9 +469,10 @@ const startDrag = (e) => {
initCanvas()
}
//
duckX.value = 50
duckY.value = 50
// 使 rpx px
duckRpx.value.x = 100 // 100rpx 50px (iPhone 6/7/8)
duckRpx.value.y = 100
updateDuckPosition()
showDuck.value = true
//
@ -413,6 +540,12 @@ onUnmounted(() => {
canvas-id="dragDuckCanvas"
id="dragDuckCanvas"
class="drag-canvas"
:style="{
left: canvasRect.left + 'px',
top: canvasRect.top + 'px',
width: canvasRect.width + 'px',
height: canvasRect.height + 'px'
}"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
@ -514,10 +647,6 @@ onUnmounted(() => {
.drag-canvas {
position: absolute;
left: 0;
top: 800px;
width: 375px;
height: 300px;
z-index: 100;
pointer-events: auto;
}