2012-09-28 7 views
9

Gibt es eine Möglichkeit, mit KineticJS auf einer Leinwand zu zoomen und zu schwenken? Ich habe diese Bibliothek gefunden kineticjs-viewport, aber nur darüber nachdenken, ob es andere Möglichkeiten gibt, dies zu erreichen, weil diese Bibliothek scheint so viele zusätzliche Bibliotheken zu verwenden und bin mir nicht sicher, welche absolut notwendig sind, um die Arbeit zu erledigen.Zoomen und Schwenken in KineticJS

Alternativ bin ich sogar offen für die Idee, ein Rechteck um die Region von Interesse zu zeichnen und in diesen einen bestimmten Bereich zu zoomen. Irgendwelche Ideen, wie man das erreicht? Ein JSFiddle-Beispiel wäre großartig!

Antwort

25

Sie können einfach .setDraggable("draggable") zu einer Ebene hinzufügen, und Sie können sie ziehen, solange sich ein Objekt unter dem Cursor befindet. Sie könnten eine große, transparente rect hinzufügen, um alles ziehbar zu machen. Der Zoom kann durch Einstellen der Skalierung der Ebene erreicht werden. In diesem Beispiel steuere ich es über das Mausrad, aber es ist einfach eine Funktion, bei der Sie den zu vergrößernden Betrag übergeben (positiv zum Vergrößern, negativ zum Herauszoomen). Hier ist der 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/

+0

Das funktioniert gut außer in IE9. Hättest du eine Ahnung, warum? Die Debug-Konsole wirft auch keine Fehler ... – Legend

+0

Sieht aus wie es funktioniert, wenn ich "e.wheelDelta" anstelle von "e.wheelDeltaY" verwende. Irgendeine Idee warum? – Legend

+1

Ich denke, dass IE deltaY verwendet. Der Mausradzoom war nur ein Beispiel, wenn Sie beabsichtigen, ihn zu behalten, dann sollten Sie einen Shim verwenden, der den Unterschied in Browserimplementierungen wie https://github.com/cobbweb/jquery-mousewheel kompensiert. – Duopixel

2

Da ich heute mit Kinetic gearbeitet habe, habe ich eine SO question gefunden, die Sie interessieren könnte.

Ich weiß, es wäre besser als Kommentar, aber ich habe nicht genug rep für diese, jedenfalls hoffe ich, dass hilft.

4

Hier ist eine sehr schnelle und einfache Implementierung von Zoomen und Schwenken einer Schicht. Wenn Sie mehrere Ebenen hätten, die gleichzeitig schwenken und zoomen müssten, würde ich vorschlagen, sie zu gruppieren und dann die Ein ("click") s auf diese Gruppe anzuwenden, um den gleichen Effekt zu erzielen.

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

Wenn es nicht offensichtlich ist, werden die hellblauen Quadrate in den oberen linken geklickt und aus, und die rosaen Quadrate in den unteren linken vergrößern geklickt links und rechts zu schwenken.

Edit: Als eine Anmerkung könnte dies natürlich geändert werden, um "mousedown" oder andere Ereignisse zu unterstützen, und ich sehe nicht, warum die Transformationen nicht als Kinetic.Animations implementiert werden konnten, um sie glatter zu machen.

+0

Awesome! Das ist genau was ich will. Ich habe versucht, die Mausereignisse über eine Bühne zu verwenden, hatte aber nicht viel Glück damit, also bin ich versucht, Sie zu fragen - könnten Sie mir mehr bei der Unterstützung der Mousedown-Ereignisse und der Unterstützung einer flüssigeren Animation helfen? – Legend

+0

Ich würde nicht empfehlen, sie auf die gesamte Bühne anzuwenden, dies würde alle Mausereignisse ohne Vorurteile erfassen. Versuchen Sie, sie einzelnen Formen wie ich zuzuweisen. Ich bin mir nicht sicher, welche Anleitung Sie genau brauchen, die APIs und Tutorials für Kinetic sind jedoch sehr hilfreich. –

+0

Ich bin nicht überrascht, 5.0.0 und 5.0.1 haben viele brechende Änderungen von 4.0.2. –

1

Leider Zustand oder Schicht Einstellung ziehbar verhindert Objekte nicht ziehbar. Die Zoom-Lösung von Duopixel ist gut, aber ich würde sie lieber auf Bühnenebene und nicht auf Ebenenebene einstellen.

Her ist meine Lösung

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/

3

ich eigentlich kineticjs-Ansichtsfenster geschrieben. Ich freue mich zu hören, dass Sie daran interessiert waren.

Es ist eigentlich für mehr als nur Ziehen gedacht. Es ermöglicht auch das Zoomen und das leistungsorientierte Clipping. Die Dinge außerhalb der Clip-Region werden überhaupt nicht gerendert, so dass Sie selbst dann eine großartige Rendering-Performance haben, wenn Sie eine enorme Ebene mit einer Tonne an Objekten haben.

Das ist der Anwendungsfall, den ich hatte.Zum Beispiel eine große RTS-Karte, die Sie über eine kleinere Viewport-Region anzeigen - denken Sie an Starcraft.

Ich hoffe, das hilft.

+1

Können Sie ein Beispiel hinzufügen, wie Sie das Ansichtsfenster dafür verwenden? – PiTheNumber

+1

Es gibt eine Demoseite im Repo: https://kineticjs-viewport.googlecode.com/git/demo.html –

2

Diese Antworten scheinen mit dem KineticJS 5.1.0 nicht zu funktionieren. Diese funktionieren nicht in erster Linie für die Signatur Änderung der Skalierungsfunktion:

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

jedoch die folgende Lösung scheint mit dem KineticJS zu arbeiten 5.1.0:

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