如何获取 CSS 3D 转换画布的画布相对鼠标位置? [英] How to get a canvas relative mouse position of a CSS 3D transformed canvas?
问题描述
只是为了好玩,我试图在 3D 转换的画布上绘画.我写了一些代码,它有点工作
const m4 = twgl.m4;[...document.querySelectorAll('canvas')].forEach((canvas) => {const ctx = canvas.getContext('2d');让计数 = 0;canvas.addEventListener('mousemove', (e) => {const pos = getElementRelativeMousePosition(e, canvas);ctx.fillStyle = hsl((count++ % 10)/10, 1, 0.5);ctx.fillRect(pos.x - 1, pos.y - 1, 3, 3);});});函数 getElementRelativeMousePosition(e, elem) {const pos = convertPointFromPageToNode(elem, e.pageX, e.pageY);返回 {x: pos[0],y:位置[1],};}函数 hsl(h, s, l) {return `hsl(${h * 360 | 0},${s * 100 | 0}%,${l * 100 | 0}%)`;}函数 convertPointFromPageToNode(elem, pageX, pageY) {const mat = m4.inverse(getTransformationMatrix(elem));返回 m4.transformPoint(mat, [pageX, pageY, 0]);};函数 getTransformationMatrix(elem) {让矩阵 = m4.identity();让 currentElem = elem;while (currentElem !== undefined &¤tElem !== currentElem.ownerDocument.documentElement) {const style = window.getComputedStyle(currentElem);const localMatrix = parseMatrix(style.transform);矩阵 = m4.multiply(localMatrix, 矩阵);currentElem = currentElem.parentElement;}const w = elem.offsetWidth;const h = elem.offsetHeight;让我 = 4;让左 = +无穷大;让顶部 = +无穷大;for (让 i = 0; i <4; ++i) {const p = m4.transformPoint(matrix, [w * (i & 1), h * ((i & 2) >> 1), 0]);left = Math.min(p[0], left);顶部 = Math.min(p[1], 顶部);}const rect = elem.getBoundingClientRect()document.querySelector('p').textContent =`${w}x${h}`;矩阵 = m4.multiply(m4.translation([window.pageXOffset + rect.left - 左,window.pageYOffset + rect.top - 顶部,0]), 矩阵);返回矩阵;}函数 parseMatrix(str) {如果(str.startsWith('matrix3d(')){return str.substring(9, str.length - 1).split(',').map(v => parseFloat(v.trim()));} else if (str.startsWith('matrix(')) {const m = str.substring(7, str.length - 1).split(',').map(v => parseFloat(v.trim()));返回 [m[0], m[1], 0, 0,m[2], m[3], 0, 0,0, 0, 1, 0,m[4], m[5], 0, 1,]} else if (str == 'none') {返回 m4.identity();}throw new Error('未知格式');}
canvas {显示:块;背景:黄色;变换:比例(0.75);}#c1 {边距:20px;背景:红色;变换:translateX(-50px);显示:内联块;}#c2 {边距:20px;背景:绿色;变换:旋转(45度);显示:内联块;}#c3 {边距:20px;背景:蓝色;显示:内联块;}#c4 {位置:绝对;顶部:0;背景:青色;变换:translateX(-250px)旋转(55度);显示:内联块;}#c5 {背景:洋红色;变换:翻译(50px);显示:内联块;}#c6 {背景:粉红色;变换:旋转(45度);显示:内联块;}
<p>富</p><div id="c1"><div id="c2"><div id="c3"><canvas></canvas>
<div id="c4"><div id="c5"><div id="c6"><canvas></canvas>