最近想制做一个在散开的纸面画画的效果,纸面会按必定角度倾斜,就像下面这样↓ css
transform: roate(-2deg)
在电脑端很容易实现,鼠标事件中有offsetX Y
,可以得到鼠标位置相对于目标节点的位置,能够简单理解为相对于元素左上角的坐标。得到坐标后,再按坐标绘制到Canvas上,一切就OK了,不过到了移动端就有点麻烦了。css3
移动端touch事件有如下几个属性git
然而就是没有offsetX Y
,怎么办,本身模拟试试?github
pageX Y
offsetTop left
计算元素左上角的顶点位置vertex
代码以下:canvas
function getVertexPosition(el) {
let currentTarget = el
let top = 0
let left = 0
while (currentTarget !== null) {
top += currentTarget.offsetTop
left += currentTarget.offsetLeft
currentTarget = currentTarget.offsetParent
}
return { top, left }
}
let vertex = getVertexPosition(canvas)
canvas.addEventListener('touchmove',(e)=>{
let offsetX = e.pageX-vertex.left
let offsetY = e.pageX-vertex.top
})
复制代码
在页面没有设置任何transform
属性的状况下,这个代码是生效的,能得到正确的坐标点。 然而若是父元素或目标元素有任何transform
属性,坐标就会错误,好比本文中的canvas元素,设置了transform: roate(-2deg)
,坐标就发生了偏移。 随后搜索了一下是否有相似的解决方案,结果都是这样的代码,都不能对transform
元素生效。缓存
偏移缘由是由于变换后,元素的坐标轴已经改变了,而咱们获得的坐标仍是变换前的坐标,天然而然就发生错误了。 bash
transform
相关属性let style = window.getComputedStyle(el)
console.log(style)
复制代码
得到的transform
属性以下wordpress
transform: "matrix(0.999391, -0.0348995, 0.0348995, 0.999391, 0, 0)"
transformBox: "view-box"
transformOrigin: "160px 240px"
transformStyle: "flat"
复制代码
关于transform:matrix
以及如何理解查看张鑫旭的文章。 简而言之,就是transform
属性都是经过transform:matrix
进行矩阵计算获得坐标的。性能
解析transform属性 因为这里涉及到矩阵运算,须要引入math.jsui
let transform = style.transform
let transformOrigin = style.transformOrigin
let origin = { x: 0, y: 0 }
let matrix = math.ones([3, 3])
if (transform !== 'none') {
let originArray = transformOrigin.split(' ')
origin.x = parseInt(originArray[0])
origin.y = parseInt(originArray[1]) //矩阵的坐标变化是基于变换中心得。
let matrixString = transform.match(/\(([^)]*)\)/)[1]
let stringArray = matrixString.split(',')
let temp = []
stringArray.forEach((value) => {
temp.push(parseFloat(value.trim()))
})
temp = [
[temp[0], temp[2], temp[4]],
[temp[1], temp[3], temp[5]],
[0, 0, 1],
]
matrix = math.inv(temp) //进行逆矩阵
} else {
matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
}
复制代码
这样咱们就获得了原变换矩阵的逆矩阵和变换中心,就能将触摸点正确的还原到原坐标系了
计算
function computPosition(obj){
let { matrix, origin, vertex: { top, left },ponit:{x,y} } = obj
x = x - left - origin.x
y = y - top - origin.y
let result = math.multiply(matrix, [x, y, 1])
x = result[0] + origin.x
y = result[1] + origin.y
return (x,y)
}
复制代码
getComputStyle()
和得到顶点坐标有较大性能消耗,最好将相关参数缓存起来 实际代码实现见此github.com/Geylnu/touc…W3C给出了没有为touch事件添加offsetX Y
的缘由github.com/w3c/touch-e…