使用EaselJS的平移缩放行为

问题描述 投票:0回答:1

我在合并平移/缩放行为时遇到了一些麻烦,还可以使用EaselJS在画布上拖动一些形状。

我只希望将鼠标悬停在形状上,但是如果我将鼠标悬停在舞台上(即不在形状上),那么我希望能够平移舞台。无论“缩放”级别如何(通过鼠标滚轮更改),此行为都必须保持一致。

我已经阅读过:How to stop the event bubble in easljs?这表明无论我单击形状还是空白空间,都会触发阶段mousedown事件,因此最好创建一个“背景”形状来捕获我的mousedown事件,形状不正确。

此小提琴是我设置的方式:https://jsfiddle.net/hmcleay/mzheuLbg/

var stage = new createjs.Stage("myCanvas");
console.log('stage.scaleX: ', stage.scaleX);
console.log('stage.scaleY: ', stage.scaleY);

function addCircle(r,x,y){
    var g=new createjs.Graphics().beginFill("#ff0000").drawCircle(0,0,r);
    var s=new createjs.Shape(g)
    s.x=x;
    s.y=y;

  s.on('pressmove',  function(ev) {
    var localpos = stage.globalToLocal(ev.stageX, ev.stageY)
    s.x = localpos.x;
    s.y = localpos.y;
    stage.update();
    });

    stage.addChild(s);
    stage.update();
}

// create a rectangle 'background' Shape object to cover the stage (to allow for capturing mouse drags on anything except other shapes). 
bg = new createjs.Shape();
bg.graphics.beginFill("LightGray").drawRect(10, 10, stage.canvas.width - 20, stage.canvas.height - 20); //deliberately smaller for debugging purposes (easier to see if it moves). 
bg.x = 0;
bg.y = 0;
stage.addChild(bg);
stage.update();


//create a rectangle frame to represent the position of the stage. 
stageborder = new createjs.Shape();
stageborder.graphics.beginStroke("Black").drawRect(0, 0, stage.canvas.width, stage.canvas.height);
stageborder.x = 0;
stageborder.y = 0;
stage.addChild(stageborder);
stage.update();


// MOUSEWHEEL ZOOM LISTENER - anywhere on canvas.
var factor
canvas.addEventListener("wheel", function(e){
    if(Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)))>0){
        factor = 1.1;
    } else {
        factor = 1/1.1;
  }

  var local = stage.globalToLocal(stage.mouseX, stage.mouseY);
  stage.regX=local.x;
  stage.regY=local.y;
    stage.x=stage.mouseX;
    stage.y=stage.mouseY;   

    stage.scaleX = stage.scaleX * factor;
    stage.scaleY = stage.scaleY * factor;

  //re-size the 'background' shape to be the same as the canvas size.
  bg.graphics.command.w = bg.graphics.command.w / factor;
  bg.graphics.command.h = bg.graphics.command.h / factor;

  // re-position the 'background' shape to it's original position of (0,0) in the global space.  
  var localzero = stage.globalToLocal(0, 0);

  bg.x = localzero.x;
  bg.y = localzero.y;

    stage.update();
});

// listener to add circles to the canvas. 
canvas.addEventListener('dblclick', function(){
var localpos = stage.globalToLocal(stage.mouseX, stage.mouseY);
    addCircle(10, localpos.x, localpos.y);
});

bg.addEventListener("mousedown", function(ev1){
  // purpose of this listener is to be able to capture drag events on the 'background' to pan the whole stage. 
  // it needs to be a separate 'shape' object (rather than the stage itself), so that it doesn't fire when other shape objects are drag-moved around on the stage. 

  // get the initial positions of the stage, background, and mousedown. 
  var mousedownPos0 = {'x': ev1.stageX, 'y': ev1.stageY};
  var stagePos0 = {'x': stage.x, 'y': stage.y};
  var bgPos0 = {'x': bg.x, 'y': bg.y};

  bg.addEventListener('pressmove', function(ev2){
    //logic is to pan the stage, which will automatically pan all of it's children (shapes). 
    // except we want the 'background' shape to stay where it is, so we need to offset it in the opposite direction to the stage movement so that it stays where it is. 
    stageDelta = {'x': ev2.stageX - mousedownPos0.x, 'y': ev2.stageY - mousedownPos0.y};

    //adjust the stage position
    stage.x = stagePos0.x + stageDelta.x;
    stage.y = stagePos0.y + stageDelta.y;

    // return the 'background' shape to global(0,0), so that it doesn't move with the stage. 
    var localzero = stage.globalToLocal(0,0);
    bg.x = localzero.x;
    bg.y = localzero.y;

    stage.update();


  });

});

灰色框是我的背景形状。我故意使它比画布略小,以便可以看到它的位置(对调试有用)。双击画布上的任意位置以添加一些红色圆圈。如果拖动一个圆,它只会移动该圆。

如果在圆圈之间的灰色“背景”区域上拖动,它将移动整个舞台(因此将移动属于该舞台的所有子形状)。由于灰色背景也是舞台的一部分,因此它希望随其一起移动。因此,我提供了一些代码,始终将灰色框返回到其开始位置。黑色边框代表“舞台”的位置,我刚刚添加了它以帮助可视化舞台的位置。

鼠标滚轮缩放控件基于以下问题的答案:EaselJS - broken panning on zoomed image

类似于拖动平移,缩放时,我必须调整灰色“背景”框的大小和位置,以使其在画布上的相同位置呈现。但是,它并不能完全停留在我想要的位置上……当我缩小时,它似乎会朝着画布的左上角爬行。我花了很多时间来尝试诊断这种行为,却找不到原因。我怀疑这可能与四舍五入有关..但我真的不确定。

谁能解释为什么我放大和缩小时我的灰色框不能保持静止?

[另一种方法是抓取用于捕获不在“适当”形状上的鼠标按下事件的“背景”形状。而是可以使用“舞台”鼠标按下事件,但如果鼠标悬停在“形状”上,则可以防止其移动舞台。这是处理这种行为的更好方法吗?有什么建议可以防止它移动舞台吗?

谢谢,休

javascript canvas createjs easeljs
1个回答
0
投票

确定]

通常,在最后寻求帮助后,我设法解决了这个问题。

此问题是由于将背景形状(灰色矩形)比画布小10px所致,因此我可以更清楚地看到其位置(以帮助调试)。具有讽刺意味的是,这种抵消导致了问题。应用缩放时,10像素偏移未转换为“本地”空间。通过使灰色矩形在(0,0)处的图形位置具有与画布相同的宽度和高度,问题就消失了!

希望这在某个时间点对某人有用。

干杯,休

© www.soinside.com 2019 - 2024. All rights reserved.