// 图片查看类,支持放大缩小旋转图片
class ViewImg {
constructor (config = {}) {
if (new.target !== undefined) {
this.width = config.width || 300
this.height = config.height || 300
this.create()
} else {
throw new Error('请通过new 方法调用')
}
}
touchStart (e) {
e.preventDefault()
e.stopPropagation()
// 判断 是否是两指缩放
if (e.touches.length > 1) {
this.pinch = true
this.drag = false
this.startPoint = {
x: e.touches[0].screenX,
y: e.touches[0].screenY,
x1: e.touches[1].screenX,
y1: e.touches[1].screenY,
}
return
} else {
this.drag = true
this.pinch = false
this.startPoint = {
x: e.changedTouches[0].screenX,
y: e.changedTouches[0].screenY
}
this.startDragTime = new Date().getTime()
}
}
touchMove (e) {
e.preventDefault()
e.stopPropagation()
let tnow = Date.now()
if (this.pinch && tnow - this.startDragTime > 100) {
// 缩放
let ts = Math.sqrt(Math.pow(Math.abs(this.startPoint.x - this.startPoint.x1),2), Math.pow(Math.abs(this.startPoint.y - this.startPoint.y1), 2))
let te = Math.sqrt(Math.pow(Math.abs(e.changedTouches[0].screenX - e.changedTouches[1].screenX), 2), Math.pow(Math.abs(e.changedTouches[0].screenY - e.changedTouches[1].screenY), 2))
this.startPoint = {
x: e.changedTouches[0].screenX,
y: e.changedTouches[0].screenY,
x1: e.changedTouches[1].screenX,
y1: e.changedTouches[1].screenY,
}
if (ts - te > 1.5) {
if (this.transform.scale > 0.2) {
this.transform.scale -= 0.1
} else {
this.transform.scale = 0.2
}
} else if (te - ts > 1.5) {
if (this.transform.scale < 5) {
this.transform.scale += 0.1
} else {
this.transform.scale = 5
}
}
this.drawIt()
return
}
// 移动
if (this.drag && tnow - this.startDragTime > 100) {
this.startDragTime = tnow
let tobj = [
e.changedTouches[0].screenX - this.startPoint.x,
e.changedTouches[0].screenY - this.startPoint.y
]
this.transform.tmptranslate = tobj
this.drawIt()
}
}
mouseDown (e) {
e.preventDefault()
e.stopPropagation()
this.drag = true
this.startPoint = {
x: e.screenX,
y: e.screenY
}
this.startDragTime = new Date().getTime()
}
mouseMove (e) {
e.preventDefault()
e.stopPropagation()
let tnow = Date.now()
if (this.drag && tnow - this.startDragTime > 100) {
this.startDragTime = tnow
let tobj = [
e.screenX - this.startPoint.x,
e.screenY - this.startPoint.y
]
this.transform.tmptranslate = tobj
this.drawIt()
}
}
mouseUp (e) {
if (this.drag) {
this.drag = false
this.transform.translate = [
this.transform.translate[0] + this.transform.tmptranslate[0],
this.transform.translate[1] + this.transform.tmptranslate[1],
]
this.transform.tmptranslate = [0,0]
this.drawIt()
}
}
mouseWheel (e) {
var tmps=0;
if(typeof e.wheelDelta=='number'){
tmps=-e.wheelDelta;
//普通浏览器有e.wheelDelta值,向上滚是正值120,向下滚是负值-120
}else{
tmps=e.detail;
//火狐浏览器有e.detail值,向上滚是负值-3,向下滚是正值3
}
if (tmps < 0) {
if (this.transform.scale < 5) {
this.transform.scale += 0.1
} else {
this.transform.scale = 5
}
} else {
if (this.transform.scale > 0.5) {
this.transform.scale -= 0.1
} else {
this.transform.scale = 0.5
}
}
this.drawIt()
}
create() {
let tw = window.innerWidth
let th = window.innerHeight
this.tw = tw
this.th = th
// 查看设置的裁剪比例和设备的宽高比例关系
let bili = this.width / this.height > tw / th
this.transform = {
scale: 1,
translate: [0,0],
tmptranslate: [0,0],
rotate: 0
}
// 整体裁剪框
let dik = document.createElement('div')
this.dik = dik
dik.setAttribute('style', `
position:fixed;
background:rgba(0,0,0,0.6);
margin:0;
padding:0;
left:0;top:0;
width:100%;height:100%;
z-index:9998;
`)
// 按钮
let close = document.createElement('div')
close.setAttribute('style', `
width:80px;
height:80px;
position:fixed;
right:20px;
top:20px;
z-index:1001;
text-align:Center;
line-height:80px;
cursor:pointer;
font-size:60px;
transform: rotate(45deg);
border: 1px solid #ffffff44;
border-radius:50%;
color:rgba(255,255,255,0.5);
`)
close.innerHTML = '+'
close.addEventListener('click', this.close.bind(this))
close.addEventListener('touchend', this.close.bind(this))
dik.append(close)
let clickHandle = (e) => {
e.preventDefault()
e.stopPropagation()
let title = e.target.getAttribute('title') || e.target.parentNode.getAttribute('title')
switch(title) {
case '左转': {
this.transform.rotate -= 5
this.drawIt()
break
}
case '右转': {
this.transform.rotate += 5
this.drawIt()
break
}
default: {
this.transform = {
scale: 1,
translate: [0,0],
tmptranslate: [0,0],
rotate: 0
}
this.imgRect = {...this.tmpRect}
this.drawIt()
break
}
}
}
let buts = document.createElement('div')
buts.setAttribute('style', `
position: fixed;
width:350px;
height: 40px;
left: 0;
right: 0;
display:flex;
bottom: 80px;
background:rgba(0,0,0,0.3);
border-radius: 20px;
margin: auto;
border: 1px solid rgba(255,255,255,0.5);
opacity:0.6;
z-index: 10001;
`)
// 子元素
let but1 = document.createElement('div')
but1.setAttribute('style', 'width:100%;cursor: pointer;height: 40px;position:relative;')
but1.setAttribute('title', '左转');
but1.addEventListener('click', clickHandle)
but1.addEventListener('touchend', clickHandle)
let but1_icon1 = document.createElement('div')
but1_icon1.setAttribute('style', `
position:absolute;right:0;top:0;bottom:0;left:0;margin:auto;
width:24px;height:24px;border-radius:50%;
border-right:2px solid #fff;
border-top:2px solid #fff;
`)
let but1_icon2 = document.createElement('div')
but1_icon2.setAttribute('style', `
position:absolute;right:0;top:0;bottom:0;left:-18px;margin:auto;
width:6px;height:6px;border:6px solid transparent;
border-top-color:#fff;
`)
but1.append(but1_icon1);
but1.append(but1_icon2);
let but2 = document.createElement('div')
but2.setAttribute('style', 'width:100%;cursor: pointer;height: 40px;position:relative;')
but2.setAttribute('title', '右转');
but2.addEventListener('click', clickHandle)
but2.addEventListener('touchend', clickHandle)
let but2_icon1 = document.createElement('div')
but2_icon1.setAttribute('style', `
position:absolute;right:0;top:0;bottom:0;left:0;margin:auto;
width:24px;height:24px;border-radius:50%;
border-left:2px solid #fff;
border-top:2px solid #fff;
`)
let but2_icon2 = document.createElement('div')
but2_icon2.setAttribute('style', `
position:absolute;right:-18px;top:0;bottom:0;left:0;margin:auto;
width:6px;height:6px;border:6px solid transparent;
border-top-color:#fff;
`)
but2.append(but2_icon1);
but2.append(but2_icon2);
let but3 = document.createElement('div')
but3.setAttribute('title', '复位');
but3.setAttribute('style', 'width:100%;cursor: pointer;height: 40px;position:relative;')
but3.addEventListener('click', clickHandle)
but3.addEventListener('touchend', clickHandle)
let but3_icon1 = document.createElement('div')
but3_icon1.setAttribute('style', `
position:absolute;right:0;top:0;bottom:0;left:0;margin:auto;
width:24px;height:24px;border-radius:50%;
border-bottom:2px solid #fff;
border-top:2px solid #fff;
`)
let but3_icon2 = document.createElement('div')
but3_icon2.setAttribute('style', `
position:absolute;right:0;top:0;bottom:0;left:0;margin:auto;
width:6px;height:6px;border:1px solid #fff;
`)
but3.append(but3_icon1);
but3.append(but3_icon2);
buts.append(but1)
buts.append(but2)
buts.append(but3)
dik.append(buts)
// 根据不同端绑定事件
if (tw > 900) {
// pc端
dik.addEventListener('mousedown', this.mouseDown.bind(this))
dik.addEventListener('mousemove', this.mouseMove.bind(this))
dik.addEventListener('mouseup', this.mouseUp.bind(this))
if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
// 火狐浏览器
dik.addEventListener('DOMMouseScroll', this.mouseWheel.bind(this))
} else {
dik.addEventListener('mousewheel', this.mouseWheel.bind(this))
}
} else {
// 手机端事件
dik.addEventListener('touchstart', this.touchStart.bind(this))
dik.addEventListener('touchmove', this.touchMove.bind(this))
// 结束函数与鼠标一致
dik.addEventListener('touchend', this.mouseUp.bind(this))
}
// 算出同比下设备上应该显示的宽或高
let sh = bili ? (th * this.width/this.height - th*0.1): (th *0.9) // 高
sh = sh > this.height ? this.height:sh
let sw = sh * this.width / this.height // 宽
let sl = (tw - sw) / 2
let st = (th - sh) / 2
this.rect = {sl, st, sw, sh} // 缓存当前裁剪框位置
}
show (src) {
// 设置裁剪的图片, 需要传入图片文件
let img = new Image()
this.img = img
// 加入到dom树中
this.dik.append(this.img)
document.body.append(this.dik)
img.onload = () => {
let timgw = this.rect.sw + 400
let timgh = img.height / img.width * timgw
this.imgRect = {
imgl: this.rect.sl - 200,
imgt: (this.th - timgh) / 2,
imgw: timgw,
imgh: timgh,
}
this.tmpRect = Object.assign({}, this.imgRect)
this.drawIt()
}
img.src = src
}
drawIt () {
let arr = this.transform.tmptranslate
let tranx = this.transform.translate[0]
let trany = this.transform.translate[1]
if (arr && arr.length) {
tranx += arr[0]
trany += arr[1]
}
this.img.setAttribute('style', `
position: fixed;
margin:0;
display:block;
box-sizing:border-box;
z-index: 99;
left: ${this.imgRect.imgl}px;
top: ${this.imgRect.imgt}px;
width: ${this.imgRect.imgw}px;
height: ${this.imgRect.imgh}px;
transform:rotate(${this.transform.rotate}deg) translate(${tranx}px,${trany}px) scale(${this.transform.scale},${this.transform.scale});
transform-origin: 50% 50%;
`)
}
close () {
// 关闭
this.dik.removeChild(this.img)
document.body.removeChild(this.dik)
this.transform = {
scale: 1,
translate: [0,0],
tmptranslate: [0,0],
rotate: 0
}
this.img = null
}
}
// 绑定所有事件
const viewImg = new ViewImg()
const allImages = document.getElementsByTagName('img')
for (let img of allImages) {
img.onclick = () => {img.src && viewImg.show(img.src)}
}
js-手写预览图片对象,兼容手机端
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- https://www.cnblogs.com/-roc/p/14592130.html[https://www....