Zoom and Pan in KineticJS

2019-02-01 07:06发布

Is there a way one could zoom and pan on a canvas using KineticJS? I found this library kineticjs-viewport, but just wondering if there is any other way of achieving this because this library seems to be using so many extra libraries and am not sure which ones are absolutely necessary to get the job done.

Alternatively, I am even open to the idea of drawing a rectangle around the region of interest and zooming into that one particular area. Any ideas on how to achieve this? A JSFiddle example would be awesome!

7条回答
淡お忘
2楼-- · 2019-02-01 07:38

As I was working with Kinetic today I found a SO question that might interest you.

I know it would be better as a comment, but I don't have enough rep for that, anyway, I hope that helps.

查看更多
欢心
3楼-- · 2019-02-01 07:40

Here's a very quick and simple implementation of zooming and panning a layer. If you had more layers which would need to pan and zoom at the same time, I would suggest grouping them and then applying the on("click")s to that group to get the same effect.

http://jsfiddle.net/renyn/56/

If it's not obvious, the light blue squares in the top left are clicked to zoom in and out, and the pink squares in the bottom left are clicked to pan left and right.

Edit: As a note, this could of course be changed to support "mousedown" or other events, and I don't see why the transformations couldn't be implemented as Kinetic.Animations to make them smoother.

查看更多
叼着烟拽天下
4楼-- · 2019-02-01 07:55

this is what i have done so far.. hope it will help you.

http://jsfiddle.net/v1r00z/ZJE7w/

查看更多
叛逆
5楼-- · 2019-02-01 07:57

You can simply add .setDraggable("draggable") to a layer and you will be able to drag it as long as there is an object under the cursor. You could add a large, transparent rect to make everything draggable. The zoom can be achieved by setting the scale of the layer. In this example I'm controlling it though the mousewheel, but it's simply a function where you pass the amount you want to zoom (positive to zoom in, negative to zoom out). Here is the code:

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/

查看更多
Anthone
6楼-- · 2019-02-01 08:00

Unfortunately, setting state or layer draggable prevents objects not draggable. Duopixel's zooming solution is good, but I would rather set it for stage level, not layer level.

Her is my solution

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/

查看更多
狗以群分
7楼-- · 2019-02-01 08:01

I actually wrote kineticjs-viewport. I'm happy to hear you were interested in it.

It is actually intended for more than merely dragging. It also allows zooming and performance-focused clipping. The things outside of the clip region aren't rendered at all, so you can have great rendering performance even if you have an enormous layer with a ton of objects.

That's the use case I had. For example, a large RTS map which you view via a smaller viewport region -- think Starcraft.

I hope this helps.

查看更多
登录 后发表回答