Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >「实战」如何用H5实现原生体验的图片预览组件

「实战」如何用H5实现原生体验的图片预览组件

作者头像
用户1097444
发布于 2022-06-29 09:17:01
发布于 2022-06-29 09:17:01
3.3K0
举报

| 导语 手Q终端原生的图片预览器支持图片翻页和各种手势,这些用H5怎样实现?基于alloyFinger,本文将介绍在手Q动漫上的图片预览组件是如何做到媲美原生体验的手势效果,同时也介绍一下关于图片手势效果里隐含的一些细节。希望对要实现手势交互和动画的前端同学有所启发。

作者:朱晓华--腾讯web前端工程师

@IMWeb前端社区

一、实现效果

先来看实现效果。目前已经上线的图片预览组件的路径如下:手Q动态——动漫——社区——点击图片。

类比手Q的AIO里的图片预览器,支持的手势和功能分别如下:

手Q动漫这里之所以没有直接用手Q原生的图片预览器,而是新造一个轮子,主要原因是手Q动漫的图片预览器有一些定制的功能和ui展示,用web来实现更快捷可控一些。从上表可以看出,除了旋转图片之外,基本上跟手Q原生体验无异。旋转图片在alloyFinger中有提供方法支持,但由于本需求中使用场景少而且涉及更复杂的坐标变换,因此我目前还没添加上。后续工作量许可的情况下会支持。

二、实现基础

图片预览组件目前是基于alloyFinger.js来做手势支持,transform.js来做CSS3的变换,to.js来做动画的过渡函数。

关于alloyFinger.js组件 https://github.com/AlloyTeam/AlloyFinger 组件提供了单击、双击、长按、拖动、旋转等手势支持。基于这些手势有很多玩法。这里就不详细叙述了。

关于transform.js组件 http://alloyteam.github.io/AlloyTouch/transformjs/ alloyFinger只提供了手势支持,但手势具体要实现的图片位置变换或者缩放的效果,需要由transform.js来支持。transform.js给dom元素添加了css3的属性对应的js属性,例如translateX, translateY, translateZ, scaleX, scaleY, scaleZ, rotateX, rotateY, rotateZ, skewX, skewY, originX, originY, originZ。 获取属性只需要var x = ele.translateX,而设置css3属性只需要ele.transalteX = 10,非常方便。

关于to.js组件 https://github.com/AlloyTeam/AlloyFinger/blob/master/asset/to.js to.js组件以requestAnimationFrame为基础,提供了设置dom元素属性的过渡函数,支持传入渐入渐出相关的函数。用法如下:

三、实现细节

1. 翻页的实现

理论上支持图片无限翻页,这里实现的方法是: 任何时候都保持三张图片在容器中并且中间的图片在屏幕内。翻页之后再通过删除前一张和补充后一张来维持三张图片的状态。 这样的好处是:更少的dom节点和更好的动画性能、支持用户主动添加和删除图片、支持异步添加图片。

2. 在origin、scale和translate三个因素下的坐标变换

正常情况下,图片缩放是只需要设置scale为你所需要的倍数就行了。双击缩放和双指缩放的原理差不多,都是需要先设置css3的transform的坐标变换中心origin,只不过双指缩放是以两个手指连线的中点作为缩放原点。因此开始的代码只需要是:

但在放大2倍的情况下,两个手指再次放到图片上另一个位置缩放的时候,图片会跳动。原因是,在有scale的情况下,改变了origin值,要保持图片位置不变,则需要同时改变translate来平移图片。 例如,对于宽高都是100的图片,在当前origin=(0,0),scale=2,translate=(0,0)的情况下,当你修改origin=(50,50)时,scale=2不变,应有translate=(50,50)。 ps:对于transform.js的origin,默认是0表示是图片50%的位置,只能设置px值不能设置比例 例如下图中,图1是当前图片从当前中心点放大两倍的情况,实际上等同与从图2平移到图3。

