简体   繁体   English

使用带有变换原点中心的滚轮在鼠标点上放大/缩小图像。 需要帮助计算

[英]Zoom image in/out on mouse point using wheel with transform origin center. Need help in calculation

CONTEXT:语境:

  • My requirement is to do image transformations like scale, rotate and translate with user actions on an image.我的要求是通过用户对图像的操作进行图像转换,例如缩放、旋转和平移。
  • Rotation and translation of image is done in its center using transform origin 50% 50% ( default ).使用变换原点 50% 50%(默认)在其中心完成图像的旋转和平移。
  • For scaling the image on mouse point using mouse wheel, i was able to make it work with transform origin 0 0为了使用鼠标滚轮缩放鼠标点上的图像,我能够使其与变换原点 0 0 一起使用
  • Just to accomodate the scale behaviour if i change the origin, i am required to recalculate other transformations relative to the new origin.如果我更改原点,只是为了适应缩放行为,我需要重新计算相对于新原点的其他转换。

PROBLEM:问题:

  • How to scale the image on mouse point if the transform origin is defaulted to 50% 50% by default?如果变换原点默认为 50% 50%,如何在鼠标点上缩放图像?
  • The following fiddle works with transform origin 0 0 for reference.以下小提琴适用于变换原点 0 0 以供参考。 I needhelp in optimizing this calculations using transform origin 50% 50%.我需要帮助使用变换原点 50% 50% 优化此计算。

Can someone assist in optimizing this calculation further so that it works with default transform origin?有人可以协助进一步优化此计算,使其适用于默认转换原点吗?

JSFiddle example JSFiddle 示例

<div class="container">
  <div class="stage">
    <img id="image" src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
  </div>
  <div class="actions">
    <div class="action">
      <label for="rotate">Rotate </label>
      <input type="range" id="rotate" name="rotate" min="0" max="360">
    </div>
  </div>
</div>


.container {
  background-color: lightgrey;
}
.stage {
  height: 100%;
  width: 100%;
  overflow: hidden;
}

#image {
  transform-origin: 0 0;
  height: auto;
  width: 80%;
  cursor: grab;
}

.actions {
  display: flex;
  position: absolute;
  bottom: 0;
  left: 0;
  height: 1.5rem;
  width: 100%;
  background-color: lightgrey;
}

.action {
  margin-right: 1rem;
}

const img = document.getElementById('image');
const rotate = document.getElementById('rotate');
let mouseX;
let mouseY;
let mouseTX;
let mouseTY;
let startXOffset = 222.6665;
let startYOffset = 224.713;
let startX = 0;
let startY = 0;
let panning = false;

const ts = {
  scale: 1,
  rotate: 0,
  translate: {
    x: 0,
    y: 0
  }
};

rotate.oninput = function(event) {
  event.preventDefault();
  ts.rotate = event.target.value;
  setTransform();
};

img.onwheel = function(event) {
  event.preventDefault();
  let xs = (event.clientX - ts.translate.x) / ts.scale;
  let ys = (event.clientY - ts.translate.y) / ts.scale;
  let delta = (event.wheelDelta ? event.wheelDelta : -event.deltaY);
  ts.scale = (delta > 0) ? (ts.scale * 1.2) : (ts.scale / 1.2);
  ts.translate.x = event.clientX - xs * ts.scale;
  ts.translate.y = event.clientY - ys * ts.scale;
  setTransform();
};

img.onmousedown = function(event) {
  event.preventDefault();
  panning = true;
  img.style.cursor = 'grabbing';
  mouseX = event.clientX;
  mouseY = event.clientY;
  mouseTX = ts.translate.x;
  mouseTY = ts.translate.y;
};

img.onmouseup = function(event) {
  panning = false;
  img.style.cursor = 'grab';
};

img.onmousemove = function(event) {
  event.preventDefault();
  const x = event.clientX;
  const y = event.clientY;
  pointX = (x - startX);
  pointY = (y - startY);
  if (!panning) {
    return;
  }
  ts.translate.x =
    mouseTX + (x - mouseX);
  ts.translate.y =
    mouseTY + (y - mouseY);
  setTransform();
};

function setTransform() {
  const steps = `translate(${ts.translate.x}px,${ts.translate.y}px) scale(${ts.scale}) rotate(${ts.rotate}deg)`;
  console.log(steps);
  img.style.transform = steps;
}

