【问题标题】:Scaling IMAGE around pointer in Konva在 Konva 中围绕指针缩放图像
【发布时间】:2021-11-12 17:08:03
【问题描述】:

无法解决这个问题并让它发挥作用。尝试在 Konva 上转置此示例,但无法使其与舞台内图层内的图像一起使用。 我要重现的示例是“相对于指针位置的缩放阶段”示例。

https://konvajs.org/docs/sandbox/Zooming_Relative_To_Pointer.html

任何帮助都会赢得赞誉。

【问题讨论】:

  • 你到底想做什么?你尝试了什么?
  • 我有一篇关于这个主题的未发表的博客文章,所以在下面的回答中包含了胆量。这是一个常见问题,我得到了答复,所以现在提供以避免延误,并为以后可能会提出这个问题的其他人提供帮助。

标签: konvajs react-konva konva


【解决方案1】:

从任意点(例如鼠标位置)进行缩放的技巧是要了解您必须重新定位舞台以保持鼠标下方的点一致。我在下面提供了有效的 vanilla JS sn-p 来说明这一点。胆量基于 Konva 文档站点上的原始演示,只是在代码中添加了更多的 cmets。一旦解释了技术的基础,翻译成 React 应该不难。

灰色区域是画布,粉色矩形是舞台。请注意,我们从放置在画布中的舞台开始,只是为了表明舞​​台可以像任何其他对象一样移动。

舞台有一个点图案,以帮助展示演示中的效果。该解决方案适用于任何层、形状或图像的布局(根据 OP 问题)。请注意,形状本身不需要单独处理 - 缩放会应用于舞台。

在舞台上的任意位置移动鼠标并滚动以查看缩放效果,注意粉色舞台矩形的左上角是如何随着缩放移动的。现在取消选中该复选框以关闭舞台位置调整 - 请注意,现在缩放不再尊重鼠标位置,因为舞台位置没有被移动。

因此,我们已经说明了在缩放期间有必要同情地移动舞台,但是我们如何知道要移动的量?

要知道的提示是,您需要在应用新比例之前获取鼠标位置在舞台上的绝对距离,然后将新比例应用于舞台,然后使用计算出的距离 * 新比例来计算新的舞台位置。查看 sn-p 中的 stage.on('wheel') 事件以获取工作代码。

另见密码笔here

// Making the stage
let stage = new Konva.Stage({
  container: "container1", 
  width: $('#container1').width(),  
  height: $('#container1').height(), 
  draggable: true,
  x: 40,
  y: 60
});


// Make the layer
let layer = new Konva.Layer();

// make a rect to fill stage to show where it is.
let rect = new Konva.Rect({
  x:0, 
  y: 0,
  width: $('#container1').width(),  
  height: $('#container1').height(), 
  fill: 'magenta',
  opacity: 0.3
})
layer.add(rect);

let grid = {w: $('#container1').width(), h: $('#container1').height()}, 
    gridStep = 40, 
    mouseCircleRadius = 80, 
    circles = [], 
    dotRadius = 10;

// Make the grid of circles
for (let i = gridStep; i < grid.w; i = i + gridStep ){
  for (let j = gridStep; j < grid.h; j = j + gridStep ){
    let c = new Konva.Circle({ x: i, y: j, radius: dotRadius, fill: 'cyan'})
    circles.push(c);
    layer.add(c)
  }
}

// Add layer to stage
stage.add(layer)

stage.on('mousemove', function (e) {
  var pointer = stage.getPointerPosition();
  
  // show the pointer and stage positions for illustration
  $('#trace').html('Pointer.x = ' + pointer.x + ' stage.x() = ' + stage.x())

});
// this is the scale factor to be applied at each step.
var scaleBy = 1.01; 

// this is the event that fires when the mouse wheel spins.
stage.on('wheel', (e) => {
    e.evt.preventDefault();
  
    // note the old scale to be used when deciding the current stage position
    var oldScale = stage.scaleX();

    // note the mouse pointer position relative to the stage at current scale 
    var pointer = stage.getPointerPosition();

    // calculate the mouse pointer position at scale = 1.
    // pointer.x is relative to the canvas - not affected by stage scale,
    // stage.x() is the poistion of the stage on the canvas. 
    //  This gives the distance from the pointer to the  
    var mousePointTo = {
        x: (pointer.x - stage.x()) / oldScale,
        y: (pointer.y - stage.y()) / oldScale,
    };

    // Calculate the new scale - slightly different calc for zoom in versus zoom out, as you would expect.
    var newScale = (e.evt.deltaY > 0 ? oldScale * scaleBy : oldScale / scaleBy);

    // Apply the new scale to the stage. Note that, assuming a zoom-in op, at this point in time the shapes on the stage would 
    // seem to have jumped down + right. We will shortly 'move' the stage left+up to counter this effect.  
    stage.scale({ x: newScale, y: newScale });

    // To do that we have to calculate what the position of the stage must be relative to the mouse pointer position at the new scale. 
    // Note - remove the 'if' for your live code, the checkbox is for illustration only.
  if ($('#fixstagepos').prop('checked')){
    var newPos = {
        x: pointer.x - mousePointTo.x * newScale,
        y: pointer.y - mousePointTo.y * newScale,
    };    
    // and apply the new position to the stage. Again in the case of a zoom-in op this has the effect of moving the stage left + up, countering the apparent movement 
    // caused by the change in scale. 
    stage.position(newPos);
  }

});
.container {
  width: 800px;
  height: 400px;
  background-color: silver;
  margin: 5px;
}
#trace {
  max-height: 200px;
  overflow-y: scroll;
  font-family: 'Courier'
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/konva@8/konva.min.js"></script>
<p id="info">Grey is the canvas and the pink rect shows the stage position. The stage is intitially positioned at {x: 40, y: 60} and can be dragged.</p>
<p>Move mouse over stage and scroll to zoom in & out. Use checkbox to see what happens without stage pos correction. </p>
<p>Apply correction to stage position <input id='fixstagepos' type='checkbox' checked='1' /></p> 
<div id='container1' class='container'>
</div>

  <p id='trace'></p>

【讨论】:

    猜你喜欢
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多