使用CSS3变换比例在点上缩放

使用CSS3变换比例在点上缩放,css,transform,css-transitions,transition,Css,Transform,Css Transitions,Transition,即使下面的代码片段看起来很短,但我在几天的时间里(真丢脸!)都在努力寻找一种方法来放大只使用CSS3transform点击的点。它现在可以工作了: var current={x:0,y:0,zoom:1},c=document.getElementById('container'); window.onclick=函数(e){ wx=current.x+e.clientX/current.zoom; wy=current.y+e.clientY/current.zoom; var coef=e

即使下面的代码片段看起来很短,但我在几天的时间里(真丢脸!)都在努力寻找一种方法来放大只使用CSS3
transform
点击的点。它现在可以工作了:

var current={x:0,y:0,zoom:1},c=document.getElementById('container');
window.onclick=函数(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');
};
html,正文{边距:0;填充:0;溢出:隐藏;最小高度:100%;}
#容器{位置:绝对;变换原点:0;转换持续时间:3s;}
#项目{位置:绝对;左侧:0px;顶部:0px;}

使用转换时需要注意的一件事是应用转换的顺序。如果您切换
缩放
平移
,您会发现您的示例的工作方式大不相同

以下是一篇关于此事的有趣文章:

我无法修复您的版本,主要是因为当您切换转换顺序时,它会意外地出现错误。基本上,你似乎遇到了奇怪的行为,因为天平本身会导致位置的自动转换,然后你也会转换。。。这些不同的翻译似乎是以稍微不同的速度进行的

不过,我确实重新实现了一个有效的版本,允许您在缩放之前进行翻译。保持转换的顺序似乎可以避免这个问题

我修改了下面的版本以使用
translate3D
,只是因为它在许多系统中性能更好

var current={x:0,y:0,zoom:1},
con=document.getElementById('container');
window.onclick=函数(e){
var coef=e.shiftKey | e.ctrlKey?0.5:2,
oz=current.zoom,
nz=当前.zoom*coef,
///集装箱偏移量
ox=20,
oy=20,
///鼠标线
mx=e.clientX-ox,
my=e.clientY-oy,
///计算当前缩放时的单击
ix=(mx-当前的.x)/oz,
iy=(my-current.y)/oz,
///计算新缩放时的单击
nx=ix*nz,
ny=iy*nz,
///转向差异
///确保我们将鼠标指针偏移量考虑在内!
cx=mx-nx,
cy=我的-纽约
;
//更新当前
current.zoom=nz;
电流x=cx;
电流y=cy;
///确保我们在缩放之前进行翻译!
con.style.transform
='translate3D('+cx+'px',+cy+'px,0)'
+'比例('+nz+')'
;
};
#容器{
位置:绝对位置;
左:20px;
顶部:20px;
宽度:100%;
身高:100%;
变换原点:0;
转换:转换0.3s;
过渡定时功能:易进易出;
变换:平移3D(0,0,0)比例(1);
}
#项目{
位置:绝对位置;
}

查看/缩放和平移图像的难题,对吗?:)

我终于成功地校准了缩放算法,所以我想与社区分享它。我创建了一个查看器类来与底层图像交互。我的解决方案中的一个重要点是,它不会修改默认的变换原点,这对于其他一些变换可能很有用

您可以使用单击缩放/ctrl+单击取消缩放,或使用夹入夹出(使用Hammer JS)。警告,Firefox默认情况下不会启用触摸事件

很抱歉,我知道它使用了Hammer和自制的Transform&Point类,但请关注zoomTo方法,它与框架无关,是这个缩放问题的要点

(如果愿意,您可以在下面找到TypeScript版本)

在这个片段中尝试一下

//加载查看器
window.onload=函数(){
var v=newui.Viewer(document.getElementById('Viewer');
v、 setViewPortSize({宽度:900,高度:600});
v、 setSource('https://upload.wikimedia.org/wikipedia/commons/d/d9/Big_Bear_Valley(u California.jpg),;
}
变量点=(函数(){
功能点(x,y){
这个.x=x;
这个。y=y;
}
Point.prototype.toString=函数(){
返回“(“+this.x+”;“+this.y+”)”;
};
返回点;
})();
变量转换=(函数(){
函数变换(){
this.translate=新点(0,0);
这个比例=1;
这个角度=0;
}
回归变换;
})();
var-UI;
(功能(UI){
变量查看器=(函数(){
函数查看器(查看器){
this.ticking=false;
console.info(“查看器浏览器打开:”+viewer);
this.viewer=查看器;
this.viewer.style.position='relative';
this.viewer.style.overflow='hidden';
this.viewer.style.touchAction='none';
this.viewer.style.backgroundColor='000000';
this.viewer.style['-webkit用户选择']='none';
this.viewer.style['-webkit用户拖动']='none';
this.viewer.style['-webkit点击高亮显示颜色']='rgba(0,0,0,0');
this.viewerContent=this.viewer.querySelector(“.image”);
if(this.viewerContent==null){
this.viewerContent=document.createElement('img');
this.viewerContent.className='image';
this.viewer.appendChild(this.viewerContent);
}
this.viewerContent.style.position='absolute';
this.viewerContent.style.transition='transform 100ms linear';
console.info(“image width=“+this.viewer.clientWidth+”x“+this.viewer.clientHeight”);
这是我的转变