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 deskImage = ref('/static/dzm/img_desk1.png')
const showGuideElements = ref(true) const showGuideElements = ref(true)
// Canvas
const canvasDisabled = ref(false)
//
const debugMode = ref(false)
// Canvas // Canvas
const ctx = ref(null) const ctx = ref(null)
// //
const duckImagePath = ref(null) const duckImagePath = ref(null)
// Canvas // rpx
const duckX = ref(275) const rpxRatio = ref(0.5) // iPhone 6/7/8 375px / 750rpx = 0.5
const duckY = ref(110)
// // 使 rpx 750rpx 稿
const duckWidth = 36 const duckRpx = ref({
const duckHeight = 70 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 dragOffsetX = ref(0)
const dragOffsetY = 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({ const canvasRect = ref({
left: 0, left: 0,
top: 0, top: 0,
@ -70,12 +93,20 @@ const canvasRect = ref({
height: 0 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({ const targetArea = ref({
x: 0, x: 0,
y: 80, y: 0,
width: 200, width: 0,
height: 150 height: 0
}) })
// ID // 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 // Canvas
const getCanvasPosition = () => { 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) const query = uni.createSelectorQuery().in(instance)
query.select('#dragDuckCanvas').boundingClientRect(res => { query.select('#dragDuckCanvas').boundingClientRect(res => {
if (res) { if (res) {
canvasRect.value = { canvasBoundingRect.value = {
left: res.left, left: res.left,
top: res.top, top: res.top
width: res.width,
height: res.height
} }
console.log('Canvas 位置信息:', canvasRect.value) console.log('Canvas 视口位置:', canvasBoundingRect.value)
} else {
console.error('无法获取 Canvas 位置信息')
} }
}).exec() }).exec()
} }
@ -163,6 +244,8 @@ const drawCanvas = () => {
const drawTarget = () => { const drawTarget = () => {
const target = targetArea.value const target = targetArea.value
if (debugMode.value) {
//
// //
ctx.value.setFillStyle('rgba(52, 152, 219, 0.3)') ctx.value.setFillStyle('rgba(52, 152, 219, 0.3)')
ctx.value.fillRect(target.x, target.y, target.width, target.height) ctx.value.fillRect(target.x, target.y, target.width, target.height)
@ -183,44 +266,61 @@ const drawTarget = () => {
target.x + target.width / 2, target.x + target.width / 2,
target.y + target.height / 2 target.y + target.height / 2
) )
}
//
} }
// //
const drawDuck = () => { const drawDuck = () => {
if (!showDuck.value) return 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) { 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 { } else {
// //
ctx.value.setFillStyle('#ffcc00') 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.setStrokeStyle('#333')
ctx.value.setLineWidth(2) 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.setFontSize(14)
ctx.value.setFillStyle('#FFFFFF') ctx.value.setFillStyle('#FFFFFF')
ctx.value.setTextAlign('center') ctx.value.setTextAlign('center')
ctx.value.setTextBaseline('middle') 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.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.setStrokeStyle('#e74c3c')
ctx.value.setLineWidth(2) ctx.value.setLineWidth(2)
ctx.value.setLineDash([5, 5]) 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([]) ctx.value.setLineDash([])
} }
} }
@ -228,9 +328,9 @@ const drawDuck = () => {
// //
const checkTouchInDuck = (x, y) => { const checkTouchInDuck = (x, y) => {
return x >= duckX.value && return x >= duckX.value &&
x <= duckX.value + duckWidth && x <= duckX.value + duckWidth.value &&
y >= duckY.value && y >= duckY.value &&
y <= duckY.value + duckHeight y <= duckY.value + duckHeight.value
} }
// //
@ -238,8 +338,8 @@ const checkDuckInTarget = () => {
const target = targetArea.value const target = targetArea.value
// //
const duckCenterX = duckX.value + duckWidth / 2 const duckCenterX = duckX.value + duckWidth.value / 2
const duckCenterY = duckY.value + duckHeight / 2 const duckCenterY = duckY.value + duckHeight.value / 2
// //
return duckCenterX >= target.x && return duckCenterX >= target.x &&
@ -250,6 +350,12 @@ const checkDuckInTarget = () => {
// //
const handleTouchStart = (e) => { const handleTouchStart = (e) => {
// Canvas
if (canvasDisabled.value) {
console.log('Canvas 已禁用,忽略触摸事件')
return
}
console.log('触摸开始事件触发', e) console.log('触摸开始事件触发', e)
// //
@ -259,17 +365,20 @@ const handleTouchStart = (e) => {
return return
} }
// Canvas // Canvas
getCanvasPosition() getCanvasBoundingRect()
// Canvas // Canvas
setTimeout(() => { setTimeout(() => {
// Canvas // Canvas 使
const touchX = touch.clientX - canvasRect.value.left const touchX = touch.clientX - canvasBoundingRect.value.left
const touchY = touch.clientY - canvasRect.value.top 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(`触摸点相对 Canvas: (${touchX}, ${touchY})`)
console.log(`鸭子位置: (${duckX.value}, ${duckY.value})`) console.log(`鸭子位置: (${duckX.value}, ${duckY.value})`)
console.log(`鸭子尺寸: (${duckWidth.value}, ${duckHeight.value})`)
// //
if (checkTouchInDuck(touchX, touchY)) { if (checkTouchInDuck(touchX, touchY)) {
@ -296,9 +405,9 @@ const handleTouchMove = (e) => {
const touch = e.touches[0] const touch = e.touches[0]
if (!touch) return if (!touch) return
// Canvas // Canvas 使
const touchX = touch.clientX - canvasRect.value.left const touchX = touch.clientX - canvasBoundingRect.value.left
const touchY = touch.clientY - canvasRect.value.top const touchY = touch.clientY - canvasBoundingRect.value.top
// //
duckX.value = touchX - dragOffsetX.value duckX.value = touchX - dragOffsetX.value
@ -308,8 +417,8 @@ const handleTouchMove = (e) => {
const canvasW = canvasRect.value.width || 400 const canvasW = canvasRect.value.width || 400
const canvasH = canvasRect.value.height || 600 const canvasH = canvasRect.value.height || 600
duckX.value = Math.max(0, Math.min(canvasW - duckWidth, duckX.value)) duckX.value = Math.max(0, Math.min(canvasW - duckWidth.value, duckX.value))
duckY.value = Math.max(0, Math.min(canvasH - duckHeight, duckY.value)) duckY.value = Math.max(0, Math.min(canvasH - duckHeight.value, duckY.value))
console.log(`鸭子新位置: (${duckX.value}, ${duckY.value})`) console.log(`鸭子新位置: (${duckX.value}, ${duckY.value})`)
} }
@ -330,10 +439,27 @@ const handleTouchEnd = () => {
showGuideElements.value = false showGuideElements.value = false
// //
showDuck.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) => { const startDrag = (e) => {
console.log('开始拖拽', e) console.log('开始拖拽', e)
@ -343,9 +469,10 @@ const startDrag = (e) => {
initCanvas() initCanvas()
} }
// // 使 rpx px
duckX.value = 50 duckRpx.value.x = 100 // 100rpx 50px (iPhone 6/7/8)
duckY.value = 50 duckRpx.value.y = 100
updateDuckPosition()
showDuck.value = true showDuck.value = true
// //
@ -413,6 +540,12 @@ onUnmounted(() => {
canvas-id="dragDuckCanvas" canvas-id="dragDuckCanvas"
id="dragDuckCanvas" id="dragDuckCanvas"
class="drag-canvas" class="drag-canvas"
:style="{
left: canvasRect.left + 'px',
top: canvasRect.top + 'px',
width: canvasRect.width + 'px',
height: canvasRect.height + 'px'
}"
@touchstart="handleTouchStart" @touchstart="handleTouchStart"
@touchmove="handleTouchMove" @touchmove="handleTouchMove"
@touchend="handleTouchEnd" @touchend="handleTouchEnd"
@ -514,10 +647,6 @@ onUnmounted(() => {
.drag-canvas { .drag-canvas {
position: absolute; position: absolute;
left: 0;
top: 800px;
width: 375px;
height: 300px;
z-index: 100; z-index: 100;
pointer-events: auto; pointer-events: auto;
} }