在没有鼠标和键盘按钮的情况下放大时 Panzoom 不一致

Panzoom inconsistent when zooming in without a mouse and keyboard buttons

我已经尝试过github post

中发布的解决方案

重现步骤:

  1. 点击放大按钮两次。
  2. 缩放比例为150%时;单击缩小。

图像放大但实际上应该缩小

const element = document.querySelector('#scene');

const zoomLevels = [0.1, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.5, 3];
let currentZoomLevel = zoomLevels[4];
const text = document.querySelector('#text');

let panZoomController = panzoom(element, {
  beforeWheel: function(e) {
    // allow wheel-zoom Disabled
    return true;
  }
});

const setText = (input) => {
  text.innerText = input;
}

const zoom = () => {
  const isSmooth = false;
  const scale = currentZoomLevel;
  if (scale) {
    const transform = panZoomController.getTransform();
    const deltaX = transform.x;
    const deltaY = transform.y;
    const offsetX = scale + deltaX;
    const offsetY = scale + deltaY;

    if (isSmooth) {
      panZoomController.smoothZoom(0, 0, scale);
    } else {
      panZoomController.zoomTo(offsetX, offsetY, scale);
    }
  }
};


const zoomIn = () => {
  const idx = zoomLevels.indexOf(currentZoomLevel);

  // If next element exists
  if (typeof zoomLevels[idx + 1] !== 'undefined') {
    currentZoomLevel = zoomLevels[idx + 1];
  }

  if (currentZoomLevel === 1) {
    panZoomController.moveTo(0, 0);
    panZoomController.zoomAbs(0, 0, 1);
  } else {
    zoom();
  }
  setText(currentZoomLevel * 100 + '%');

};

const zoomOut = () => {
  const idx = zoomLevels.indexOf(currentZoomLevel);

  //if previous element exists
  if (typeof zoomLevels[idx - 1] !== 'undefined') {
    currentZoomLevel = zoomLevels[idx - 1];
  }


  if (currentZoomLevel === 1) {
    panZoomController.moveTo(0, 0);
    panZoomController.zoomAbs(0, 0, 1);
  } else {
    zoom();
  }

  setText(currentZoomLevel * 100 + '%');
};
div {
  overflow: hidden;
  border: 3px solid red
}
<script src="https://unpkg.com/panzoom@8.1.0/dist/panzoom.min.js"></script>

<body>
  <div>
    <img id="scene" src="https://www.probytes.net/wp-content/uploads/2018/01/5-1.png">
  </div>

  <br/>
  <button onclick="zoomOut()">-</button>
  <span id="text">100%</span>
  <button onclick="zoomIn()">+</button>
</body>

您在这里将相对比例误认为是绝对比例。 zoomAbs() 使用的是绝对缩放级别,而 zoom() 函数使用的是 zoomTo(),后者采用相对缩放级别。

因此,描述你的整个过程:

 - Initial.  Scale: 1
 - Zoom in.  Scale: 1 * 1.25 = 1.25
 - Zoom in.  Scale: 1.25 * 1.5 = 1.875
 - Zoom out. Scale: 1.875 * 1.25 = 2.344
 - Zoom out. Scale: Hard reset to 1

注意:如果您缩小不止一次,然后尝试放大,您也可以看到这种情况反过来发生。

这可以通过使用绝对比例方法 zoomAbs()(更简单)或使用当前和所需比例计算相对缩放来解决。

要做到这一点,只需替换这一行

panZoomController.zoomTo(offsetX, offsetY, scale);

panZoomController.zoomAbs(offsetX, offsetY, scale);

固定片段:

const element = document.querySelector('#scene');

const zoomLevels = [0.1, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.5, 3];
let currentZoomLevel = zoomLevels[4];
const text = document.querySelector('#text');

let panZoomController = panzoom(element, {
  beforeWheel: function(e) {
    // allow wheel-zoom Disabled
    return true;
  }
});

const setText = (input) => {
  text.innerText = input;
}

const zoom = () => {
  const isSmooth = false;
  const scale = currentZoomLevel;
  if (scale) {
    const transform = panZoomController.getTransform();
    const deltaX = transform.x;
    const deltaY = transform.y;
    const offsetX = scale + deltaX;
    const offsetY = scale + deltaY;

    if (isSmooth) {
      panZoomController.smoothZoom(0, 0, scale);
    } else {
      panZoomController.zoomAbs(offsetX, offsetY, scale);
    }
  }
};


const zoomIn = () => {
  const idx = zoomLevels.indexOf(currentZoomLevel);

  // If next element exists
  if (typeof zoomLevels[idx + 1] !== 'undefined') {
    currentZoomLevel = zoomLevels[idx + 1];
  }

  if (currentZoomLevel === 1) {
    panZoomController.moveTo(0, 0);
    panZoomController.zoomAbs(0, 0, 1);
  } else {
    zoom();
  }
  setText(currentZoomLevel * 100 + '%');

};

const zoomOut = () => {
  const idx = zoomLevels.indexOf(currentZoomLevel);

  //if previous element exists
  if (typeof zoomLevels[idx - 1] !== 'undefined') {
    currentZoomLevel = zoomLevels[idx - 1];
  }


  if (currentZoomLevel === 1) {
    panZoomController.moveTo(0, 0);
    panZoomController.zoomAbs(0, 0, 1);
  } else {
    zoom();
  }

  setText(currentZoomLevel * 100 + '%');
};
div {
  overflow: hidden;
  border: 3px solid red
}
<script src="https://unpkg.com/panzoom@8.1.0/dist/panzoom.min.js"></script>

<body>
  <div>
    <img id="scene" src="https://www.probytes.net/wp-content/uploads/2018/01/5-1.png">
  </div>

  <br/>
  <button onclick="zoomOut()">-</button>
  <span id="text">100%</span>
  <button onclick="zoomIn()">+</button>
</body>