import React, {Component} from 'react'
|
import {
|
RotateLeftOutlined,
|
RotateRightOutlined,
|
CloseOutlined,
|
ZoomOutOutlined,
|
ZoomInOutlined,
|
LeftOutlined,
|
RightOutlined
|
} from '@ant-design/icons'
|
|
import MKEmitter from '@/utils/events.js'
|
import './index.scss'
|
|
class ImgScale extends Component {
|
state = {
|
className: 'close',
|
url: '',
|
list: [],
|
scale: 1,
|
rotate: 0,
|
index: 0
|
}
|
|
imgNode = null
|
wrapNode = null
|
visible = false
|
originPositionRef = null
|
position = {x: 0, y: 0}
|
|
componentDidMount () {
|
MKEmitter.addListener('mkImageScale', this.mkImageScale)
|
}
|
|
componentWillUnmount () {
|
this.setState = () => {
|
return
|
}
|
MKEmitter.removeListener('mkImageScale', this.mkImageScale)
|
}
|
|
mkImageScale = (src, list = []) => {
|
const { url } = this.state
|
|
if (url || !src) return
|
|
let index = 0
|
let _list = []
|
|
if (list.length > 1) {
|
index = list.indexOf(src)
|
_list = list
|
}
|
|
this.setState({url: src, className: 'opening', list: _list, scale: 1, rotate: 0, index, position: {x: 0, y: 0}})
|
setTimeout(() => {
|
this.setState({className: 'open'})
|
|
window.addEventListener('mouseup', this.onMouseUp)
|
window.addEventListener('mousemove', this.onMouseMove)
|
window.addEventListener('wheel', this.onWheelMove, {passive: false})
|
this.imgNode && this.imgNode.addEventListener('mousedown', this.onMouseDown)
|
this.wrapNode.style.transform = 'translate3d(0px, 0px, 0px)'
|
|
this.position = {x: 0, y: 0}
|
this.originPositionRef = {
|
originX: 0,
|
originY: 0,
|
deltaX: 0,
|
deltaY: 0
|
}
|
}, 300)
|
}
|
|
onMouseDown = (e) => {
|
e.preventDefault()
|
e.stopPropagation()
|
|
this.visible = true
|
|
this.originPositionRef.deltaX = e.pageX
|
this.originPositionRef.deltaY = e.pageY
|
this.originPositionRef.originX = this.position.x
|
this.originPositionRef.originY = this.position.y
|
}
|
|
onMouseUp = (e) => {
|
const { scale, rotate } = this.state
|
this.visible = false
|
|
if (!this.imgNode) return
|
|
let isRotate = rotate % 180 !== 0
|
|
let nodeWidth = this.imgNode.offsetWidth * scale
|
let nodeHeight = this.imgNode.offsetHeight * scale
|
let winWidth = window.innerWidth
|
let winHeight = window.innerHeight
|
let width = isRotate ? nodeHeight : nodeWidth
|
let height = isRotate ? nodeWidth : nodeHeight
|
|
let x = this.position.x
|
let y = this.position.y
|
|
if (width <= winWidth && height <= winHeight) {
|
x = 0
|
y = 0
|
} else {
|
x = this.fixPoint(x, width, winWidth)
|
y = this.fixPoint(y, height, winHeight)
|
}
|
|
this.position.x = x
|
this.position.y = y
|
|
this.wrapNode.style.transform = `translate3d(${this.position.x}px, ${this.position.y}px, 0px)`
|
}
|
|
fixPoint(start, width, clientWidth) {
|
let startAddWidth = start + width
|
let offsetStart = (width - clientWidth) / 2
|
|
if (width > clientWidth) {
|
if (start > 0) {
|
return offsetStart
|
}
|
|
if (start < 0 && startAddWidth < clientWidth) {
|
return -offsetStart
|
}
|
} else if (start < 0 || startAddWidth > clientWidth) {
|
return start < 0 ? offsetStart : -offsetStart
|
}
|
|
return start
|
}
|
|
onMouseMove = (e) => {
|
if (!this.visible) return
|
|
e.preventDefault()
|
e.stopPropagation()
|
|
let x = e.pageX - this.originPositionRef.deltaX
|
let y = e.pageY - this.originPositionRef.deltaY
|
|
this.position.x = this.originPositionRef.originX + x
|
this.position.y = this.originPositionRef.originY + y
|
|
this.wrapNode.style.transform = `translate3d(${this.position.x}px, ${this.position.y}px, 0px)`
|
}
|
|
onWheelMove = (e) => {
|
e.preventDefault()
|
let delta = -e.wheelDelta || e.deltaY
|
|
if (delta > 0) {
|
this.zoomOut()
|
} else if(delta < 0) {
|
this.zoomIn()
|
}
|
|
this.position.x = 0
|
this.position.y = 0
|
this.wrapNode.style.transform = `translate3d(${this.position.x}px, ${this.position.y}px, 0px)`
|
}
|
|
close = () => {
|
this.setState({className: 'closeing'})
|
|
this.visible = false
|
|
this.imgNode && this.imgNode.removeEventListener('mousedown', this.onMouseDown)
|
window.removeEventListener('mouseup', this.onMouseUp)
|
window.removeEventListener('mousemove', this.onMouseMove)
|
window.removeEventListener('wheel', this.onWheelMove)
|
|
setTimeout(() => {
|
this.wrapNode.style.transform = 'translate3d(0px, 0px, 0px)'
|
this.setState({className: 'close', url: ''})
|
}, 300)
|
}
|
|
zoomIn = () => {
|
this.setState({scale: this.state.scale + 1})
|
|
this.position.x = 0
|
this.position.y = 0
|
this.wrapNode.style.transform = `translate3d(${this.position.x}px, ${this.position.y}px, 0px)`
|
}
|
|
zoomOut = () => {
|
const { scale } = this.state
|
|
if (scale === 1) return
|
|
this.setState({scale: scale - 1})
|
|
this.position.x = 0
|
this.position.y = 0
|
this.wrapNode.style.transform = `translate3d(${this.position.x}px, ${this.position.y}px, 0px)`
|
}
|
|
rotateRight = () => {
|
this.setState({rotate: this.state.rotate + 90})
|
}
|
|
rotateLeft = () => {
|
this.setState({rotate: this.state.rotate - 90})
|
}
|
|
prev = () => {
|
const { list, index } = this.state
|
|
this.setState({url: list[index - 1], index: index - 1, scale: 1, rotate: 0})
|
this.position.x = 0
|
this.position.y = 0
|
this.wrapNode.style.transform = `translate3d(${this.position.x}px, ${this.position.y}px, 0px)`
|
}
|
|
next = () => {
|
const { list, index } = this.state
|
|
this.setState({url: list[index + 1], index: index + 1, scale: 1, rotate: 0})
|
this.position.x = 0
|
this.position.y = 0
|
this.wrapNode.style.transform = `translate3d(${this.position.x}px, ${this.position.y}px, 0px)`
|
}
|
|
render() {
|
const { index, url, scale, rotate, className, list } = this.state
|
|
return (
|
<div className={'mk-preview ' + className}>
|
<div className="mk-image-preview-mask"></div>
|
<div className="mk-image-preview-wrap">
|
<div className="mk-image-preview">
|
<div className="mk-image-preview-content">
|
<div className="mk-image-preview-body">
|
<ul className="mk-image-preview-operations">
|
<li className="mk-image-preview-operations-operation" onClick={this.close}>
|
<CloseOutlined />
|
</li>
|
<li className="mk-image-preview-operations-operation" onClick={this.zoomIn}>
|
<ZoomInOutlined />
|
</li>
|
<li className={'mk-image-preview-operations-operation ' + (scale === 1 ? 'mk-image-preview-operations-operation-disabled' : '')} onClick={this.zoomOut}>
|
<ZoomOutOutlined />
|
</li>
|
<li className="mk-image-preview-operations-operation" onClick={this.rotateRight}>
|
<RotateRightOutlined />
|
</li>
|
<li className="mk-image-preview-operations-operation" onClick={this.rotateLeft}>
|
<RotateLeftOutlined />
|
</li>
|
</ul>
|
<div ref={e => (this.wrapNode = e)} className="mk-image-preview-img-wrapper">
|
{url ? <img ref={e => (this.imgNode = e)} className="mk-image-preview-img" alt="" src={url} style={{transform: `scale3d(${scale}, ${scale}, 1) rotate(${rotate}deg)`}}/> : null}
|
</div>
|
{index ? <LeftOutlined className="mk-image-preview-switch-left" onClick={this.prev}/> : null}
|
{list.length > index + 1 ? <RightOutlined className="mk-image-preview-switch-right" onClick={this.next}/> : null}
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
)
|
}
|
}
|
|
export default ImgScale
|