2012-09-11 12 views
8

Mam problemy z przeskalowaniem kontenera do ustalonego punktu.
W moim przypadku próbuję przeskalować (przybliżyć) scenę do kursora myszy.Skalowanie do stałego punktu w KineticJS

Oto sposób zrobić z czystego płótna: http://phrogz.net/tmp/canvas_zoom_to_cursor.html (omówione w Zoom Canvas to Mouse Cursor)

Po prostu nie mogę się dowiedzieć się, jak zastosować tę samą logikę podczas korzystania z API KineticJS.

Przykładowy kod:

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(); 

Odpowiedz

16

Po wielu walczy i szuka i próbuje za pomocą końcówki dostarczone przez @Eric Rowell i kodu zamieszczonych w SO pytanie Zoom in on a point (using scale and translate) I wreszcie dostał powiększania i pomniejszania o stałym punkt pracy przy użyciu KineticJS.

Oto działa DEMO.

A oto kod:

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

Dziękujemy! To działa. Przepraszam za późną odpowiedź. – Skarbo

+0

Hej dziękuję, działa to dobrze, ale mam wiele warstw, więc nie mogę ustawić warstw jako "przeciągalne". dlatego ustawiam etap przeciągany. Kiedy przesuwam scenę jako przeciąganie, nie mogę przybliżyć do pożądanego punktu przybliżenia. Muszę ponownie przeliczyć cokolwiek jako etapy x i y, ale nie mogłem tego osiągnąć. Czy możesz mi pomóc? – magirtopcu

+0

@ user1645941 Proszę, podziel się roboczym przykładem problemu, z którym masz do czynienia (może jako [skrzypce] (http://jsfiddle.net/)) i zrobię co w mojej mocy, aby pomóc. –

3

trzeba zrównoważyć scenę tak, że jest to punkt środkowy jest umieszczony w punkcie stałym. Oto przykład, ponieważ centralnym punktem sceny jest domyślny lewy górny róg płótna. Załóżmy, że Twoja scena ma 600px szerokości i 400px wysokości, a chcesz, aby na scenie zbliżyć się od środka. trzeba by to zrobić:

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

aktualizowane demo @juan.facorro „s skalować kształt zamiast etapie

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

Demo powyżej działa tylko jeśli współrzędne X i Y etapu to 0. Jeśli np etap jest przeciągalny, zmieni współrzędne podczas przeciągania, więc należy je uwzględnić w obliczeniach przesunięcia. Można to osiągnąć poprzez odjęcie ich od offsetu płótnie:

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; 
}