簡體   English   中英

多點觸控縮放錯誤 Canvas 縮放縮放

[英]Scaling bug with multi-touch Canvas scale with pinch zoom

使用來自 Konvajs.org 的示例代碼作為基礎 ( https://konvajs.org/docs/sandbox/Multi-touch_Scale_Stage.html ),我添加了一個大的 SVG 到一個層 (4096 x 3444) 來試驗縮放 /在這種情況下,基於向量的 map、base64 編碼為 SVG 的泛。 最初的印象很好,但是在測試過程中,我遇到了一個奇怪的錯誤,即在緊要關頭,map 的視圖會捕捉到 map 上的不同位置,而不是我所關注的區域。

這是代碼(地圖 base64 代碼由於長度而被刪除):

// by default Konva prevent some events when node is dragging
// it improve the performance and work well for 95% of cases
// we need to enable all events on Konva, even when we are dragging a node
// so it triggers touchmove correctly
Konva.hitOnDragEnabled = true;

var width = window.innerWidth;
var height = window.innerHeight;

var stage = new Konva.Stage({
  container: 'container',
  width: width,
  height: height,
  draggable: true,
});

var layer = new Konva.Layer();

var triangle = new Konva.RegularPolygon({
  x: 190,
  y: stage.height() / 2,
  sides: 3,
  radius: 80,
  fill: 'green',
  stroke: 'black',
  strokeWidth: 4,
});

var circle = new Konva.Circle({
  x: 380,
  y: stage.height() / 2,
  radius: 70,
  fill: 'red',
  stroke: 'black',
  strokeWidth: 4,
});

let bg = new Konva.Image({
    width: 4096,
    height: 3444
});
layer.add(bg);

var image = new Image();
image.onload = function() {
    bg.image(image);
    layer.draw();
};

image.src = 'data:image/svg+xml;base64,...';

function getDistance(p1, p2) {
  return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}

function getCenter(p1, p2) {
  return {
    x: (p1.x + p2.x) / 2,
    y: (p1.y + p2.y) / 2,
  };
}
var lastCenter = null;
var lastDist = 0;

stage.on('touchmove', function (e) {
  e.evt.preventDefault();
  var touch1 = e.evt.touches[0];
  var touch2 = e.evt.touches[1];

  if (touch1 && touch2) {
    // if the stage was under Konva's drag&drop
    // we need to stop it, and implement our own pan logic with two pointers
    if (stage.isDragging()) {
      stage.stopDrag();
    }

    var p1 = {
      x: touch1.clientX,
      y: touch1.clientY,
    };
    var p2 = {
      x: touch2.clientX,
      y: touch2.clientY,
    };

    if (!lastCenter) {
      lastCenter = getCenter(p1, p2);
      return;
    }
    var newCenter = getCenter(p1, p2);

    var dist = getDistance(p1, p2);

    if (!lastDist) {
      lastDist = dist;
    }

    // local coordinates of center point
    var pointTo = {
      x: (newCenter.x - stage.x()) / stage.scaleX(),
      y: (newCenter.y - stage.y()) / stage.scaleX(),
    };

    var scale = stage.scaleX() * (dist / lastDist);

    stage.scaleX(scale);
    stage.scaleY(scale);

    // calculate new position of the stage
    var dx = newCenter.x - lastCenter.x;
    var dy = newCenter.y - lastCenter.y;

    var newPos = {
      x: newCenter.x - pointTo.x * scale + dx,
      y: newCenter.y - pointTo.y * scale + dy,
    };

    stage.position(newPos);

    lastDist = dist;
    lastCenter = newCenter;
  }
});

stage.on('touchend', function () {
  lastDist = 0;
  lastCenter = null;
});


layer.add(triangle);
layer.add(circle);
stage.add(layer);

我不確定這是由於圖像尺寸過大和/或 canvas 還是來自 Konvas.js 的示例代碼中的固有缺陷。 這已經在 iPad Pro、iPhone X 和 11、Android Pixel 3、5 和 6 Pro 的 2 款機型上進行了測試,結果相同。

這里以codepen上的代碼為例: https://codepen.io/mr-jose/pen/WNXgbdG

任何幫助將不勝感激,謝謝!

我遇到了同樣的問題,發現它是由舞台的拖動功能引起的。 每次if (stage.isDragging())評估為 true 時,都會發生跳躍。

對我來說,有效的是在捏合縮放時將 draggable 設置為 false,然后在觸摸端設置為 true。

stage.on('touchmove', function (e) {
  ...
  if (touch1 && touch2) {
    stage.draggable(false);
    ....
  }
});

stage.on('touchend', function (e) {
  ...
  stage.draggable(true);
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM