zx-image-viewer
Version:
259 lines (239 loc) • 8.06 kB
JavaScript
/**
* Create by capricorncd
* 2018/5/16 0016.
* https://github.com/capricorncd
*/
import util from './util'
import dom from './dom'
import WinSize from './window-size'
import { touchEvents } from './touch-event'
import { getTouches, handleTouches } from './touch-zoom'
// 缩小最小尺寸限制
const MIN_SIZE = 60
const win = new WinSize()
// 边界限制,屏幕宽度的30%
const boundary = win.width * 0.3
export default {
/**
* 缩放
* @param $img 缩放对象
* @param wheelDelta > 0放大或 < 0缩小
*/
scale ($img, wheelDelta, isTouches) {
let scaleRatio = isTouches ? 0.02 : 0.4
if (wheelDelta > 0) {
// 放大
this._scaleHandler($img, true, scaleRatio)
} else {
// 缩小
this._scaleHandler($img, false, scaleRatio)
}
},
// @param isEnlarge 是否放大
_scaleHandler ($img, isEnlarge, scaleRatio) {
let naturalWidth = $img.naturalWidth
// let naturalHeight = $img.naturalHeight
let imgWidth = $img.width
let imgHeight = $img.height
let iw, ih
if (isEnlarge) {
iw = imgWidth * (1 + scaleRatio)
// 最大放大2倍
if (iw >= naturalWidth * 3) return
} else {
// 图片实际尺寸小于最小限制尺寸
if (naturalWidth < MIN_SIZE) return
iw = imgWidth * (1 - scaleRatio)
if (iw <= MIN_SIZE) return
}
ih = iw * imgHeight / imgWidth
$img.style.width = iw + 'px'
$img.style.height = ih + 'px'
// 图片增加的宽度、高度
let addW = iw - imgWidth
let addH = ih - imgHeight
let css = util.getStyleValue($img)
$img.style.top = util.int(util.toNumber(css.top) - addH / 2) + 'px'
$img.style.left = util.int(util.toNumber(css.left) - addW / 2) + 'px'
},
// 旋转
rotate ($img, angle) {
// ie9及以下浏览器禁用旋转
if (util.isLeIE9()) angle = 0
// console.error(angle)
$img.style.transform = `rotate(${angle}deg)`
// console.log(this.$img)
this._initImagePosition($img, angle)
},
// 移动, 拖动
move ($img) {
// 鼠标在图片上按下
let isMousedownOnImage = false
// isTouchEvent
let isTouchEvent = false
// 鼠标按下位置图片左上角位置
let moveBeforePostion = {}
// 图片是否旋转
let isRotate = false
// 图片宽高差
let halfImgSizeDifference = 0
// 竖图
let isVerticalImage = false
// 手指数量
let fingers = 0
let startTouches = []
// 开始
$img.addEventListener(touchEvents.start, e => {
// log(e.type)
// 防止触发浏览器图片拖动行为
e.preventDefault()
isMousedownOnImage = true
isTouchEvent = e.type === 'touchstart'
if (isTouchEvent) {
fingers = e.touches.length
}
if (fingers > 1) {
startTouches = getTouches(e, $img)
}
// prevent user enter with right and the swiper move (needs isTouchEvent)
if (!isTouchEvent && 'which' in e && e.which === 3) {
isMousedownOnImage = false
return
}
if (!isTouchEvent || e.targetTouches.length === 1) {
if (!isTouchEvent && !util.isAndroid()) {
if (e.preventDefault) {
e.preventDefault()
} else {
e.returnValue = false
}
}
let pageX = isTouchEvent ? e.targetTouches[0].pageX : (e.pageX || e.clientX)
let pageY = isTouchEvent ? e.targetTouches[0].pageY : (e.pageY || e.clientY)
moveBeforePostion.x = pageX - $img.offsetLeft
moveBeforePostion.y = pageY - $img.offsetTop
dom.rmClass($img, 'v-transition')
}
// 是否旋转
let angle = $img.getAttribute('rotate-angle')
if (/^(\d+)/.test(angle)) {
isRotate = RegExp.$1 / 90 % 2 === 1
}
// 图片宽高差
let imgPos = $img.getBoundingClientRect()
halfImgSizeDifference = Math.abs(imgPos.width - imgPos.height) / 2
// 竖图
isVerticalImage = $img.width < $img.height
})
// 拖动
document.addEventListener(touchEvents.move, e => {
if (!isMousedownOnImage) return
if (!isTouchEvent && !util.isAndroid()) {
if (e.preventDefault) {
e.preventDefault()
} else {
e.returnValue = false
}
}
if (fingers > 1) {
let scale = handleTouches(e, startTouches)
this._scaleHandler($img, scale > 1, 0.04)
} else {
handleMove(e, $img, moveBeforePostion, isTouchEvent, isRotate, isVerticalImage, halfImgSizeDifference)
}
})
// 释放鼠标
document.addEventListener(touchEvents.end, e => {
isMousedownOnImage = false
dom.addClass($img, 'v-transition')
})
},
// 设置图片显示尺寸及位置
_initImagePosition ($img, angle) {
// 是否旋转
const isRotate = util.int(angle / 90) % 2
let imgWidth, imgHeight, iw, ih, winRatio, imgRatio
// 屏幕尺寸
const winWidth = window.innerWidth
const winHeight = window.innerHeight
winRatio = winWidth / winHeight
// 图片原始尺寸
imgWidth = $img.naturalWidth
imgHeight = $img.naturalHeight
imgRatio = imgWidth / imgHeight
if (isRotate) {
imgRatio = imgHeight / imgWidth
if (imgRatio > winRatio) {
ih = imgHeight > winWidth * 0.9 ? winWidth * 0.9 : imgHeight
iw = ih * imgWidth / imgHeight
$img.style.width = iw + 'px'
$img.style.height = ih + 'px'
// $img.style.top = (winHeight - ih) / 2 + 'px'
} else {
iw = imgWidth > winHeight * 0.9 ? winHeight * 0.9 : imgWidth
ih = iw * imgHeight / imgWidth
$img.style.width = iw + 'px'
$img.style.height = ih + 'px'
}
// $img.style.top = (winHeight - ih) / 2 + 'px'
// $img.style.left = (winWidth - iw) / 2 + 'px'
} else {
if (imgRatio > winRatio) {
iw = imgWidth > winWidth * 0.9 ? winWidth * 0.9 : imgWidth
ih = iw * imgHeight / imgWidth
$img.style.width = iw + 'px'
$img.style.height = ih + 'px'
// $img.style.top = (winHeight - ih) / 2 + 'px'
} else {
ih = imgHeight > winHeight * 0.9 ? winHeight * 0.9 : imgHeight
iw = ih * imgWidth / imgHeight
$img.style.width = iw + 'px'
$img.style.height = ih + 'px'
}
}
$img.style.top = (winHeight - ih) / 2 + 'px'
$img.style.left = (winWidth - iw) / 2 + 'px'
// console.log(winWidth, winHeight)
// console.log(iw, ih)
// console.log(imgRatio, winRatio)
}
}
function handleMove (e, $img, moveBeforePostion, isTouchEvent, isRotate, isVerticalImage, halfImgSizeDifference) {
let pageX = isTouchEvent ? e.targetTouches[0].pageX : (e.pageX || e.clientX)
let pageY = isTouchEvent ? e.targetTouches[0].pageY : (e.pageY || e.clientY)
let l = pageX - moveBeforePostion.x
let t = pageY - moveBeforePostion.y
// ie11 无x/y属性
let imgPos = $img.getBoundingClientRect()
// Boundary restriction
// Right boundary
let rightBoundary = isRotate
? (isVerticalImage ? win.width + halfImgSizeDifference - boundary : win.width - halfImgSizeDifference - boundary)
: win.width - boundary
if (rightBoundary <= l) {
l = rightBoundary
}
// Left boundary
let leftBoundary = isRotate
? (isVerticalImage ? boundary - imgPos.width + halfImgSizeDifference : boundary - imgPos.width - halfImgSizeDifference)
: boundary - imgPos.width
if (l <= leftBoundary) {
l = leftBoundary
}
// Bottom boundary
let bottomBoundary = isRotate
? (isVerticalImage ? win.height - halfImgSizeDifference - boundary : win.height + halfImgSizeDifference - boundary)
: win.height - boundary
if (bottomBoundary <= t) {
t = bottomBoundary
}
// Top boundary
let topBoundary = isRotate
? (isVerticalImage ? boundary - imgPos.height - halfImgSizeDifference : boundary - imgPos.height + halfImgSizeDifference)
: boundary - imgPos.height
if (t <= topBoundary) {
t = topBoundary
}
$img.style.left = l + 'px'
$img.style.top = t + 'px'
}