weaver_trunk_cli/pc4mobx/esearch/public/wea-zmage/components/Wrapper/index.js

216 lines
5.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 包裹层
* 储存主要状态,组织架构
**/
// React Libs
import React from 'react'
import ReactDOM from 'react-dom'
// Style
import './index.less'
// Components
import Position from '../Position'
import Control from '../Control'
import Image from '../Image'
import Background from '../Background'
import {addListenEventOf, removeListenEventOf} from '../../utils'
class Wrapper extends React.Component {
constructor(props) {
super(props)
this.state = {
// 显示
show: false,
// 缩放
zoom: false,
// 当前页数
page: props.page || 0
}
}
componentWillReceiveProps(nextProps) {
if (this.props.page != nextProps.page) {
this.setState({page: nextProps.page});
}
}
componentWillMount() {
// 延迟 100 毫秒加载自己,保证动画正常
setTimeout(this.mountSelf, 50)
}
componentWillUnmount() {
removeListenEventOf('keydown', this.handleKeyDown)
removeListenEventOf('wheel', this.handleWheelScroll)
}
/**
* 加载器
**/
mountSelf = () => {
const {coverNodeRef} = this.props
// 隐藏封面原图
// if (coverNodeRef) coverNodeRef.style.visibility = 'hidden'
// 显示并绑定事件
this.setState({show: true}, () => {
addListenEventOf('keydown', this.handleKeyDown)
addListenEventOf('wheel', this.handleWheelScroll)
})
}
unmountSelf = () => {
const {coverNodeRef} = this.props
const {page} = this.state
// 显示封面原图(当前不为第一页时,遮罩从上方移除会迅速露出,需要立即显示,否则交由图片层处理)
if (coverNodeRef && page !== 0) coverNodeRef.style.visibility = 'visible'
this.setState({show: false})
}
/**
* 事件处理
**/
handleKeyDown = (e) => {
// 阻止默认事件
e.preventDefault()
const {imageSet} = this.props
const {zoom} = this.state
const hasImageSet = imageSet && imageSet.constructor === Array
const toPrevPage = this.handleSwitchPages("prev")
const toNextPage = this.handleSwitchPages("next")
switch (e.key) {
case "ArrowLeft":
// 上一张
!zoom && toPrevPage()
break
case "ArrowRight":
// 下一张
!zoom && hasImageSet && toNextPage()
break
case " ":
// 缩放
this.handleToggleZoom()
break
case "Escape":
// 退出
zoom ? this.handleToggleZoom() : this.unmountSelf()
break
default:
return
}
}
handleWheelScroll = (e) => {
this.state.show && this.unmountSelf()
}
/**
* 翻页控制
**/
handleSwitchPages = (direction) => {
return () => {
const {imageSet} = this.props
const {page} = this.state
this.setState({
page: direction === "prev" ?
Math.abs(imageSet.length + page - 1) % imageSet.length :
(page + 1) % imageSet.length
})
}
}
/**
* 缩放控制
**/
handleToggleZoom = () => {
this.setState({
zoom: !this.state.zoom
})
}
render() {
const {coverNodeRef, imageSet, remove} = this.props
const {show, zoom, page} = this.state
return (
<div className="wrapperLayer">
{/*控制层*/}
<Control
show={show}
zoom={zoom}
page={page}
imageSet={imageSet}
unmountSelf={this.unmountSelf}
toggleZoom={this.handleToggleZoom}
switchPages={this.handleSwitchPages}
/>
{/*位移控制层*/}
<Position
show={show}
zoom={zoom}
page={page}
imageSet={imageSet}
coverNodeRef={coverNodeRef}
>
{/*图片层*/}
<Image
show={show}
zoom={zoom}
page={page}
imageSet={imageSet}
coverNodeRef={coverNodeRef}
remove={remove}
/>
</Position>
{/*背景层*/}
<Background
show={show}
unmountSelf={this.unmountSelf}
toggleZoom={this.handleToggleZoom}
/>
</div>
)
}
}
// 主动调用显示插入控件到指定节点Body末端
const showImage = ({id, lazyLoad, indicator, imageSet, page}) => {
// 封面节点
const coverNodeRef = document.getElementById(id)
// 容器节点
const wrapperNodeId = `zmage-wrapper`
const previousOverlayNode = document.getElementById(wrapperNodeId)
previousOverlayNode && previousOverlayNode.remove()
const wrapperNode = document.createElement('div')
wrapperNode.id = wrapperNodeId
document.body.appendChild(wrapperNode)
const wrapperNodeRef = document.getElementById(wrapperNodeId)
//移除函数
const remove = () => {
ReactDOM.unmountComponentAtNode(wrapperNodeRef)
wrapperNodeRef.remove()
}
// 插入容器节点
wrapperNodeRef && ReactDOM.render(
<Wrapper
coverNodeRef={coverNodeRef}
lazyLoad={lazyLoad}
indicator={indicator}
imageSet={imageSet}
remove={remove}
page={page}
/>, wrapperNodeRef)
// 对于函数调用模式,返回容器节点引用, 调用 remove() 即可移除(无动画)
return {
node: wrapperNodeRef,
remove: remove
}
}
export {showImage, Wrapper}