2012-09-28 9 views
9

C'è un modo per ingrandire e eseguire panoramiche su una tela utilizzando KineticJS? Ho trovato questa libreria kineticjs-viewport, ma mi chiedo solo se c'è un altro modo per ottenere questo perché questa libreria sembra utilizzare tante librerie extra e non sono sicuro di quali siano assolutamente necessarie per portare a termine il lavoro.Zoom e panoramica in KineticJS

In alternativa, sono persino aperto all'idea di disegnare un rettangolo attorno alla regione di interesse e di eseguire lo zoom in quella particolare area. Qualche idea su come raggiungere questo obiettivo? Un esempio di JSFiddle sarebbe fantastico!

risposta

25

È possibile semplicemente aggiungere .setDraggable("draggable") a un livello e sarà possibile trascinarlo finché c'è un oggetto sotto il cursore. È possibile aggiungere un grande rect trasparente per rendere trascinabile tutto. Lo zoom può essere ottenuto impostando la scala del livello. In questo esempio lo sto controllando anche se la rotellina del mouse, ma è semplicemente una funzione in cui si passa la quantità che si desidera ingrandire (positivo per ingrandire, negativo per ridurre). Ecco il codice:

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

Funziona alla grande tranne in IE9. Avresti qualche idea sul perché? La console di debug non genera alcun errore ... – Legend

+0

Sembra che funzioni se uso 'e.wheelDelta' invece di' e.wheelDeltaY'. Qualche idea del perché? – Legend

+1

Penso che IE usi il deltaY. Lo zoom della rotellina del mouse era solo un esempio, se hai intenzione di tenerlo, dovresti usare uno shim che compensi la differenza nelle implementazioni del browser come https://github.com/cobbweb/jquery-mousewheel – Duopixel

2

Mentre stavo lavorando con Kinetic oggi ho trovato un SO question che potrebbe interessarti.

So che sarebbe meglio come commento, ma non ho abbastanza rep per questo, comunque, spero che aiuti.

4

Ecco un'implementazione molto veloce e semplice di zoom e panoramica uno strato. Se avessi più livelli che avrebbero bisogno di eseguire il pan e lo zoom contemporaneamente, ti suggerirei di raggrupparli e quindi di applicare gli on ("clic") a quel gruppo per ottenere lo stesso effetto.

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

Se non è ovvio, le piazze azzurri in alto a sinistra si fa clic per ingrandire e fuori, e le piazze rosa in basso a sinistra si fa clic per eseguire una panoramica a sinistra ea destra.

Modifica: Come nota, questo potrebbe naturalmente essere modificato per supportare "mousedown" o altri eventi e non vedo perché le trasformazioni non possano essere implementate come Kinetic.

+0

Impressionante! Questo è esattamente quello che voglio. Ho provato a utilizzare gli eventi del mouse su un palco, ma non ho avuto molta fortuna, quindi sono tentato di chiedertelo: saresti in grado di guidarmi di più nel sostenere gli eventi del film e sostenere un'animazione più fluida? – Legend

+0

Non consiglierei di applicarli a tutto lo stage, questo catturerebbe tutti gli eventi del mouse senza pregiudizi. Prova ad assegnarli a forme individuali come ho fatto io. Non sono sicuro di quali siano le indicazioni di cui hai bisogno, le API e le esercitazioni per Kinetic sono piuttosto utili. –

+0

Non sono sorpreso, 5.0.0 e 5.0.1 hanno un sacco di modifiche da 4.0.2. –

1

Sfortunatamente, modificando statali o strato impedisce trascinabili oggetti non trascinabile. La soluzione di zoom di Duopixel è buona, ma preferisco impostarla per il livello di stage, non a livello di livello.

La sua è la mia soluzione

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

ho scritto kineticjs-finestra. Sono felice di sapere che eri interessato a questo.

In realtà è destinato a qualcosa di più del semplice trascinamento. Permette anche lo zoom e il ritaglio focalizzato sulle prestazioni. Le cose al di fuori dell'area della clip non sono affatto renderizzate, quindi puoi avere grandi prestazioni di rendering anche se hai un enorme strato con una tonnellata di oggetti.

Questo è il caso d'uso che ho avuto.Ad esempio, una grande mappa RTS che si visualizza attraverso una regione viewport più piccola - pensa Starcraft.

Spero che questo aiuti.

+1

Puoi aggiungere un esempio su come usare il viewport per questo? – PiTheNumber

+1

C'è una pagina demo nel repository: https://kineticjs-viewport.googlecode.com/git/demo.html –

2

Queste risposte sembrano non funzionare con KineticJS 5.1.0. Questi non funzionano principalmente per il cambio della firma della funzione di scala:

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

Tuttavia, la seguente soluzione sembra funzionare con le KineticJS 5.1.0:

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