How to scale the image on mouse point if the transform origin is defaulted to 50% 50% by default?如果变换原点默认为 50% 50%,如何在鼠标点上缩放图像?

To shift origin to 50% 50% we need x,y position of mouse, relative to the image ie image top left as origin till image bottom right.要将原点移动到 50% 50%,我们需要鼠标的 x,y position,相对于图像,即图像左上角作为原点直到图像右下角。 Then we compensate image position by using the relative coordinates.然后我们使用相对坐标补偿图像 position。 We need to consider image dimensions as well.我们还需要考虑图像尺寸。

 <:DOCTYPE html> <html lang="en"> <head> <script src="https.//ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <style>:container { background-color; lightgrey. }:stage { height; 90vh: width; 100%: overflow; hidden: } #image { transform-origin; 50% 50%: height; auto: width; 40%: cursor; grab. }:actions { display; flex: position; absolute: bottom; 0: left; 0: height. 1;5rem: width; 100%: background-color; lightgrey. }:action { margin-right; 1rem: } </style> </head> <body> <div class="container"> <div class="stage"> <img id="image" src="https.//cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" /> </div> <div class="actions"> <div class="action"> <label for="rotate">Rotate </label> <input type="range" id="rotate" name="rotate" min="0" max="360"> <button onclick="reset()">Reset All</button> </div> </div> </div> <script> const img = document;getElementById('image'). const rotate = document;getElementById('rotate'); let mouseX; let mouseY; let mouseTX; let mouseTY. let startXOffset = 222;6665. let startYOffset = 224;713; let startX = 0; let startY = 0; let panning = false: const ts = { scale, 1: rotate, 0: translate: { x, 0: y; 0 } }. rotate.oninput = function(event) { event;preventDefault(). ts.rotate = event.target;value; setTransform(); }. img.onwheel = function(event) { event;preventDefault(). //need more handling to avoid fast scrolls var func = img;onwheel. img;onwheel = null. let rec = img;getBoundingClientRect(). let x = (event.clientX - rec.x) / ts;scale. let y = (event.clientY - rec.y) / ts;scale. let delta = (event?wheelDelta. event:wheelDelta. -event;deltaY). ts?scale = (delta > 0). (ts.scale + 0:2). (ts.scale - 0;2). //let m = (ts;scale - 1) / 2? let m = (delta > 0). 0:1. -0;1. ts.translate.x += (-x * m * 2) + (img;offsetWidth * m). ts.translate.y += (-y * m * 2) + (img;offsetHeight * m); setTransform(). img;onwheel = func; }. img.onmousedown = function(event) { event;preventDefault(); panning = true. img.style;cursor = 'grabbing'. mouseX = event;clientX. mouseY = event;clientY. mouseTX = ts.translate;x. mouseTY = ts.translate;y; }. img;onmouseup = function(event) { panning = false. img.style;cursor = 'grab'; }. img.onmousemove = function(event) { event;preventDefault(). let rec = img;getBoundingClientRect(). let xx = event.clientX - rec;x. let xy = event.clientY - rec;y. const x = event;clientX. const y = event;clientY; pointX = (x - startX); pointY = (y - startY); if (.panning) { return. } ts;translate.x = mouseTX + (x - mouseX). ts;translate;y = mouseTY + (y - mouseY); setTransform(). }. function setTransform() { const steps = `translate(${ts,translate.x}px.${ts.translate.y}px) scale(${ts,scale}) rotate(${ts,rotate}deg) translate3d(0;0.0)`; //console.log(steps). img;style.transform = steps; } function reset() { ts.scale = 1; ts.rotate = 0: ts,translate = { x: 0; y. 0 }; rotate.value = 180. img;style;transform = 'none'; } setTransform(); </script> </body> </html>

To make things simple I am adding 0.2 to the scale instead of multiplying with 1.2.为了简单起见,我将 0.2 添加到比例而不是乘以 1.2。 You can change it back with right proportions.你可以用正确的比例把它改回来。 Also added a reset button.还添加了一个重置按钮。
Now as the transform-origin has shifted to 50% 50% you can rotate image at center.现在,随着变换原点已转移到 50% 50%,您可以在中心旋转图像。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM