pc 图片预览放大 端vue_移动端Vue.js的图片预览组件,支持放缩、滑动功能!
功能:图片预览组件,支持双手指放大/缩小,双击放大/缩小,单击消失隐藏。
注:touch事件请手机预览
源码分享
组件参数
data() {
return {
loading: 2, // 1成功 2正在加载 3error失败
dragObject: {},
starLine: 0, // 初始俩个点第1次距离
zoom: 1, // 放缩比
compress: null, // 最大压缩比
elWidth: null, // 外层宽度
elHeight: null, // 外层高度
imgWidth: null, // 当前图片宽度
imgHeight: null, // 当前图片高度
mTop: 0, // margin-top 值
mLeft: 0, // margin-left 值
isTouch: false, // 是否touch
scrolling: false, // 是否放缩
animating: false, // 是否动画中
isTwoClick: false, // 是否双击
startTime: null, // 第一次时间
timeFunc: null, // 定时器
}
},
组件初始化init(),dom绑定事件,区分滑动事件、单击、双击事件
/**
* 初始化事件
* @param {Object} $el 当前DOM
*/
init($el) {
this.elWidth = document.documentElement.clientWidth
this.elHeight = document.documentElement.clientHeight
$el.addEventListener('touchstart', (e) => {
if (this.animating) return
// 记录点击时间和第二次点击的时差
if (this.startTime) this.dragObject.duration = new Date() - this.startTime
if (!this.startTime) this.startTime = new Date()
if (this.dragObject.duration) this.startTime = null
this.dragObject.startTime = new Date()
this.touchStart(e)
if (!this.isTouch) this.isTouch = e.touches.length > 1
})
$el.addEventListener('touchmove', (e) => {
....
})
$el.addEventListener('touchend', (e) => {
....
}
})
图片加载完后执行imgLoad()事件,设置图片初始显示的宽imgWidth高imgHeight以及放缩比compress
/**
* 图片加载成功事件
*/
imgLoad(e) {
const compress = e.target.width / this.elWidth
const scale = this.scale > 3 ? this.scale : 3
this.imgWidth = compress > 1 ? this.elWidth : e.target.width
this.imgHeight = compress > 1 ? e.target.height / compress : e.target.height
this.compress = compress > scale ? compress : scale
this.loading = 1
},
滑动开始,区分放缩事件or滑动事件
$el.addEventListener('touchmove', (e) => {
e.preventDefault()
if (this.animating) return
this.isTouch = true
if (e.touches.length === 2) this.touchTwoMove(e)
if (e.touches.length === 1) this.touchMove(e)
})
touchStart()滑动开始事件
/**
* 触发开发
*/
touchStart(e) {
const touch = e.touches[0]
if (e.touches.length > 1) {
// 放缩初始俩点的距离
const touch2 = e.touches[1]
const diffX = touch.pageX - touch2.pageX
const diffY = touch.pageY - touch2.pageY
this.starLine = Math.pow((diffX * diffX + diffY * diffY), 0.5)
}
// 缓存初始的margin-left和margin-top的比值
this.dragObject.topThan = this.mTop !== 0 ? this.mTop / this.reckonHeight(this.zoom) : 0
this.dragObject.leftThan = this.mLeft !== 0 ? this.mLeft / this.reckonWidth(this.zoom) : 0
this.dragObject.startLeft = touch.pageX
this.dragObject.startTop = touch.pageY
this.dragObject.zoom = this.zoom
}
touchMove()触发滑动事件
/**
* 触发移动
*/
touchMove(e) {
if (this.scrolling) return
const dragObject = this.dragObject
const touch = e.touches[0]
let xx = touch.pageX - (dragObject.oldLeft || dragObject.startLeft)
let yy = touch.pageY - (dragObject.oldTop || dragObject.startTop)
dragObject.oldLeft = touch.pageX
dragObject.oldTop = touch.pageY
if (this.imgWidth * dragObject.zoom > this.elWidth) {
if (Math.abs(this.mLeft) > this.reckonWidth(dragObject.zoom)) xx *= 0.3
this.mLeft += xx
}
if (this.imgHeight * dragObject.zoom > this.elHeight) {
if (Math.abs(this.mTop) > this.reckonHeight(dragObject.zoom)) yy *= 0.3
this.mTop += yy
}
},
touchEnd()触发结束事件,计算滑动后的位置,并执行动画事件continueTranslate()
/**
* 解发结束
* @param {Number} dragDuration 间隔
*/
touchEnd(dragDuration) {
....
this.continueTranslate(top, left, this.mLeft, this.mTop)
},
continueTranslate()动画事件,借助requestAnimationFrame()方法
/**
* 继续执行一段距离滑行
* @param {Number} top 将要到达的top值
* @param {Number} left 将要到达的left值
* @param {Number} oldX 动画执行前left值
* @param {Number} oldY 动画执行前top值
*/
continueTranslate(top, left, oldX, oldY) {
this.animating = true
const xx = left - oldX
const yy = top - oldY
let diffX = 0
let diffY = 0
let ALPHA = 0.88
const animationLoop = () => {
ALPHA *= 0.95
const resultX = Math.abs(diffX - xx) < 1
const resultY = Math.abs(diffY - yy) < 1
if (resultX && resultY) {
this.animating = false
this.mLeft = left
this.mTop = top
} else {
diffX = diffX * ALPHA + (1 - ALPHA) * xx
diffY = diffY * ALPHA + (1 - ALPHA) * yy
if (!resultX) this.mLeft = oldX + diffX
if (!resultY) this.mTop = oldY + diffY
animationFrame(animationLoop)
}
}
animationLoop()
},
touchTwoMove()放缩滑动事件
/**
* 放缩移动
*/
touchTwoMove(e) {
this.scrolling = true
const dragObject = this.dragObject
const touch = e.touches[0]
const touch2 = e.touches[1]
const diffX = touch.pageX - touch2.pageX
const diffY = touch.pageY - touch2.pageY
const line = Math.pow((diffX * diffX + diffY * diffY), 0.5) - this.starLine
let zoom = Number(dragObject.zoom + (line / 2 / 75))
if (zoom < 1) zoom = 1 - (1 - zoom) * 0.15
if (zoom > this.compress) zoom = this.compress + (zoom - 3) * 0.2
this.zoom = zoom
this.mLeft = dragObject.leftThan * this.reckonWidth(zoom)
this.mTop = dragObject.topThan * this.reckonHeight(zoom)
},
touchEnd()事件,当touches.length===0才执行事件,区分滑动事件、单击、双击事件。
$el.addEventListener('touchend', (e) => {
if (this.animating || e.touches.length > 0) return
const dragObject = this.dragObject
// 单次间隔时长
const duration = new Date() - this.dragObject.startTime
let zoom = this.zoom
if (this.isTouch) {
// 滑动事件
clearTimeout(this.timeFunc)
this.timeFunc = null
// 滑动执行事件
if (!this.scrolling) this.touchEnd(duration)
// 放缩执行事件
if (this.scrolling) {
if (zoom > this.compress) zoom = this.compress
if (zoom < 1) zoom = 1
if (dragObject.leftThan) this.mLeft = dragObject.leftThan * this.reckonWidth(zoom)
if (dragObject.topThan) this.mTop = dragObject.topThan * this.reckonHeight(zoom)
}
this.isTouch = false
this.zoom = zoom
this.scrolling = false
this.starLine = 0
this.dragObject = {}
} else {
// 俩次点击时长<250双击
if (dragObject.duration && dragObject.duration < 250) {
// 双击事件
clearTimeout(this.timeFunc)
this.timeFunc = null
this.zoom = zoom > 1 ? 1 : 2
this.mLeft = this.mTop = 0
this.dragObject = {}
} else {
// 单击事件
if (this.timeFunc) return
this.timeFunc = setTimeout(() => {
this.timeFunc = null
this.dragObject = {}
this.startTime = null
this.zoom = 1
this.mLeft = this.mTop = 0
this.$emit('input', false)
}, 250)
}
}
})
结束...
效果图
扫码预览
欢迎buging
pc 图片预览放大 端vue_移动端Vue.js的图片预览组件,支持放缩、滑动功能!相关推荐
- vue本地上传并预览php,vue.js 实现图片本地预览 裁剪 压缩 上传功能
以下代码涉及 Vue 2.0 及 ES6 语法. 目标 纯 javascrpit 实现,兼容ie9及以上浏览器,在本地做好文件格式.长宽.大小的检测,减少浏览器交互. 现实是残酷的,为了兼容Ie9 还 ...
- vue 图片裁剪工具_使用Vue.js的图片裁剪工具,包括预览
vue 图片裁剪工具 Vue作物 (vue-crop) Images Crop tool with Vue.js including preview. 使用Vue.js的图片裁剪工具,包括预览. Vi ...
- 本地如何预览php文件上传,如何实现js上传图片本地预览同时支持预览截图的功能...
在项目中经常会用到js上传图片本地预览的效果,同时需要在预览图上直接预览截图的范围. 下面是我写的简单的demo,是用js结合cropper.js模拟实现此项前端的功能,后台则不考虑. 准备:引入文件 ...
- 计算机毕业设计SpringBoot+Vue.js学前教育图片智能识别系统(百度AI平台)
功能 本系统七个部分分别是用户管理模块.用户信息模块.用户留言模块.管理员模块.图片识别模块.学习收藏模块,它们的功能如下: (1) 用户管理模块 用户管理模块包含了注册(账号.昵称.密码).登录(不 ...
- 在vue.js引用图片的问题
<div id="img"> <img src="img.png" class="img"> </div> ...
- VUE.JS 实现图片随鼠标变换的动画效果
先来看演示效果 首先我们设置一个这样的图片样式 <template><div class="login100-pic"><img src=" ...
- vue——js实现图片/文件的拖拽上传(复制粘贴就能用,还有优化空间)
首先先创建元素容器 <template><div id="drop"><span v-show="isUpload" class= ...
- vue.js实现图片、视频文件压缩后再上传
这里只展示图片上传代码 在这里插入代码片 ``` //html部分// 上传图片<div class="fileBox"><span class="fi ...
- layui日期与vue_详解Vue.js和layui日期控件冲突问题解决办法
详解Vue.js和layui日期控件冲突问题解决办法 发布于 2020-8-10| 复制链接 摘记: 事故还原: 今天在用layui的日期控件的时候发现一个问题,就是form表单中的日期选择之后,如果 ...
最新文章
- Solr 4.x定时、实时增量索引 - 修改、删除和新增索引
- 经验 | OpenCV图像旋转的原理与技巧
- 能打开java文件_用java打开一个本地文件
- freemaker介绍及常见的用法解析
- led拼接屏报价_LED拼接屏的装饰
- jenkins与SonarQube集成
- Java:Overriding与Overloading
- 23. 客户默认选项(Default Customer Options)
- 树算法系列之三:GBDT
- Leetcode 372.超级次方
- OpenGL.Superbible.7th.Edition(openGL超级宝典第七版)随书例子运行
- 【Unity Shaders】ShadowGun系列之一——飞机坠毁的浓烟效果
- HTML做一个节日页面【六一儿童节】纯HTML代码
- html页面嵌入百度地图
- 网络编程(二)- 检查网络的工具
- sql中如何按拼音笔画排序
- 讯时O口MX8网关对接昆石软交换vos3000
- python实现从oracle读数据写入mysql(1)
- figma的一些用法(一)
- Ubuntu系统SSH免密登录,以及SSH免密登录原理
热门文章
- Spring JdbcTemplate查询实例
- 关于错误提示:此实现不是 Windows 平台 FIPS 验证的加密算法的一部分的解决方案...
- PHP SOAP 教程 实例一
- Composer The openssl extension is required for SSL/TLS protection
- PHP CURL 多线程 GET/POST 类
- ELK的What files do you want me to watch? Exiting: no modules or inputs enabled and configuration
- Bug之PHPMailer附件名字不支持中文的
- auto errored after 报错解决_MySQL5.7 group_by报错问题解决办法,大部分程序员都收藏了...
- java 只显示文本文件_Java设计并实现一个应用程序,能够读取一个文本文件中的内容并显示,同时能够计算出文本中的行数。...
- ddr5内存上市时间_辣评烩:SK海力士首发DDR5内存:频率冲上5600MHz