将鼠标滚轮滚动添加到 Konva JS Stage,并在最外层对象的开始和结束处使用锚点

Add Mouse Wheel Scrolling to Konva JS Stage with Anchor at beginning and end of outermost objects

我正在开发一个允许鼠标滚轮在 Konva JS canvas 阶段滚动的项目。目标是模仿可以用 DIV 完成的传统 CSS 溢出滚动。我认为我正在做的事情的问题与扩展舞台有关。

为了简化这个问题,我创建了一个演示,展示缩放舞台时会发生什么。理想情况下,图像的底部将锚定到舞台的底部,就像滚动到此 SO 页面或任何网站的底部一样(一旦到达底部,它就会停止)。

滚动演示时,您会注意到图像并没有停在舞台底部,而是一直滚动过去。

var stageWidth = window.innerWidth;
var stageHeight = 300;
var viewportPadding = 10;
var stage = new Konva.Stage({
  x: 0,
  y: 0,
    container: 'container',
    width: stageWidth,
    height: stageHeight
});
var zoom = .5;
stage.scaleX(zoom);
stage.scaleY(zoom);
stage.draw();

var layer = new Konva.Layer();
var background = new Konva.Rect({
  x: 0,
  y: 0,
  fill: 'red',
    width: stageWidth,
    height: stageHeight,
});


var img = new Image();

img.onload = function() {
  var imageWidth = stageWidth - (viewportPadding * 2);
   var ratio = imageWidth / this.naturalWidth;
   var imageHeight = this.naturalHeight * ratio;
    var floorImage = new Konva.Image({
      x: viewportPadding,
        y: viewportPadding,
        image: img,
        width: imageWidth,
        height: imageHeight,
    });
    layer.add(floorImage);
    
    // update height of background
    background.height(imageHeight + (viewportPadding * 2));
    stage.draw();
};

img.src = 'https://dspncdn.com/a1/media/originals/fa/06/eb/fa06ebac2b188e309cff600400d34e41.jpg';

layer.add(background);
stage.add(layer);
stage.draw();




stage.on('wheel', function(e) {
  var deltaX = e.evt.deltaX;
  var deltaY = e.evt.deltaY;
  var scrollStep = Math.abs(deltaY * 1);

  // Scrolling up
    if (deltaY < 0) {
      var yPos = layer.y() + scrollStep;

      if (yPos > 0) {
       yPos = 0;
      }

      layer.y(yPos);
      layer.batchDraw();

  // Scrolling down
    } else if (deltaY > 0) {
      var yPos = layer.y() - scrollStep;
     var remainingDistance = background.height() - stage.height();
    
      if (yPos < -remainingDistance) {
        yPos = -remainingDistance;
      }

      layer.y(yPos);
      layer.batchDraw();
    }
});
html,body {
  margin:0;
}

#container {
  border: 2px solid red;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
<script src="https://unpkg.com/konva@4.0.17/konva.min.js"></script>
  <title>JS Bin</title>
</head>
<body>
  <div id="container"></div>
</body>
</html>

你只需要根据舞台的比例调整剩余滚动:

var remainingDistance = background.height() - stage.height() / stage.scaleY();

var stageWidth = window.innerWidth;
var stageHeight = 300;
var viewportPadding = 10;
var stage = new Konva.Stage({
  x: 0,
  y: 0,
    container: 'container',
    width: stageWidth,
    height: stageHeight
});
var zoom = 0.5;
stage.scaleX(zoom);
stage.scaleY(zoom);
stage.draw();

var layer = new Konva.Layer();
var background = new Konva.Rect({
  x: 0,
  y: 0,
  fill: 'red',
    width: stageWidth,
    height: stageHeight,
});


var img = new Image();

img.onload = function() {
  var imageWidth = stageWidth - (viewportPadding * 2);
   var ratio = imageWidth / this.naturalWidth;
   var imageHeight = this.naturalHeight * ratio;
    var floorImage = new Konva.Image({
      x: viewportPadding,
        y: viewportPadding,
        image: img,
        width: imageWidth,
        height: imageHeight,
    });
    layer.add(floorImage);
    
    // update height of background
    background.height(imageHeight + (viewportPadding * 2));
    stage.draw();
};

img.src = 'https://dspncdn.com/a1/media/originals/fa/06/eb/fa06ebac2b188e309cff600400d34e41.jpg';

layer.add(background);
stage.add(layer);
stage.draw();




stage.on('wheel', function(e) {
  var deltaX = e.evt.deltaX;
  var deltaY = e.evt.deltaY;
  var scrollStep = Math.abs(deltaY * 1);

  // Scrolling up
    if (deltaY < 0) {
      var yPos = layer.y() + scrollStep;

      if (yPos > 0) {
       yPos = 0;
      }

      layer.y(yPos);
      layer.batchDraw();

  // Scrolling down
    } else if (deltaY > 0) {
      var yPos = layer.y() - scrollStep;
     var remainingDistance = background.height() - stage.height() / stage.scaleY();
    
      if (yPos < -remainingDistance) {
        yPos = -remainingDistance;
      }

      layer.y(yPos);
      layer.batchDraw();
    }
});
html,body {
  margin:0;
}

#container {
  border: 2px solid red;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
<script src="https://unpkg.com/konva@4.0.17/konva.min.js"></script>
  <title>JS Bin</title>
</head>
<body>
  <div id="container"></div>
</body>
</html>