2012-05-29 9 views
23

Próbuję zaimplementować gesty szczypta na zoom dokładnie tak, jak w Google Maps. Obejrzałem rozmowę Stephen Woods - "Creating Responsive HTML5 Touch Interfaces” - o problemie i wykorzystałem wspomnianą technikę. Chodzi o to, aby ustawić początek transformacji elementu docelowego na (0, 0) i skalę w punkcie transformacji. Następnie przetłumaczyć obraz, aby zachować go w środku w punkcie transformacji.Szczypta, aby powiększyć za pomocą CSS3

W moim kodzie testowym skalowanie działa dobrze. Obraz jest powiększany i pomniejszany między kolejnymi tłumaczeniami. Problem polega na tym, że nie obliczam poprawnie wartości translacji. Korzystam z jQuery i Hammer.js dla zdarzeń dotykowych. Jak mogę dostosować moje obliczenia w oddzwanianiu transformacyjnym, aby obraz pozostał wyśrodkowany w punkcie transformacji?

The coffeescript (#test-resize jest div z obrazu tła)

image = $('#test-resize') 

hammer = image.hammer -> 
    prevent_default: true 
    scale_treshold: 0 

width = image.width() 
height = image.height() 
toX = 0 
toY = 0 
translateX = 0 
translateY = 0 
prevScale = 1 
scale = 1 

hammer.bind 'transformstart', (event) -> 

    toX = (event.touches[0].x + event.touches[0].x)/2 
    toY = (event.touches[1].y + event.touches[1].y)/2 

hammer.bind 'transform', (event) -> 

    scale = prevScale * event.scale 
    shiftX = toX * ((image.width() * scale) - width)/(image.width() * scale) 
    shiftY = toY * ((image.height() * scale) - height)/(image.height() * scale) 
    width = image.width() * scale 
    height = image.height() * scale 

    translateX -= shiftX 
    translateY -= shiftY 

    css = 'translateX(' + @translateX + 'px) translateY(' + @translateY + 'px) scale(' + scale + ')' 
    image.css '-webkit-transform', css 
    image.css '-webkit-transform-origin', '0 0' 

hammer.bind 'transformend',() -> 
    prevScale = scale 

Odpowiedz

19

udało mi się uzyskać jego pracy.

jsFiddle demo

W demie jsFiddle, klikając na obrazek reprezentuje gestu pinch środku w punkcie kliknięcia. Kolejne kliknięcia zwiększają współczynnik skali o stałą wartość. Aby było to użyteczne, należy znacznie częściej skalować i tłumaczyć obliczenia na zdarzeniu przekształcania (plik hammer.js zapewnia).

Kluczem do uruchomienia go było prawidłowe obliczenie współrzędnych skali względem obrazu. Użyłem event.clientX/Y, aby uzyskać współrzędne ekranu. Następujące linie przekonwertować z ekranu na współrzędne obrazu:

x -= offset.left + newX 
y -= offset.top + newY 

Następnie obliczamy nowy rozmiar obrazu i znaleźć dystans do przetłumaczenia przez. Równanie translacji pochodzi z Stephen Woods' talk.

newWidth = image.width() * scale 
newHeight = image.height() * scale 

newX += -x * (newWidth - image.width)/newWidth 
newY += -y * (newHeight - image.height)/newHeight 

Wreszcie, skalować i tłumaczyć

image.css '-webkit-transform', "scale3d(#{scale}, #{scale}, 1)"   
wrap.css '-webkit-transform', "translate3d(#{newX}px, #{newY}px, 0)" 

Mamy wszystkie nasze tłumaczenia na elemencie owijarki do zapewnienia, że ​​tłumaczyć-pochodzenie pozostaje w lewym górnym rogu naszego wizerunku.

+10

ów mojego kota! !! ?? –

+0

Drugi link jest uszkodzony. –

+0

Jest naprawdę dobry punkt od Stephena Woodsa: Czy absolutnie nic więcej w kodzie podczas transformacji z css (nie ładowanie itp.). Dużo pomógł we własnym projekcie. – Hardy

6

Pomyślnie wykorzystałem ten fragment do zmiany rozmiaru zdjęć na phonegap, używając młotka i jquery.

Jeśli kogoś interesuje, przetłumaczyłem to na JS.

function attachPinch(wrapperID,imgID) 
{ 
    var image = $(imgID); 
    var wrap = $(wrapperID); 

    var width = image.width(); 
    var height = image.height(); 
    var newX = 0; 
    var newY = 0; 
    var offset = wrap.offset(); 

    $(imgID).hammer().on("pinch", function(event) { 
     var photo = $(this); 

     newWidth = photo.width() * event.gesture.scale; 
     newHeight = photo.height() * event.gesture.scale; 

     // Convert from screen to image coordinates 
     var x; 
     var y; 
     x -= offset.left + newX; 
     y -= offset.top + newY; 

     newX += -x * (newWidth - width)/newWidth; 
     newY += -y * (newHeight - height)/newHeight; 

     photo.css('-webkit-transform', "scale3d("+event.gesture.scale+", "+event.gesture.scale+", 1)");  
     wrap.css('-webkit-transform', "translate3d("+newX+"px, "+newY+"px, 0)"); 

     width = newWidth; 
     height = newHeight; 
    }); 

} 
+0

Czy umiesz przeczytać? "** Z powodzeniem użyłem tego fragmentu do zmiany rozmiaru zdjęć **" Nigdy nie wspominałem o "drganiu". '$ (imgID) .hammer(). on (" pinch ", funkcja (zdarzenie) [...] function attachPinch (wrapperID, imgID) [...]" ' –

+0

To świetny skrypt, ale dla każdego, kto chce replikuj go - zauważ, że (a) używa wtyczki Jquery dla młota i (b) będziesz musiał zmienić wtyczkę, ponieważ * musisz włączyć szczyptę w młotku, aby działało *. \t \t \t \t {hamObj = new Hammer ($ el [0], opcje); \t \t \t \t hamObj.get ('szczyptę') zestaw ({enable: true}.); \t \t \t \t $ el.data ("młotek", hamObj);} – Ukuser32

2

Spojrzałem w całym Internecie, a siecią zewnętrzną cokolwiek, aż natknąłem się tylko pracy wtyczki/biblioteka - http://cubiq.org/iscroll-4

var myScroll; 
myScroll = new iScroll('wrapper'); 

gdzie owijka ma swój identyfikator, jak w id = "wrapper"

<div id="wrapper"> 
    <img src="smth.jpg" /> 
</div> 
0

to jest coś pisałem kilka lat temu w Javie i niedawno konwertowane do JavaScript

function View() 
{ 
this.pos = {x:0,y:0}; 
this.Z = 0; 
this.zoom = 1; 
this.scale = 1.1; 
this.Zoom = function(delta,x,y) 
{ 
    var X = x-this.pos.x; 
    var Y = y-this.pos.y; 
    var scale = this.scale; 
    if(delta>0) this.Z++; 
    else 
    { 
    this.Z--; 
    scale = 1/scale; 
    } 
    this.zoom = Math.pow(this.scale, this.Z); 
    this.pos.x+=X-scale*X; 
    this.pos.y+=Y-scale*Y; 
} 
} 

this.Zoom = function(delta,x,y) odbywa:

  • delta = powiększania lub z
  • x = x położenie początku powiększenia
  • y = y położenie początku powiększenia

A mały przykład:

<script> 
var view = new View(); 
var DivStyle = {x:-123,y:-423,w:300,h:200}; 
function OnMouseWheel(event) 
{ 
event.preventDefault(); 
view.Zoom(event.wheelDelta,event.clientX,event.clientY); 
div.style.left = (DivStyle.x*view.zoom+view.pos.x)+"px"; 
div.style.top = (DivStyle.y*view.zoom+view.pos.y)+"px"; 
div.style.width = (DivStyle.w*view.zoom)+"px"; 
div.style.height = (DivStyle.h*view.zoom)+"px"; 
} 
function OnMouseMove(event) 
{ 
view.pos = {x:event.clientX,y:event.clientY}; 
div.style.left = (DivStyle.x*view.zoom+view.pos.x)+"px"; 
div.style.top = (DivStyle.y*view.zoom+view.pos.y)+"px"; 
div.style.width = (DivStyle.w*view.zoom)+"px"; 
div.style.height = (DivStyle.h*view.zoom)+"px"; 
} 
</script> 
<body onmousewheel="OnMouseWheel(event)" onmousemove="OnMouseMove(event)"> 
<div id="div" style="position:absolute;left:-123px;top:-423px;width:300px;height:200px;border:1px solid;"></div> 
</body> 

ten powstał z zamiarem jest używany z płótna i grafiki, ale to powinno działać idealnie do normalnego układu HTML

Powiązane problemy