KineticJS中的缩放和平移

9
有没有一种方法可以使用KineticJS在画布上进行缩放和平移?我发现这个库kineticjs-viewport,但只是想知道是否有其他方法来实现这一点,因为这个库似乎使用了很多额外的库,我不确定哪些是绝对必要的来完成工作。
或者,我甚至可以接受围绕感兴趣的区域画一个矩形,然后缩放到那个特定的区域。如何实现这一点? JSFiddle示例将是很棒的!
7个回答

25
您可以简单地将.setDraggable("draggable")添加到层中,只要鼠标指针下有对象,就可以拖动它。您可以添加一个大的透明rect来使所有内容都可拖动。缩放可以通过设置图层的比例来实现。在这个示例中,我通过鼠标滚轮来控制它,但它只是一个函数,您可以传递您想要缩放的数量(正数表示放大,负数表示缩小)。以下是代码:
var stage = new Kinetic.Stage({
    container: "canvas",
    width: 500,
    height: 500
});

var draggableLayer = new Kinetic.Layer();
draggableLayer.setDraggable("draggable");

//a large transparent background to make everything draggable
var background = new Kinetic.Rect({
    x: -1000,
    y: -1000,
    width: 2000,
    height: 2000,
    fill: "#000000",
    opacity: 0
});

draggableLayer.add(background);


//don't mind this, just to create fake elements
var addCircle = function(x, y, r){
  draggableLayer.add(new Kinetic.Circle({
        x: x*700,
        y: y*700,
        radius: r*20,
        fill: "rgb("+ parseInt(255*r) +",0,0)"
    })
  );
}

var circles = 300
while (circles) {
  addCircle(Math.random(),Math.random(), Math.random())
  circles--;
}

var zoom = function(e) {
  var zoomAmount = e.wheelDeltaY*0.001;
  draggableLayer.setScale(draggableLayer.getScale().x+zoomAmount)
  draggableLayer.draw();
}

document.addEventListener("mousewheel", zoom, false)

stage.add(draggableLayer)

http://jsfiddle.net/zAUYd/


这个很好用,但在IE9中除外。你有任何想法为什么吗?调试控制台也没有抛出任何错误... - Legend
看起来如果我使用 e.wheelDelta 而不是 e.wheelDeltaY,它就可以工作了。你有什么想法吗? - Legend
1
我认为IE使用deltaY。鼠标滚轮缩放只是一个例子,如果您打算保留它,则应该使用一个shim来弥补浏览器实现之间的差异,例如https://github.com/cobbweb/jquery-mousewheel。 - methodofaction
太棒了!再次感谢你的帮助。 - Legend
1
很好,但有一个问题,如果该图层是可拖动的,则该图层上的对象尽管已设置为可拖动,但不能被拖动。您知道是否有办法仅将背景设置为可拖动以进行平移吗? - allenhwkim
1
这个 jsfiddle:http://jsfiddle.net/zAUYd/ 不再工作,无论是在 FF 还是 Chrome 上。你能更新一下吗? - Basj

4
这是一个非常快速简单的图层缩放和平移实现。如果您有更多需要同时平移和缩放的图层,建议将它们分组,然后将on("click")应用于该组以获得相同的效果。 http://jsfiddle.net/renyn/56/ 如果不明显,左上角的浅蓝色正方形被点击以进行缩放,底部左侧的粉色正方形被点击以左右平移。
编辑:请注意,这当然可以更改为支持"mousedown"或其他事件,并且我不认为为了使它们更加平滑而不能实现变换为Kinetic.Animations。

太棒了!这正是我想要的。我尝试在舞台上使用鼠标事件,但运气不太好,所以我很想问你 - 你能否在支持mousedown事件和支持更平滑的动画方面给我指导? - Legend
我不建议将它们应用于整个舞台,这样会捕捉所有的鼠标事件而不加区分。尝试像我一样将它们分配给单独的形状。我不确定你需要什么样的指导,但Kinetic的API和教程非常有帮助。 - michael.orchard
我并不感到惊讶,5.0.0和5.0.1与4.0.2有很多破坏性的变化。 - michael.orchard
1
你能否更新你回答中提到的 jsfiddle?它在 Firefox 和 Chrome 上已经无法工作了。 - Basj

3

3

我实际上编写了kineticjs-viewport插件。很高兴听到你对它感兴趣。

它的作用不仅仅是拖拽,它还可以进行缩放和性能优化的裁剪。超出裁剪区域的元素根本就不会被渲染,因此即使您有一个包含大量对象的巨大图层,也可以获得良好的渲染性能。

这正是我使用它的用例。例如,在通过较小的视口区域查看的大型RTS地图中,类似于星际争霸。

希望这可以帮到您。


1
你能否添加一个使用视口的示例? - PiTheNumber
1
存储库中有一个演示页面:https://kineticjs-viewport.googlecode.com/git/demo.html - Andrew Lundgren

2

这些答案似乎不能与KineticJS 5.1.0一起使用。这些主要是因为缩放函数的签名更改而无法工作:

 stage.setScale(newscale); --> stage.setScale({x:newscale,y:newscale});

然而,以下解决方案似乎适用于KineticJS 5.1.0:

JSFiddle:http://jsfiddle.net/rpaul/ckwu7u86/3/


2

今天我在使用Kinetic时发现了一个Stack Overflow问题,可能会对您有所帮助。

我知道这应该写成评论的形式,但是我没有足够的声望来进行评论,无论如何,希望这可以帮到您。


1

不幸的是,设置状态或图层可拖动会阻止不可拖动的对象。 Duopixel的缩放解决方案很好,但我宁愿将其设置为舞台级别,而不是图层级别。

这是我的解决方案

var stage = new Kinetic.Stage({
    container : 'container',
    width: $("#container").width(),
    height: $("#container").height(),
});
var layer = new Kinetic.Layer();

//layer.setDraggable("draggable");
var center = { x:stage.getWidth() / 2, y: stage.getHeight() / 2};

var circle = new Kinetic.Circle({
    x: center.x-100,
    y: center.y,
    radius: 50,
    fill: 'green',
    draggable: true
});
layer.add(circle);
layer.add(circle.clone({x: center.x+100}));

// zoom by scrollong
document.getElementById("container").addEventListener("mousewheel", function(e) {
  var zoomAmount = e.wheelDeltaY*0.0001;
  stage.setScale(stage.getScale().x+zoomAmount)
  stage.draw();
  e.preventDefault();
}, false)

// pan by mouse dragging on stage
stage.on("dragstart dragmove", function(e) {window.draggingNode = true;});
stage.on("dragend", function(e) { window.draggingNode = false;});
$("#container").on("mousedown", function(e) {
    if (window.draggingNode) return false;
    if (e.which==1) {
        window.draggingStart = {x: e.pageX, y: e.pageY, stageX: stage.getX(), stageY: stage.getY()};
        window.draggingStage = true;
    }
});
$("#container").on("mousemove", function(e) {
    if (window.draggingNode || !window.draggingStage) return false;
    stage.setX(window.draggingStart.stageX+(e.pageX-window.draggingStart.x));
    stage.setY(window.draggingStart.stageY+(e.pageY-window.draggingStart.y));
    stage.draw();
});
$("#container").on("mouseup", function(e) { window.draggingStage = false } );

stage.add(layer);

http://jsfiddle.net/bighostkim/jsqJ2/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接