Bas*_*asj 13 css transition transform css3 css-transitions
即使以下代码片段看起来很短,我也会在几天内挣扎(对我感到羞耻!)找到一种方法来缩放仅使用CSS3 点击的点transform.它现在有效:
var current = {x: 0, y: 0, zoom: 1}, c = document.getElementById('container');
window.onclick = function(e) {
wx = current.x + e.clientX / current.zoom;
wy = current.y + e.clientY / current.zoom;
var coef = e.ctrlKey ? 0.5 : 2;
current.zoom *= coef;
current.x = wx - e.clientX / current.zoom;
current.y = wy - e.clientY / current.zoom;
c.style.transform = 'scale(' + current.zoom +') translate(' + (-current.x) + 'px,' + (-current.y) + 'px)';
};Run Code Online (Sandbox Code Playgroud)
html, body { margin: 0; padding: 0; overflow: hidden; min-height: 100%; }
#container { position: absolute; transform-origin: 0 0; transition-duration: 3s;}
#item { position: absolute; left:0px; top:0px; }Run Code Online (Sandbox Code Playgroud)
<div id="container"><div id="item"><img src="http://fadili.users.greyc.fr/demos/WaveRestore/EMInpaint/parrot_original.png"></img></div></div>Run Code Online (Sandbox Code Playgroud)
唯一的问题是转换是奇怪的,就像它首先翻译然后缩放一样; 它会产生一种奇怪的锯齿形状.在这种情况下如何顺利过渡CSS3?
在这里看到奇怪的过渡效果的动画GIF:http://gget.it/zf3fmwum/weirdtransition.gif
注意:点击的点是缩放变换的固定点(例如:单击眼睛,图像被缩放,光标仍在眼睛上),就像在GoogleMaps-doubleclick-zoom中一样.
Peb*_*bbl 19
使用变换时要注意的一件事是您应用它们的顺序.如果你切换它scale,你会发现你的例子的工作方式有所不同translate.
这是一篇关于此事的有趣文章:
https://staff.washington.edu/fmf/2011/07/15/css3-transform-attribute-order/
我无法修复你的版本,主要是因为当你切换变换的顺序时它意外地行为异常.基本上你似乎遇到了奇怪的行为,因为音阶本身导致位置自动翻译,然后你也翻译......似乎这些不同的翻译以稍微不同的速度发生.
然而,我确实重新实现了一个有效的版本,并允许您在缩放之前进行翻译.按顺序保持转换似乎可以避免这个问题.
http://jsfiddle.net/fxpc5rao/32/
我已经修改了下面的版本,translate3D因为它对许多系统来说效果更好.
var current = {x: 0, y: 0, zoom: 1},
con = document.getElementById('container');
window.onclick = function(e) {
var coef = e.shiftKey || e.ctrlKey ? 0.5 : 2,
oz = current.zoom,
nz = current.zoom * coef,
/// offset of container
ox = 20,
oy = 20,
/// mouse cords
mx = e.clientX - ox,
my = e.clientY - oy,
/// calculate click at current zoom
ix = (mx - current.x) / oz,
iy = (my - current.y) / oz,
/// calculate click at new zoom
nx = ix * nz,
ny = iy * nz,
/// move to the difference
/// make sure we take mouse pointer offset into account!
cx = mx - nx,
cy = my - ny
;
// update current
current.zoom = nz;
current.x = cx;
current.y = cy;
/// make sure we translate before scale!
con.style.transform
= 'translate3D('+cx+'px, '+cy+'px,0) '
+ 'scale('+nz+')'
;
};Run Code Online (Sandbox Code Playgroud)
#container {
position: absolute;
left: 20px;
top: 20px;
width: 100%;
height: 100%;
transform-origin: 0 0 0;
transition: transform 0.3s;
transition-timing-function: ease-in-out;
transform: translate3D(0,0,0) scale(1);
}
#item {
position: absolute;
}Run Code Online (Sandbox Code Playgroud)
<div id="container">
<div id="item">
<img src="http://fadili.users.greyc.fr/demos/WaveRestore/EMInpaint/parrot_original.png" />
</div>
</div>Run Code Online (Sandbox Code Playgroud)
我已经更新了我的答案(以及上面的代码段)以考虑您的额外要求,您只需要修改计算以包括鼠标指针偏移的差异.
http://jsfiddle.net/fxpc5rao/33/
现在每次点击计算的未缩放位置之间的差异都会e.clientX, e.clientY被添加.这为您提供了在鼠标指针周围保持缩放平移所需的偏移量.关键变化在于:
cx = (ix + (e.clientX - ix) - nx),
cy = (iy + (e.clientY - iy) - ny)
Run Code Online (Sandbox Code Playgroud)
注意:因为你依赖
e.clientX,e.clientY你会发现如果你#container离开它的当前0,0坐标会发生令人讨厌的异常.这可以完成,但您必须修改计算以将坐标本地化到最终的任何#container's位置.
好的电话@Basj,我不知道转换是以相反的顺序发生的,我会在你的评论中添加链接:
所以就像你说的,你需要的规模加工方面的翻译之前发生,但转化为可在实际转换值规模之前写的-如果是有道理的:)还没确切地知道为什么做一个其它结果前然而,在奇数插值中.
此外,我注意到有一个相当明显的优化 - 我敢肯定,正如你实现这一点,你会发现 - 没有必要添加一些东西只是为了以后减去它.我想那天我的节日欢呼太多了!
cx = e.clientX - nx,
cy = e.clientY - ny
Run Code Online (Sandbox Code Playgroud)
没问题@jdavies,这只是转换鼠标坐标的问题,因此它们相对于容器的左上角.如何计算此偏移量将完全取决于您的项目(使用jQuery.offset之类的东西,更容易获得图层的偏移量 - 跨浏览器).但是我已经更新了这个答案中的代码,考虑到使用绝对位置从0,0开始的硬编码/固定偏移 - 只是为了说明.这里还有一个更新的小提琴:
http://jsfiddle.net/fxpc5rao/5/
正如我们正在使用的那样clientX,clientY鼠标坐标将始终从浏览器窗口的左上角开始计算,使其成为页面的全局(忽略滚动).为了将它们本地化到容器中,您只需要减去容器的x和y位置.
Container at 0,0 Container at 80,100
+------+------- screen x 0 +--------------- 0
| | |
| | | +------+
| x | <-- mouse click | |x | <-- mouse click
+------+ at 100,120 | | | at 100,120
| | | | but relative
| | +------+ 20,20
| | so we us 20,20
0 screen y 0
Run Code Online (Sandbox Code Playgroud)
该#container还可以包含在其他元素中,你只是不得不再次考虑任何位置偏移这些元素给的#container.在下面的小提琴中,有一个#page-setting元素可以用保证金抵消所有内容,只要ox, oy变量使用保证金值更新一切应该表现.
http://jsfiddle.net/fxpc5rao/34/
注意:如果您将此系统放在可滚动页面中,您还需要将视口的滚动偏移添加到鼠标坐标,我在这里给出一个示例,但这很可能不是一个完整的跨浏览器解决方案.你最好看一下像jQuery这样的已建立的库来为你计算坐标和偏移量.