pc 图片预览放大 端vue_移动端Vue.js的图片预览组件,支持放缩、滑动功能!
功能:圖片預(yù)覽組件,支持雙手指放大/縮小,雙擊放大/縮小,單擊消失隱藏。
注:touch事件請手機(jī)預(yù)覽
源碼分享
組件參數(shù)
data() {
return {
loading: 2, // 1成功 2正在加載 3error失敗
dragObject: {},
starLine: 0, // 初始倆個點(diǎn)第1次距離
zoom: 1, // 放縮比
compress: null, // 最大壓縮比
elWidth: null, // 外層寬度
elHeight: null, // 外層高度
imgWidth: null, // 當(dāng)前圖片寬度
imgHeight: null, // 當(dāng)前圖片高度
mTop: 0, // margin-top 值
mLeft: 0, // margin-left 值
isTouch: false, // 是否touch
scrolling: false, // 是否放縮
animating: false, // 是否動畫中
isTwoClick: false, // 是否雙擊
startTime: null, // 第一次時間
timeFunc: null, // 定時器
}
},
組件初始化init(),dom綁定事件,區(qū)分滑動事件、單擊、雙擊事件
/**
* 初始化事件
* @param {Object} $el 當(dāng)前DOM
*/
init($el) {
this.elWidth = document.documentElement.clientWidth
this.elHeight = document.documentElement.clientHeight
$el.addEventListener('touchstart', (e) => {
if (this.animating) return
// 記錄點(diǎn)擊時間和第二次點(diǎn)擊的時差
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) => {
....
}
})
圖片加載完后執(zhí)行imgLoad()事件,設(shè)置圖片初始顯示的寬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
},
滑動開始,區(qū)分放縮事件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()滑動開始事件
/**
* 觸發(fā)開發(fā)
*/
touchStart(e) {
const touch = e.touches[0]
if (e.touches.length > 1) {
// 放縮初始倆點(diǎn)的距離
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()觸發(fā)滑動事件
/**
* 觸發(fā)移動
*/
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()觸發(fā)結(jié)束事件,計算滑動后的位置,并執(zhí)行動畫事件continueTranslate()
/**
* 解發(fā)結(jié)束
* @param {Number} dragDuration 間隔
*/
touchEnd(dragDuration) {
....
this.continueTranslate(top, left, this.mLeft, this.mTop)
},
continueTranslate()動畫事件,借助requestAnimationFrame()方法
/**
* 繼續(xù)執(zhí)行一段距離滑行
* @param {Number} top 將要到達(dá)的top值
* @param {Number} left 將要到達(dá)的left值
* @param {Number} oldX 動畫執(zhí)行前l(fā)eft值
* @param {Number} oldY 動畫執(zhí)行前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()事件,當(dāng)touches.length===0才執(zhí)行事件,區(qū)分滑動事件、單擊、雙擊事件。
$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
// 滑動執(zhí)行事件
if (!this.scrolling) this.touchEnd(duration)
// 放縮執(zhí)行事件
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 {
// 倆次點(diǎn)擊時長<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)
}
}
})
結(jié)束...
效果圖
掃碼預(yù)覽
歡迎buging
總結(jié)
以上是生活随笔為你收集整理的pc 图片预览放大 端vue_移动端Vue.js的图片预览组件,支持放缩、滑动功能!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 也能当平板使用平板电脑可以当平板用吗
- 下一篇: php数学函数,加(bcadd)、减(b