你如何放大特定点(没有画布)?

und*_*ned 2 javascript image zoom absolute

目标很简单,使用鼠标滚轮,放大到特定点(鼠标所在的位置).这意味着在缩放后,鼠标将与图片大致相同的位置.

缩放后鼠标保持位置的示例 (纯粹是说明性的,我不在乎你是否使用海豚,鸭子或麦当娜的形象)

我不想使用画布,到目前为止我尝试过这样的事情:

HTML

<img src="whatever">
Run Code Online (Sandbox Code Playgroud)

JS

function zoom(e){
    var deltaScale = deltaScale || -e.deltaY / 1000;
    var newScale = scale + deltaScale;
    var newWidth = img.naturalWidth * newScale;
    var newHeight = img.naturalHeight * newScale;
    var x = e.pageX;
    var y = e.pageY;
    var newX = x * newWidth / img.width;
    var newY = y * newHeight / img.height;
    var deltaX = newX - x;
    var deltaY = newY - y;
    setScale(newScale);
    setPosDelta(-deltaX,-deltaY);
}

function setPosDelta(dX, dY) {
    var imgPos = getPosition();
    setPosition(imgPos.x + dX, imgPos.y + dY);
}

function getPosition() {
    var x = parseFloat(img.style.left);
    var y = parseFloat(img.style.top);
    return {
        x: x,
        y: y
    }
}

function setScale(n) {
    scale = n;
    img.width = img.naturalWidth * n;
    img.height = img.naturalHeight * n;
}
Run Code Online (Sandbox Code Playgroud)

这是什么尝试做的是计算x,y坐标海豚的眼睛之前之后变焦,并计算这两个点之间的距离后,从substracts其左,上位置,以纠正变焦移位,无特别成功.

变焦发生自然地将图像向右和向下延伸,因此校正尝试向左拉回到顶部,以便将鼠标保持在那该死的海豚眼上!但它肯定没有.

告诉我,代码/数学有什么问题?考虑到除了画布之外我找不到任何解决方案,我觉得这个问题不是太宽泛.

谢谢!

[编辑]重要

CSS转换顺序很重要,如果您按照选定的答案,请确保先按顺序排序,然后再按比例排序.CSS变换向后(从右到左)执行,因此首先处理缩放,然后处理翻译.

fma*_*dee 7

这是一个缩放到一个点的实现.该代码使用CSS 2D 变换,包括在单击和拖动时平移图像.这很容易,因为规模没有变化.

缩放时的技巧是首先使用当前比例(换句话说:将其除以当前比例)来标准化偏移量,然后将新比例应用于该标准化偏移.这使光标准确地保持在与刻度无关的位置.

var scale = 1,
    panning = false,
    xoff = 0,
    yoff = 0,
    start = {x: 0, y: 0},
    doc = document.getElementById("document");

function setTransform() {
  doc.style.transform = "translate(" + xoff + "px, " + yoff + "px) scale(" + scale + ")";
}

doc.onmousedown = function(e) {
  e.preventDefault();
  start = {x: e.clientX - xoff, y: e.clientY - yoff};    
  panning = true;
}

doc.onmouseup = function(e) {
  panning = false;
}

doc.onmousemove = function(e) {
  e.preventDefault();         
  if (!panning) {
    return;
  }
  xoff = (e.clientX - start.x);
  yoff = (e.clientY - start.y);
  setTransform();
}

doc.onwheel = function(e) {
    e.preventDefault();
    // take the scale into account with the offset
    var xs = (e.clientX - xoff) / scale,
        ys = (e.clientY - yoff) / scale,
        delta = (e.wheelDelta ? e.wheelDelta : -e.deltaY);

    // get scroll direction & set zoom level
    (delta > 0) ? (scale *= 1.2) : (scale /= 1.2);

    // reverse the offset amount with the new scale
    xoff = e.clientX - xs * scale;
    yoff = e.clientY - ys * scale;

    setTransform();          
}
Run Code Online (Sandbox Code Playgroud)
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

#document {
  width: 100%;
  height: 100%;
  transform-origin: 0px 0px;
  transform: scale(1) translate(0px, 0px);
}
Run Code Online (Sandbox Code Playgroud)
<div id="document">
  <img style="width: 100%"
       src="http://lorempixel.com/output/animals-q-c-1920-1920-9.jpg" />
</div>
    
Run Code Online (Sandbox Code Playgroud)