“容易证明”得以下数学公式↓↓↓ 以X轴为例,假设放大倍数是s,计算新的translateX的数学公式如下:

谨记这个公式,下面基本上所有涉及到缩放状态的变换都以这个为基础。

在这个公式的使用时机是每次touchstart的时候,都要重新调整origin和translate的值,然后手指缩放的touchmove里再对scale做改变。就能实现多次变换位置的缩放了。代码例如:

3. 手势细节-边界检测

图片放大之后,支持拖动图片查看细节。实现的原理很简单,touchmove的时候,改变图片的translate值即可。对比手Q的AIO的图片预览,在拖动图片到图片边缘的时候,检测边界并禁止继续拖动。 (1) 当图片的缩放原点origin为(0,0)时 以X轴为例,假设图片宽度为w,放大倍数为s,则translateX的区间为

图示边界的四种情况:

(2) 但实际过程中,因为图片的原点origin不一定是(0,0),因此上述区间不适用 解决方法也简单,根据当前的origin和translate,通过translateX2 = translateX1 + (originX2 - originX1) * s公式,计算出图片当前位置在origin=(0,0)的时候translate应该是哪些值。然后再套用上面的区间来判断边界即可。

4. 手势细节-自动贴边

当图片放大再缩小的时候,图片有可能还是超出边界了。因此,在手指松开之后,需要让图片自动贴近到该方向的屏幕边缘。 自动贴边得益于上述的边界检测的方法,在touchend中判断超出边界之后,自动把translate设置到最近的边界值。

5. 手势细节-惯性

单指拖动图片然后松开手指时,手Q原生的图片预览器有继续滑动一段距离的惯性效果。 滑动到终点之后,图片真正停在的点是在延长点上。那延长点要怎么计算呢,这里可以用向量的知识来指导坐标的计算方法。

假设起点起点坐标(x1, y1),终点坐标(x2, y2),滑动距离是l,需要计算延长点(x3, y3)的公式如下:

当然这里有个小问题,就是滑动距离l的定义。如果拖动的起点和终点距离很小,那么滑动距离也应该很小才对。否则就导致轻轻拖动一下,惯性却非常大。因此滑动距离是拖动距离的一个小比例值。

上述的实现惯性的方法其实只能算近似模拟,不符合现实生活中曲线运动的问题的惯性运动轨迹。 实际上的运动延长线的方向,应该是曲线在终点位置的切线。而且实际的惯性滑动距离,也是跟当前的速度有关,而不是一个恒定的比例值。这里后期优化的时候,会考虑这些点。

6. 手势细节-回弹

交互上,图片放大和缩小是有倍数限制的,超过最大/最小倍数值的时候,会让用户继续放大一部分,但再超过一定的阈值之后会停止放大,并在手指松开之后回弹到最大/最小倍数。这样的交互形式让用户对放大缩小的最大限制有一个直观的了解,避免生硬的交互体验。 这里的实现原理很简单:在alloyFinger的pinch回调中,设置最大倍数为max+n,其中n为超出阈值。在touchend的回调中,设置缩小值回弹到max。

四、总结

感谢@dntzhang 提供alloyFinger的支持,感谢@javinzhong 提供的先行实验版。我的工作是站在两位巨人的肩膀上才得以实现。 总的来说,这个项目除了加深自己对web手势和css3动画的理解之外,对于深入挖掘图片手势的细节和效果也是很有帮助。很多产品细节是需要不断地打磨和优化的,对自己的工作需要多的细节追求和精力倾注才能有好的成果,与君共勉(不小心抖了个鸡汤-_-)

扫码下方二维码,

随时关注更多前端干货文章!

