Sug*_*uge 1 html javascript css
我的 web 项目需要div在鼠标滚轮时将鼠标位置周围的元素缩放为锚点,我的灵感来自 @Tatarize 在Zoom in a point (using scale and translate) 中的回答,但我无法准确地实现它,它无法围绕鼠标位置进行缩放和平移,有人可以帮忙吗?
window.onload = function() {
const STEP = 0.05;
const MAX_SCALE = 10;
const MIN_SCALE = 0.01;
const red = document.getElementById('red');
const yellow = red.parentNode;
let scale = 1;
yellow.onmousewheel = function (event) {
event.preventDefault();
let mouseX = event.clientX - yellow.offsetLeft - red.offsetLeft;
let mouseY = event.clientY - yellow.offsetTop - red.offsetTop;
const factor = event.wheelDelta / 120;
const oldScale = scale;
scale = scale + STEP * factor;
scale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));
const scaleChanged = scale - oldScale;
const offsetX = -(mouseX * scaleChanged);
const offsetY = -(mouseY * scaleChanged);
console.log(offsetX, offsetY);
red.style.transform = 'translate(' + offsetX + 'px, ' + offsetY + 'px)' + 'scale(' + scale + ')';
}
}Run Code Online (Sandbox Code Playgroud)
.yellow {
background-color: yellow;
width: 400px;
height: 200px;
}
.red {
background-color: red;
width: 100px;
height: 50px;
}Run Code Online (Sandbox Code Playgroud)
<div class="yellow">
<div id="red" class="red"></div>
</div>Run Code Online (Sandbox Code Playgroud)
真的很不可思议,我真的做到了。
window.onload = () => {
const STEP = 0.99;
const MAX_SCALE = 5;
const MIN_SCALE = 0.01;
const red = document.getElementById("red");
const yellow = red.parentNode;
let scale = 1;
const rect = red.getBoundingClientRect();
const originCenterX = rect.x + rect.width / 2;
const originCenterY = rect.y + rect.height / 2;
yellow.onwheel = (event) => {
event.preventDefault();
const factor = event.deltaY;
// If current scale is equal to or greater than MAX_SCALE, but you're still zoom in it, then return;
// If current scale is equal to or smaller than MIN_SCALE, but you're still zoom out it, then return;
// Can not use Math.max and Math.min here, think about it.
if ((scale >= MAX_SCALE && factor < 0) || (scale <= MIN_SCALE && factor > 0)) return;
const scaleChanged = Math.pow(STEP, factor);
scale *= scaleChanged;
const rect = red.getBoundingClientRect();
const currentCenterX = rect.x + rect.width / 2;
const currentCenterY = rect.y + rect.height / 2;
const mousePosToCurrentCenterDistanceX = event.clientX - currentCenterX;
const mousePosToCurrentCenterDistanceY = event.clientY - currentCenterY;
const newCenterX = currentCenterX + mousePosToCurrentCenterDistanceX * (1 - scaleChanged);
const newCenterY = currentCenterY + mousePosToCurrentCenterDistanceY * (1 - scaleChanged);
// All we are doing above is: getting the target center, then calculate the offset from origin center.
const offsetX = newCenterX - originCenterX;
const offsetY = newCenterY - originCenterY;
// !!! Both translate and scale are relative to the original position and scale, not to the current.
red.style.transform = 'translate(' + offsetX + 'px, ' + offsetY + 'px)' + 'scale(' + scale + ')';
}
}Run Code Online (Sandbox Code Playgroud)
.yellow {
background-color: yellow;
width: 200px;
height: 100px;
margin-left: 50px;
margin-top: 50px;
position: absolute;
}
.red {
background-color: red;
width: 200px;
height: 100px;
position: absolute;
}Run Code Online (Sandbox Code Playgroud)
<div class="yellow">
<div id="red" class="red"></div>
</div>Run Code Online (Sandbox Code Playgroud)