Javascript 使用 CSS3 捏合缩放
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10802176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Pinch to zoom with CSS3
提问by Maros
I'm trying to implement pinch-to-zoom gestures exactly as in Google Maps. I watched a talk by Stephen Woods - "Creating Responsive HTML5 Touch Interfaces”- about the issue and used the technique mentioned. The idea is to set the transform origin of the target element at (0, 0) and scale at the point of the transform. Then translate the image to keep it centered at the point of transform.
我正在尝试像在 Google 地图中一样实现双指缩放手势。我观看了 Stephen Woods 的演讲 - “Creating Responsive HTML5 Touch Interfaces”- 关于这个问题并使用了提到的技术。这个想法是将目标元素的变换原点设置为 (0, 0) 并在该点进行缩放变换。然后平移图像以使其保持在变换点的中心。
In my test code scaling works fine. The image zooms in and out fine between subsequent translations. The problem is I am not calculating the translation values properly. I am using jQuery and Hammer.js for touch events. How can I adjust my calculation in the transform callback so that the image stays centered at the point of transform?
在我的测试代码缩放工作正常。图像在后续翻译之间精细放大和缩小。问题是我没有正确计算翻译值。我使用 jQuery 和 Hammer.js 来处理触摸事件。如何在转换回调中调整我的计算,以便图像保持在转换点的中心?
The CoffeeScript (#test-resize
is a div
with a background image)
所述的CoffeeScript(#test-resize
是一个div
与背景图像)
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
采纳答案by Maros
I managed to get it working.
我设法让它工作。
In the jsFiddle demo, clicking on the image represents a pinch gesture centred at the click point. Subsequent clicks increase the scale factor by a constant amount. To make this useful, you would want to make the scale and translate computations much more often on a transform event (hammer.js provides one).
在 jsFiddle 演示中,单击图像表示以单击点为中心的捏合手势。随后的点击将比例因子增加一个常数。为了使它有用,您需要在转换事件上更频繁地进行缩放和转换计算(hammer.js 提供了一个)。
The key to getting it to work was to correctly compute the point of scale coordinates relative to the image. I used event.clientX/Y
to get the screen coordinates. The following lines convert from screen to image coordinates:
让它工作的关键是正确计算相对于图像的比例点坐标。我曾经event.clientX/Y
得到屏幕坐标。以下几行将屏幕坐标转换为图像坐标:
x -= offset.left + newX
y -= offset.top + newY
Then we compute a new size for the image and find the distances to translate by. The translation equation is taken from Stephen Woods' talk.
然后我们计算图像的新尺寸并找到要平移的距离。平移方程取自Stephen Woods 的演讲。
newWidth = image.width() * scale
newHeight = image.height() * scale
newX += -x * (newWidth - image.width) / newWidth
newY += -y * (newHeight - image.height) / newHeight
Finally, we scale and translate
最后,我们缩放和翻译
image.css '-webkit-transform', "scale3d(#{scale}, #{scale}, 1)"
wrap.css '-webkit-transform', "translate3d(#{newX}px, #{newY}px, 0)"
We do all our translations on a wrapper element to ensure that the translate-origin stays at the top left of our image.
我们在包装元素上进行所有翻译,以确保 translate-origin 保持在图像的左上角。
回答by Raphael Toselli
I successfully used that snippet to resize images on phonegap, using hammer and jquery.
我使用锤子和 jquery 成功地使用该片段调整了 phonegap 上的图像大小。
If it interests someone, i translated this to JS.
如果有人感兴趣,我将其翻译为 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;
});
}
回答by Andrei Cristian Prodan
I looked all over the internet, and outernet whatever, until I came across the only working plugin/library - http://cubiq.org/iscroll-4
我查看了整个互联网和外网,直到我遇到了唯一可用的插件/库 - http://cubiq.org/iscroll-4
var myScroll;
myScroll = new iScroll('wrapper');
where wrapper is your id as in id="wrapper"
其中 wrapper 是您的 id,如 id="wrapper"
<div id="wrapper">
<img src="smth.jpg" />
</div>
回答by Ideogram
Not a real answer, but a link to a plug=in that does it all for you. Great work!
不是真正的答案,而是指向插件的链接,可以为您完成所有工作。做得好!
https://github.com/timmywil/jquery.panzoom
https://github.com/timmywil/jquery.panzoom
(Thanks 'Timmywil', who-ever you are)
(感谢 'Timmywil',无论你是谁)
回答by Isaac
This is something I wrote a few years back in Java and recently converted to JavaScript
这是我几年前用 Java 写的,最近转换成 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;
}
}
The this.Zoom = function(delta,x,y)
takes:
将this.Zoom = function(delta,x,y)
需要:
delta
= zoom in or outx
= x position of the zoom originy
= y position of the zoom origin
delta
= 放大或缩小x
= 缩放原点的 x 位置y
= 缩放原点的 y 位置
A small example:
一个小例子:
<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>
This was made with the intention of being used with a canvas and graphics, but it should work perfectly for normal HTML layout
这是为了与画布和图形一起使用而制作的,但它应该可以完美地用于普通的 HTML 布局