問題
當前需要開發彈窗拖拽移動功能,在通過mousemove計算坐標點位時,出現計算后點位始終與鼠標坐標存在一定比例差異,并且距離初始未知越遠差距越大。
移動計算公式
這里需要被移動塊與初始點擊點做相對偏移移動, 所以可知移動前后鼠標所在點與被移動塊的相對距離不變
x1, y1 移動塊初始坐標
px1, py1 鼠標按下初始坐標
x2, y2 移動后移動塊坐標
px2, px2 鼠標移動后坐標
px1 - x1 = px2 - x2
py1 - y1 = py2 - y2
求移動后的塊坐標
x2 = x1 + px2 - px1
y2 = y1 + py2 - py1
debug
- 將計算邏輯提取,放置到無任何依賴的純環境中, 計算結果正常, 未存在比例差問題
- 判斷問題與調用環境有關, 切換不同組件,上下文依舊, 所以與全局配置有關
- 切換不同屏幕比例,比例差不同,所以問題與屏幕適配有關
- 發現當前環境中使用的 transform:scale 做屏幕適配
解決
這里出現的問題是,通過mousemove獲取的 e.pageX, e.pageY 是相對于頁面的尺寸,不受全局樣式 transform:scale 的影響, 而實際dom定位是經過比例縮放的,所以始終存在一個比例差問題,且鼠標移動距離越遠,差距越大。
這里需要將 e.pageX, e.pageY 也做比例尺轉換,在做坐標計算。最終得出正確結果
x2 = x1 + px2*scale - px1
y2 = y1 + py2 *scale - py1
function onMouseDown (e) {
// 轉換初始坐標
prePosition.value = ratePosition({
startX: e.pageX,
startY: e.pageY
})
ctx.emit('blockMouseDown', { ...prePosition.value })
document.addEventListener('mousemove', throttledMove)
document.addEventListener('mouseup', onMouseUp)
}
function onMouseMove (e) {
// 轉換移動坐標
const { startX, startY } = prePosition.value
const { pageX, pageY } = ratePosition({
pageX: e.pageX,
pageY: e.pageY
})
...
}
// 轉換函數
function ratePosition (position = {}) {
const rate = getSacleRate() // 獲取當前比例尺
return Object.entries(position).reduce((acc, [prop, value]) => {
return {
...acc,
[prop]: value / rate
}
}, {})
}