2012-09-11 11 views
8

Sto avendo alcuni problemi con il ridimensionamento di un contenitore ad un punto fisso.
Nel mio caso sto provando a ridimensionare (zoomare) uno stage sul cursore del mouse.Scaling ad un punto fisso nel KineticJS

Qui è un modo per farlo con puro tela: http://phrogz.net/tmp/canvas_zoom_to_cursor.html (come discusso in Zoom Canvas to Mouse Cursor)

proprio non riesco a capire come applicare la stessa logica mentre si utilizza l'API KineticJS.

codice di esempio:

var position = this.stage.getUserPosition(); 
var scale = Math.max(this.stage.getScale().x + (0.05 * (scaleUp ? 1 : -1)), 0); 
this.stage.setScale(scale); 
// Adjust scale to position...? 
this.stage.draw(); 

risposta

16

Dopo un sacco di lottare e cercare e cercare, con la punta fornita dal @Eric Rowell e il codice pubblicato nel SO interrogare Zoom in on a point (using scale and translate) ho finalmente ottenuto lo zoom in e fuori di un determinato punto di lavoro utilizzando KineticJS.

Ecco una DEMO lavoro.

Ed ecco il codice:

var ui = { 
    stage: null, 
    scale: 1, 
    zoomFactor: 1.1, 
    origin: { 
     x: 0, 
     y: 0 
    }, 
    zoom: function(event) { 
     event.preventDefault(); 
     var evt = event.originalEvent, 
      mx = evt.clientX /* - canvas.offsetLeft */, 
      my = evt.clientY /* - canvas.offsetTop */, 
      wheel = evt.wheelDelta/120; 
     var zoom = (ui.zoomFactor - (evt.wheelDelta < 0 ? 0.2 : 0)); 
     var newscale = ui.scale * zoom; 
     ui.origin.x = mx/ui.scale + ui.origin.x - mx/newscale; 
     ui.origin.y = my/ui.scale + ui.origin.y - my/newscale; 

     ui.stage.setOffset(ui.origin.x, ui.origin.y); 
     ui.stage.setScale(newscale); 
     ui.stage.draw(); 

     ui.scale *= zoom; 
    } 
}; 

$(function() { 
    var width = $(document).width() - 2, 
     height = $(document).height() - 5; 
    var stage = ui.stage = new Kinetic.Stage({ 
     container: 'container', 
     width: width, 
     height: height 
    }); 
    var layer = new Kinetic.Layer({ 
     draggable: true 
    }); 
    var rectX = stage.getWidth()/2 - 50; 
    var rectY = stage.getHeight()/2 - 25; 

    var box = new Kinetic.Circle({ 
     x: 100, 
     y: 100, 
     radius: 50, 
     fill: '#00D200', 
     stroke: 'black', 
     strokeWidth: 2, 
    }); 

    // add cursor styling 
    box.on('mouseover', function() { 
     document.body.style.cursor = 'pointer'; 
    }); 
    box.on('mouseout', function() { 
     document.body.style.cursor = 'default'; 
    }); 

    layer.add(box); 
    stage.add(layer); 

    $(stage.content).on('mousewheel', ui.zoom); 
});​ 
+0

Grazie! Questo funziona. Scusa per la risposta in ritardo. – Skarbo

+0

Hey, grazie, funziona bene ma ho molti livelli, quindi non posso impostare i layer come "trascinabili". quindi ho impostato lo stage trascinabile. Quando sposto il tavolino come trascinamento, non riesco a zoomare sul punto di zoom desiderato. Devo ricalcolare qualcosa come il conteggio delle fasi x e y ma non riesco a raggiungerlo. Potresti aiutarmi? – magirtopcu

+0

@ user1645941 Si prega di condividere alcuni esempi di lavoro del problema si sta trattando (forse come un [violino] (http://jsfiddle.net/)) e farò quello che posso per aiutare. –

3

È necessario compensare la fase così che è punto centrale è posizionata al punto fisso. Ecco un esempio, perché il punto centrale dello stage è impostato in modo predefinito nell'angolo superiore sinistro dell'area di disegno. Diciamo che il tuo palcoscenico è largo 600px e alto 400px e vuoi che lo stage si ingrandisca dal centro. Si avrebbe bisogno di fare questo:

var stage = new Kinetic.Stage({ 
    container: 'container', 
    width: 600, 
    height: 400, 
    offset: [300, 200] 
}; 
3

aggiornato demo @juan.facorro s' per scalare la forma, invece di scena

jsFiddle

var ui = { 
    stage: null, 
    box: null, 
    scale: 1, 
    zoomFactor: 1.1, 
    zoom: function(event) { 
     event.preventDefault(); 
     var evt = event.originalEvent, 
      mx = evt.offsetX, 
      my = evt.offsetY, 
      wheel = evt.wheelDelta/120; //n or -n 
     var zoom = (ui.zoomFactor - (evt.wheelDelta < 0 ? 0.2 : 0)); 
     var newscale = ui.scale * zoom; 

     var origin = ui.box.getPosition(); 
     origin.x = mx - (mx - origin.x) * zoom; 
     origin.y = my - (my - origin.y) * zoom; 

     ui.box.setPosition(origin.x, origin.y); 
     ui.box.setScale(newscale); 
     ui.stage.draw(); 

     ui.scale *= zoom; 
    } 
}; 

$(function() { 
    var width = $(document).width() - 2, 
     height = $(document).height() - 5; 
    var stage = ui.stage = new Kinetic.Stage({ 
     container: 'container', 
     width: width, 
     height: height 
    }); 
    var layer = new Kinetic.Layer(); 
    var rectX = stage.getWidth()/2 - 50; 
    var rectY = stage.getHeight()/2 - 25; 

    var box = ui.box = new Kinetic.Circle({ 
     x: 100, 
     y: 100, 
     radius: 50, 
     fill: '#00D200', 
     stroke: 'black', 
     strokeWidth: 2, 
     draggable: true 
    }); 

    // add cursor styling 
    box.on('mouseover', function() { 
     document.body.style.cursor = 'pointer'; 
    }); 
    box.on('mouseout', function() { 
     document.body.style.cursor = 'default'; 
    }); 

    layer.add(box); 
    stage.add(layer); 

    $(stage.content).on('mousewheel', ui.zoom); 
}); 
2

La demo di cui sopra funziona solo se le coordinate X e Y del palco sono 0. Se eg lo stage è trascinabile, cambierà queste coordinate durante il trascinamento, quindi è necessario includerle nel calcolo dell'offset. Ciò può essere ottenuto da loro sottraendo gli offset tela:

jsfiddle

zoom: function(event) { 
    event.preventDefault(); 
    var evt = event.originalEvent, 
     mx = evt.offsetX - ui.scale.getX(), 
     my = evt.offsetY - ui.scale.getY(), 
    var zoom = (ui.zoomFactor - (evt.wheelDelta < 0 ? 0.2 : 0)); 
    var newscale = ui.scale * zoom; 

    var origin = ui.box.getPosition(); 
    origin.x = mx - (mx - origin.x) * zoom; 
    origin.y = my - (my - origin.y) * zoom; 

    ui.box.setPosition(origin.x, origin.y); 
    ui.box.setScale(newscale); 
    ui.stage.draw(); 

    ui.scale *= zoom; 
}