微信:IMWebTech

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-04-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯IMWeb前端团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
64.Harmonyos NEXT 图片预览组件之手势处理实现(二)
在上一篇文章中,我们介绍了图片预览组件的单指拖动和双指缩放手势实现。本文将继续介绍双指旋转手势和双击缩放手势的实现细节。
全栈若城
2025/03/14
850
65.Harmonyos NEXT 图片预览组件之手势处理实现(三)
在前两篇文章中,我们介绍了图片预览组件的单指拖动、双指缩放和双指旋转手势实现。本文将继续介绍双击缩放手势的实现细节,以及手势之间的协同工作机制。
全栈若城
2025/03/14
1300
写一个H5图片预览组件
这里需要实现的一点是点击照片墙上的小图时预览大图,小程序中提供了API: wx.previewImage预览图片,非常方便。但没有找到比较满意的React实现,于是仿小程序写了一个PhotoPreview组件。
IMWeb前端团队
2019/12/03
1.5K0
写一个H5图片预览组件
63.Harmonyos NEXT 图片预览组件之手势处理实现
手势处理是图片预览组件的核心交互功能,通过识别和响应用户的各种触摸操作,实现图片的缩放、旋转、拖动和切换等功能。本文将详细介绍PicturePreviewImage组件中的手势处理实现原理。
全栈若城
2025/03/14
740
59.Harmonyos NEXT 图片预览组件之PicturePreviewImage实现原理
PicturePreviewImage是图片预览组件的核心内层组件,负责单张图片的展示和交互处理。该组件实现了图片的缩放、旋转、拖动等丰富的交互功能,为用户提供流畅的图片预览体验。
全栈若城
2025/03/13
950
腾讯开源的非常小巧的JS手势库
腾讯前端团队前几天在Github上发布了一个JS手势库 AlloyFinger 极其小巧,只有几K,但功能很全面,支持缩放、旋转、拖拽、单击、双击、滑动、长按 而且除了Dom对象外,还可以监听Canvas内元素的手势 在腾讯内部的应用已经非常广泛,例如 QQ群、QQ动漫、AlloyTeam 等团队和项目 官方示例 http://alloyteam.github.io/AlloyFinger/ 代码示例 实现对一个图片的移动和缩放 <!DOCTYPE html> <html> <head> <
dys
2018/04/03
3.6K0
60.Harmonyos NEXT 图片预览组件之边界处理与图片切换
在图片预览组件中,边界处理是一个核心功能,它确保了图片在缩放、旋转和拖动过程中的合理显示,并实现了多图片之间的平滑切换。本文将详细介绍 PicturePreviewImage 组件中的边界处理与图片切换实现原理。
全栈若城
2025/03/14
820
66.Harmonyos NEXT 图片预览组件使用指南
图片预览组件是一个功能完善的图片查看器,支持图片的缩放、旋转、滑动切换等功能。本文将详细介绍如何在HarmonyOS应用中集成和使用图片预览组件,帮助开发者快速实现高质量的图片预览功能。
全栈若城
2025/03/14
1510
57.Harmonyos NEXT 图片预览组件实现概览
图片预览组件是一个用于展示和交互图片的高级组件,支持图片的缩放、旋转、滑动切换等功能。该组件由两个核心部分组成:
全栈若城
2025/03/13
1170
【实战】Canvas实现图片上标注、缩放、移动和保存历史状态
面试官说可以往深层次思考一下,或许加一些新的功能来增加项目的难度,他提了几个建议,其中一个就是试卷在线批阅,老师可以在上面对作业进行批注,圈圈点点等俺当天晚上就开始研究这个东东哈哈哈,终于被我研究出来啦!
Nealyang
2020/06/10
7.1K0
【实战】Canvas实现图片上标注、缩放、移动和保存历史状态
原生 JS 手写一个优雅的图片预览功能,带你吃透背后原理
本文将用一个极简的例子详细讲解如何用原生JS一步步实现完整的图片预览和查看功能,无任何第三方依赖,兼容PC与H5,实现了触屏双指缩放等,干货满满。
茶无味的一天
2022/11/02
3.7K0
原生 JS 手写一个优雅的图片预览功能,带你吃透背后原理
62.Harmonyos NEXT 图片预览组件之工具类实现
图片预览组件中的工具类是支撑组件功能实现的重要基础设施,它们提供了约束计算、动画效果、窗口管理等核心功能。本文将详细介绍图片预览组件中的三个核心工具类:Constrain、FuncUtils和Managers。
全栈若城
2025/03/14
940
68.Harmonyos NEXT 图片预览组件应用实践(一):相册与社交场景
图片预览组件作为一个功能完善的图片查看器,可以应用于多种场景。本文将重点介绍相册和社交媒体场景下的最佳实践。
全栈若城
2025/03/14
1260
61.Harmonyos NEXT 图片预览组件之数据模型设计与实现
图片预览组件采用了模型驱动的设计思想,将不同的交互状态抽象为独立的数据模型,实现了状态管理的解耦和代码的高内聚。本文将详细介绍图片预览组件中的四个核心数据模型:ScaleModel、RotateModel、OffsetModel和CommonLazyDataSourceModel。
全栈若城
2025/03/15
580
61.Harmonyos NEXT 图片预览组件之数据模型设计与实现
61.Harmonyos NEXT 图片预览组件之数据模型设计与实现
图片预览组件采用了模型驱动的设计思想,将不同的交互状态抽象为独立的数据模型,实现了状态管理的解耦和代码的高内聚。本文将详细介绍图片预览组件中的四个核心数据模型:ScaleModel、RotateModel、OffsetModel和CommonLazyDataSourceModel。
全栈若城
2025/03/14
770
在小程序里实现手势缩放,你可以这样做 | 实战教程
文 | 严灏 上周,知晓程序向大家分享了「知了地铁」小程序的上手体验。同时,我们也在这篇文章中提过,会与大家讨论有关小程序中手势缩放功能的实现。 关注知晓程序(微信号 zxcx0101),回复「知了地
知晓君
2018/06/28
2.1K0
HarmonyOS 开发实践 —— 基于手势的图片预览与缩放
1、使用组合手势GestureGroup,同时绑定捏合手势PinchGesture和滑动手势PanGesture,设置组合手势识别模式为并行识别模式:Parallel,并行识别组合手势中注册的手势将同时进行识别,直到所有手势识别结束,并行识别手势组合中的手势进行识别时互不影响。
小帅聊鸿蒙
2024/12/09
3160
【博客美化】10.图片预览放大
写文章用到的图片尺寸都很大,但是放到博客里面就显得比较小,所以每次看图时需要打开新标签页来看大图,有没有什么办法直接在博客里面预览大图呢?有的,CSS的强大功能就可以帮助实现
悟空聊架构
2019/07/01
7170
【博客美化】10.图片预览放大
H5C3第二节
对于我们眼睛来说,离我们越近的房子,我们会感觉到这个房子越大,离我们越远的房子,就会感觉越小,其实房子的大小都是一样的,只是在视觉上的一种不同。
用户3461357
2019/08/02
5610
H5C3第二节
让元素呈现出“七十二变”的效果,就是这么简单
HTML5学堂:作为前端开发者,总会在设计图上看到各种各样奇怪的图形,想用图片解决又怕觉得很low,想用其它方法又一下子反应不过来。不管现在的你有没有面对过这样的状态,多做准备总是好的。 本文主要内容 一、CSS3的变形引入 二、二维变形的语法 三、二维变形的常用属性分析 四、二维变形的操作实例 五、总结 一、CSS3的变形引入 在网页设计中,CSS被习惯性的理解为擅长表现静态样式,动态的元素必须借助于javascript才可以实现,而CSS3的出现改变了这一思维方式。CSS3除了增加革命性的创新功能外,还
HTML5学堂
2018/03/13
1.8K0
让元素呈现出“七十二变”的效果,就是这么简单
推荐阅读
相关推荐
64.Harmonyos NEXT 图片预览组件之手势处理实现(二)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档