Js实现任意位置缩放图片,深入理解背后原理
前言
本文将用一个简单的例子详细讲解如何用原生JS一步步实现完整的任意位置缩放图片功能,无任何第三方依赖,指针事件
进行多端统一的事件监听,干货满满。
完整代码
为提升阅读体验,正文中代码展示有部分省略处理,完整代码可以在码上掘金查看:
https://code.juejin.cn/pen/7356824634160840730可在任意位置缩放、移动图片
实现原理
实现图片放大的关键点在于 CSS3 中的 transform
变换,该属性应用于元素在2D或3D上的旋转,缩放,移动,倾斜等等变换,通过设置 translate(x,y)
即可偏移元素位置,设置 scale
即可缩放元素,当然你也可以只设置 matrix
来完成上述所有操作,这涉及到矩阵变换的知识,本文使用的均是CSS提供的语法糖进行变换操作。
PC上的点击、移动,H5的手势操作,都离不开DOM事件监听。例如鼠标移动事件对应 mousemove
,移动端因为没有鼠标则对应 touchmove
,而本文将介绍如何仅通过指针事件来进行多端统一
的事件监听。在监听事件中我们可以通过 event
对象获取各种属性,例如常用的 offsetX
、offsetY
相对偏移量,clientX
、clientY
距离窗口的横坐标和纵坐标等。
理解transform-origin值
官方文档解释为:**transform-origin
**CSS 属性让你更改一个元素变形的原点。
https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform-origin
我们可以简单的理解为图片缩放起点,这个值默认为图片的正中心,所以我们进行放大或缩小都是依图片中心来缩放。
css缩放图片有两种方法
一、修改transform-origin
值进行缩放
优点:简单快捷,容易理解
缺点:频繁修改
transform-origin
值会抖动,需要计算修正量
将鼠标当前的偏移量即 offsetX、offsetY
的值改变 transform-origin
来动态设置缩放的原点,再进行缩放,那么最终效果就是依照最新的transform-origin
值来进行缩放。
比如修改transform-origin
值为90% 90%。再设置放大倍数scale
为1.1。效果就是下图的样子
二、不修改transform-origin
值,设置偏移量translate(x,y)
进行缩放
我们利用滚轮事件监听并改变 scale
值。重点是利用 deltaY
值的正负来判断滚轮是朝上还是朝下:
let scale = 1;
image.addEventListener("wheel", function (e) {
//d值永远是正的0.1或者负的0.1,代表每次缩放的倍数
let d = e.deltaY < 0 ? 0.1 : -0.1;
scale = scale * (1 + d);
...
});
如上图,怎么样从左图变成右图呢?由于我们未修改transform-origin
,所以缩放始终都以图片中心
为原点进行缩放,这显然不符合我们的操作习惯,我们需要的是以鼠标点为中心对图片进行缩放。
可以清晰的看到,我们先将图片放大0.1倍,再设置偏移量translate(x,y)
就可以实现任意位置缩放
需要计算的translate(x,y)
值,实际上就是放大后的图片中心点与原始图片中心点的差值
每次可偏移translate(x,y)
的最大值
= 长宽 * 放大倍数 / 2
例如:长400,宽为800的图片。放大0.1倍之后,图片的长为440,宽为880。如果是在中心点放大,那么不需要移动图片,xy等于0。如果在左上角放大,那么图片整体向右下角偏移
x = (440 - 400) / 2 = 20,y = (880 - 800) / 2 = 40.
let d = e.deltaY < 0 ? 0.1 : -0.1;
const max = {
x: (d * rect.width) / 2,
y: (d * rect.height) / 2,
};
用鼠标点的座标
减去图片的在页面中的位置
可以得到鼠标在图片中的位置
rect = image.getBoundingClientRect()
const mouseOffset = {
x: e.clientX - rect.x,
y: e.clientY - rect.y
}
最后用mouseOffset
减去已偏移的xy,再剩以放大倍数d
,再减去max
,就是当前的translate(x,y)
值
- 因为
mouseOffset
的值,基本可以看作为一个常量,如果鼠标不移动位置,那么mouseOffset
的值不会变,所以需要减去已偏移的xy,才能累计偏移量 - 再剩以放大倍数,得到的值,还不能用于偏移
- 第二步得到的这个值已经超过我们的最大偏移值
max
,所以需要减去max
,最终就是当前的偏移量
// 计算每次的偏移量
x -= d * (mouseOffset.x - x) - max.x;
y -= d * (mouseOffset.y - y) - max.y;
image.style.transform = "translate3d(" + x + "px, " + y + "px, 0) scale(" + scale + ")";
移动图片
移动图片的实现是比较简单的,在每次指针按下时我们记录 clientX
、clientY
为初始值,移动时计算当前的值与初始点位的差值加到 translate
偏移量中即可另外当抬起动作结束时,会触发 click
事件,所以注意加入全局变量标记以及定时器进行一些判断处理。
image.addEventListener("pointerdown", function (e) {
isPointerdown = true;
lastPointermove = {x: e.clientX, y: e.clientY};
});
image.addEventListener("pointermove", function (e) {
if (isPointerdown) {
const current = {x: e.clientX, y: e.clientY};
x += current.x - lastPointermove.x;
y += current.y - lastPointermove.y;
lastPointermove = current;
image.style.transform = "translate3d(" + x + "px, " + y + "px, 0) scale(" + scale + ")";
}
e.preventDefault();
});
image.addEventListener("pointerup", function (e) {
isPointerdown = false;
});
结束
以上就是文章的全部内容,感谢看到这里,希望对你有所帮助或启发!创作不易,如果觉得文章写得不错,可以点赞收藏支持一下,也欢迎关注,我会更新更多实用的前端知识与技巧,期待与你共同成长~
Js实现任意位置缩放图片,深入理解背后原理的更多相关文章
- JS实现等比例缩放图片
JS实现等比例缩放图片 2014-01-19 21:57 by 龙恩0707, 40 阅读, 0 评论, 收藏, 编辑 JS实现等比例缩放图片 有时候我们前端页面只有500×500像素的宽和高的布局, ...
- Magnifier.js - 支持鼠标滚轮缩放的图片放大镜效果
Magnifier.js 是一个 JavaScript 库,能够帮助你在图像上实现放大镜效果,支持使用鼠标滚轮放大/缩小功能.放大的图像可以显示在镜头本身或它的外部容器中.Magnifier.js 使 ...
- JS等比例缩放图片,限定最大宽度和最大高度
JS等比例缩放图片,限定最大宽度和最大高度 JavaScript //图片按比例缩放 var flag=false; function DrawImage(ImgD,iwidth,iheight){ ...
- 如何在html中把一个图片或者表格覆盖在一张已有图片上的任意位置
如何在html中把一个图片或者表格覆盖在一张已有图片上的任意位置 <div style="position:relative;"> <img src=&quo ...
- 【js】【图片显示】js控制html页面显示图片方式
js控制html页面显示图片方式,只需要引入“jquery-1.11.2.min.js” js: /* 引用 <script src="jquery-1.11.2.min.js&quo ...
- Android 图片文件操作、屏幕相关、.9图片的理解
一:Android图片操作 1.存储bitmap到本地文件系统 public static void bitmapToFile(Bitmap bitmap, String uri) { if(!ex ...
- C语言中链表任意位置怎么插入数据?然后写入文件中?
链表插入示意图:(图是个人所画)因为链表指针指来指去,难以理解,所以辅助画图更加方便. 插入某个学号后面图: 定义的结构体: struct student { ]; //学生学号 ]; //学生姓名 ...
- Android拖动和缩放图片
Android拖动和缩放图片 2014年5月9日 我们在使用应用其中常常须要浏览图片.比方在微信其中.点击图片之后能够对图片进行缩放. 本博客介绍怎样对图片进行拖拽和缩放.这首先要了解Android中 ...
- JavaScript等比例缩放图片
js等比例缩放图片,这个功能非常实用,当网页加载一个尺寸比较大的图片时,往往会把一个网页撑的变形,页面变得很难看,于是我们就想到了用JS去控制超出一定范围的图片,以稳定页面布局,本代码段就是完成了此功 ...
- 【全面总结】js获取元素位置大小
[js获取元素位置+元素大小]全面总结 目录 1.关于offset offsetParent(只读) offsetTop(只读) offsetLeft(只读) offsetHeight(只读) off ...
随机推荐
- 因果推断review
什么是因果推断? 因果推断(Causal Inference):就是预估对某个对象/群体/人 等 做不做某种干预后产生的结果. 常说'关系不代表因果'. 比如,一项研究表面,吃早餐的女孩比不吃早餐的女 ...
- Linux CentOs6.4 静态IP 设置
Linux CentOs6.4 静态IP 设置 分类: IT技术 2013-04-07 09:20 2330人阅读 评论(1) 收藏 举报 To do that, just log on as ...
- UML 哲学之道——领域模型[四]
前言 简单整理一下领域模型. 正文 领域模型是对领域内的概念类或现实中的对象的可视化表示 领域模型也称概念模型.领域对象模型和分析对象模型 领域模型是可以在业务建模科目中创建的制品之一 领域模型是up ...
- 重新整理数据结构与算法(c#)—— 算法套路分治算法[二十五]
前言 有一个汉罗塔的游戏如下: 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具. 大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘. 大梵天 ...
- em/px/rem/vh/vw的区别
一.介绍 传统的项目开发中,我们只会用到px.%.em这几个单位,它可以适用于大部分的项目开发,且拥有比较良好的兼容性 从CSS3开始,浏览器对计量单位的支持又提升到了另外一个境界,新增了rem.vh ...
- 什么是token,为什么需要token
1.为什么需要token 随着互联网的发展,为了更安全,以及更好的用户体验,逐渐产生了token这个技术方案 之所以使用token是因为http/https协议本身是无状态的,不能进行信息的存储 (c ...
- 【SQL】IN和EXISTS谁的效率更高
[SQL]IN和EXISTS谁的效率更高 总结: 索引设置好的情况下 子查询数据量大的,用exists 子查询数据量小的,用in 原文连接:https://zhuanlan.zhihu.com/p/4 ...
- 为 Serverless Devs 插上 Terraform 的翅膀,实现企业级多环境部署(下)
简介: 在上篇中,主要介绍了 Serverless Devs 多环境功能的使用,用户读完可能会些疑问,本文会就一些常见问题进行下回答. 在上篇中,主要介绍了 Serverless Devs 多环境功能 ...
- 如何发起 MQTT 亿级连接和千万消息吞吐性能测试
简介:MQTT 协议凭借简单易实现.支持 QoS.报文小等特点,占据了物联网协议的半壁江山. 作者:亦炎 随着 5G 时代的来临,万物互联的伟大构想正在成为现实.联网的物联网设备 在 2021 年已 ...
- Serverless 工程实践 | 细数 Serverless 的配套服务
简介: 上文说到云计算的十余年发展让整个互联网行业发生了翻天覆地的变化,Serverless 作为云计算的产物,或者说是云计算在某个时代的表现,被很多人认为是真正意义上的云计算,关于"Se ...