javascript 在 KineticJS 中缩放和平移
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12633554/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Zoom and Pan in KineticJS
提问by Legend
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.
有没有一种方法可以使用 KineticJS 在画布上缩放和平移?我找到了这个库kineticjs-viewport,但只是想知道是否还有其他方法可以实现这一点,因为这个库似乎使用了太多额外的库,并且不确定哪些库对于完成工作是绝对必要的。
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!
或者,我什至愿意在感兴趣的区域周围绘制一个矩形并放大该特定区域的想法。关于如何实现这一目标的任何想法?一个 JSFiddle 示例会很棒!
回答by methodofaction
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:
您可以简单地添加.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)
回答by michael.orchard
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.
这是缩放和平移图层的非常快速和简单的实现。如果您有更多需要同时平移和缩放的图层,我建议将它们分组,然后将 on("click") 应用于该组以获得相同的效果。
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.
编辑:请注意,这当然可以更改为支持“鼠标按下”或其他事件,我不明白为什么不能将转换实现为 Kinetic.Animations 以使它们更平滑。
回答by v1r00z
this is what i have done so far.. hope it will help you.
这是我到目前为止所做的..希望它会帮助你。
回答by Andrew Lundgren
I actually wrote kineticjs-viewport. I'm happy to hear you were interested in it.
我实际上写了 kineticjs-viewport。我很高兴听到您对此感兴趣。
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.
这就是我的用例。例如,您可以通过较小的视口区域查看大型 RTS 地图——想想星际争霸。
I hope this helps.
我希望这有帮助。
回答by Razan Paul
These answers seems not to work with the KineticJS 5.1.0. These do not work mainly for the signature change of the scale function:
这些答案似乎不适用于 KineticJS 5.1.0。这些主要不适用于缩放函数的签名更改:
stage.setScale(newscale); --> stage.setScale({x:newscale,y:newscale});
However, the following solution seems to work with the KineticJS 5.1.0:
但是,以下解决方案似乎适用于 KineticJS 5.1.0:
JSFiddle: http://jsfiddle.net/rpaul/ckwu7u86/3/
JSFiddle:http: //jsfiddle.net/rpaul/ckwu7u86/3/
回答by Richard Otvos
As I was working with Kinetic today I found a SO questionthat might interest you.
当我今天与 Kinetic 合作时,我发现了一个您可能感兴趣的问题。
I know it would be better as a comment, but I don't have enough rep for that, anyway, I hope that helps.
我知道作为评论会更好,但我没有足够的代表,无论如何,我希望这会有所帮助。
回答by allenhwkim
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.
不幸的是,设置状态或图层可拖动可防止对象不可拖动。Duopixel 的缩放解决方案很好,但我宁愿将其设置为舞台级别,而不是图层级别。
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);