Extract daily business components and package them into a small plug-in, which is similar to wechat PC image preview;

Post the code below (CSS code can be found on Github).

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

import './style.less';

const R = (2 * Math.PI) / 360;
class ImageView extends Component {
  constructor(props) {
    super(props);
    const {data = [], curIndex = 0} = props;
    this.ImgWrapDom = null;
    this.ImgToolDom = null;
    this.initEvent = new CustomEvent('init');
    this.ImgViewDom = React.createRef();

    this.imgWidth = 0;
    this.state = {
      scaleImg: 100.rotateImg: 0,
      data,
      curIndex,
      show: false.minWidth: 400.minHeight: 400}; }componentDidMount() {}
  componentWillReceiveProps(){}open({data = [], curIndex = 0}) {
    this.setState({
      show: true,
      data,
      curIndex,
      scaleImg: 100.rotateImg: 0,},() = > {
      this.init();
    });
  }
  / / initialization
  init = () = > {
    // Drag data to prepare
    this.ImgToolDom = this.ImgViewDom.querySelector('.tool-wrapper');
    this.ImgWrapDom = this.ImgViewDom.querySelector('.img-wrapper');
    this.ImgDom = this.ImgWrapDom.querySelector('.cur-img');
    this.ImgMask = this.ImgWrapDom.querySelector('.mask');

    this.scaleWindow(this.ImgViewDom);

    this.drage(this.ImgToolDom, this.ImgViewDom, true);
    this.drage(this.ImgWrapDom, this.ImgDom);

    this.imgWidth = this.ImgDom.clientWidth;
  }
  / * * *@description: Drag window *@param {dom} Trigger the drag dom *@param {moveDom} Dragged DOM *@param {limit} Whether to restrict boundaries *@return {null}* /
  drage = (dom, moveDom, limit = false) = > {
    // Indicates whether the mouse is pressed in the image area
    // Mouse click on the image area
    // x, y position
    // offsetL, offsetT window offset position
    // Image initial width
    let ImgWrapClickFlag = false;
    let clickX = 0;
    let clickY = 0;
    let top = 0;
    let left = 0;

    dom.addEventListener('mousedown'.(e) = > {
      e.preventDefault();
      if (this.ImgMask.style.cursor) { return false; }
      ImgWrapClickFlag = true;
      dom.style.cursor = 'move';
      top = window.getComputedStyle(moveDom).top;
      left = window.getComputedStyle(moveDom).left;
      clickX = e.pageX;
      clickY = e.pageY;
      document.addEventListener('mousemove', move);
      document.addEventListener('mouseup', end);
    });

    dom.addEventListener('mouseup', end);
    document.addEventListener('mouseup', end);

    dom.addEventListener('init'.() = > {
      ImgWrapClickFlag = false;
      clickX = 0;
      clickY = 0;
      moveDom.style.left = 0;
      moveDom.style.top = 0;
      top = 0;
      left = 0;
    });

    function move(e) {
      if(! ImgWrapClickFlag) {return false; }
      const moveX = (e.clientX - clickX) + parseInt(left, 10);
      const moveY = (e.clientY - clickY) + parseInt(top, 10);
      const moveDomWidth = moveDom.clientWidth;
      const moveDomHeight = moveDom.clientHeight;
      const pageWidth = document.documentElement.clientWidth;
      const pageHeight = document.documentElement.clientHeight;
      if (limit) {
        if (moveDomWidth / 2 < moveX && ((moveX + (moveDomWidth / 2)) < pageWidth)) {
          moveDom.style.left = `${moveX}px`;
        }
        if (moveDomHeight / 2 < moveY && ((moveY + (moveDomHeight / 2)) < pageHeight)) {
          moveDom.style.top = `${moveY}px`;
        }
        return false;
      }
      moveDom.style.left = `${moveX}px`;
      moveDom.style.top = `${moveY}px`;
    }

    function end(e) {
      e.preventDefault();
      if(! ImgWrapClickFlag) {return false; }
      ImgWrapClickFlag = false;
      dom.style.cursor = 'default';
      document.removeEventListener('mousemove', move);
      document.removeEventListener('mouseup', end); }}/ * * *@description: Zoom image *@param {dom}
   * @param {type}
   * @return {null}* /
  scaleImgFn = (type = 'plus') = > {
    let { scaleImg = 100} = this.state;
    if ((type === 'plus' && scaleImg >= 300) || (type === 'minus' && scaleImg <= 100)) { return false; }
    scaleImg += type === 'plus' ? 10 : -10;
    this.ImgDom.style.width = `${(scaleImg / 100) * this.imgWidth}px`;
    this.setState({scaleImg});
  }
  / * * *@description: Rotation function *@param {*}
   * @return {null}* /
  rotate = () = > {
    let { rotateImg } = this.state;
    rotateImg = (rotateImg + 90) % 360;
    this.ImgDom.style.webkitTransform = `matrix(The ${Math.cos(rotateImg * R)}.The ${Math.sin(rotateImg * R)}.The ${-1 * Math.sin(rotateImg * R)}.The ${Math.cos(rotateImg * R)}`, 0, 0);
    this.setState({rotateImg});
    this.ImgWrapDom.dispatchEvent(this.initEvent);
  }
  / * * *@description: Zoom window *@param {dom} Window dom *@return {type}* /
  scaleWindow = (dom) = > {
    const { minHeight, minWidth } = this.state;
    const that = this;
    const scaleR = 20; // Stretch area radius
    let clickFlag = false;

    let pageX = 0;
    let pageY = 0;

    let winWidth = this.ImgViewDom.clientWidth;
    let winHeight = this.ImgMask.clientHeight;

    let top = 0;
    let left = 0;

    // Stretching mode 0 is not in the stretching state, 1 right line stretching, 2 bottom stretching, 3 left line stretching, 4 right line stretching, 5 lower left corner stretching
    let way = 0;
    dom.addEventListener('mousemove'.(e) = > {
      const x = e.offsetX;
      const y = e.offsetY;

      this.ImgMask.style.cursor = ' ';
      e.preventDefault();
      // Lock stretch state when mouse down
      if (clickFlag) { return false; }
      // The right line is stretched
      if (((winWidth - x < scaleR) && winHeight - y > scaleR)) {
        way = 1;
        this.ImgMask.style.cursor = 'col-resize';
      // Lower edge stretch
      } else if (((winWidth - x > scaleR) && winHeight - y < scaleR && x > scaleR)) {
        way = 2;
        this.ImgMask.style.cursor = 'row-resize';
      // The left line is stretched
      } else if (((x < scaleR) && winHeight - y > scaleR)) {
        way = 3;
        this.ImgMask.style.cursor = 'col-resize';
      // Lower right corner stretch
      } else if (((winWidth - x <= scaleR) && (winHeight - y <= scaleR))) {
        way = 4;
        this.ImgMask.style.cursor = 'nw-resize';
      // Lower left corner stretch
      } else if (((x <= scaleR) && (winHeight - y <= scaleR))) {
        way = 5;
        this.ImgMask.style.cursor = 'sw-resize';
      } else if (y < scaleR) {
        way = 0; }}); dom.addEventListener('mousedown'.(e) = > {
      if (way === 0) { return false; }
      if(! inScaleArea(e)) {return false; }
      clickFlag = true;
      pageX = e.pageX;
      pageY = e.pageY;
      top = window.getComputedStyle(dom).top;
      left = window.getComputedStyle(dom).left;
      document.addEventListener('mousemove', scaleFn);
      document.addEventListener('mouseup', end);
    });
    dom.addEventListener('mouseup', end);

    function scaleFn(evt) {
      const pX = evt.pageX;
      const pY = evt.pageY;
      let newWidth = 0;
      let newHeight = 0;
      if(! clickFlag) {return false; }

      if (way === 1) {
        newWidth = winWidth + (pX - pageX);
        if (newWidth < minWidth) { return false; }

        that.ImgViewDom.style.width = `${newWidth}px`;
        const moveX = ((pX - pageX) / 2) + parseInt(left, 10);
        dom.style.left = `${moveX}px`;
      } else if (way === 2) {
        newHeight = winHeight + (pY - pageY);
        if (newHeight < minHeight) { return false; }

        that.ImgWrapDom.style.height = `${newHeight}px`;
        const moveY = ((pY - pageY) / 2) + parseInt(top, 10);
        dom.style.top = `${moveY}px`;
      } else if (way === 3) {
        newWidth = winWidth - ((pX - pageX));
        if (newWidth < minWidth) { return false; }

        that.ImgViewDom.style.width = `${newWidth}px`;
        const moveX = ((pX - pageX) / 2) + parseInt(left, 10);
        dom.style.left = `${moveX}px`;
      } else if (way === 4) {
        newWidth = winWidth + (pX - pageX);
        newHeight = winHeight + (pY - pageY);

        if (newWidth >= minWidth) {
          that.ImgViewDom.style.width = `${newWidth}px`;
          const moveX = ((pX - pageX) / 2) + parseInt(left, 10);
          dom.style.left = `${moveX}px`;
        }

        if (newHeight >= minHeight) {
          that.ImgWrapDom.style.height = `${newHeight}px`;
          const moveY = ((pY - pageY) / 2) + parseInt(top, 10);
          dom.style.top = `${moveY}px`; }}else if (way === 5) {
        newWidth = winWidth - (pX - pageX);
        newHeight = winHeight + (pY - pageY);

        if (newWidth >= minWidth) {
          that.ImgViewDom.style.width = `${newWidth}px`;
          const moveX = ((pX - pageX) / 2) + parseInt(left, 10);
          dom.style.left = `${moveX}px`;
        }

        if (newHeight >= minHeight) {
          that.ImgWrapDom.style.height = `${newHeight}px`;
          const moveY = ((pY - pageY) / 2) + parseInt(top, 10);
          dom.style.top = `${moveY}px`; }}return false;
    }

    function inScaleArea(e) {
      let inAarea = 0;
      const x = e.offsetX;
      const y = e.offsetY;
      e.preventDefault();
      // The right line is stretched
      if (((winWidth - x < scaleR) && winHeight - y > scaleR)) {
        inAarea = 1;
      // Lower edge stretch
      } else if (((winWidth - x > scaleR) && winHeight - y < scaleR) && x > scaleR) {
        inAarea = 2;
      // The left line is stretched
      } else if (((x < scaleR) && winHeight - y > scaleR)) {
        inAarea = 3;
      } else if (((winWidth - x <= scaleR) && (winHeight - y < scaleR))) {
        inAarea = 4;
      } else if (((x <= scaleR) && (winHeight - y < scaleR))) {
        inAarea = 5;
      } else if (y < scaleR) {
        inAarea = 0;
      }
      return inAarea;
    }

    function end() {
      winWidth = that.ImgViewDom.clientWidth;
      winHeight = that.ImgMask.clientHeight;
      clickFlag = false;
      way = 0;
      document.removeEventListener('mousemove', scaleFn);
      document.removeEventListener('mouseup', end);
    }
  }

  change = (type = 'pre') = > {
    let { curIndex = 0 } = this.state;
    const { data } = this.state;
    const rotateImg = 0;
    const scaleImg = 100;
    if (curIndex === 0 && type === 'pre') {
      curIndex = data.length - 1;
    } else if (curIndex === (data.length - 1) && type === 'next') {
      curIndex = 0;
    } else {
      curIndex += type === 'next' ? 1 : -1;
    }
    this.setState({curIndex, rotateImg, scaleImg});
    this.ImgDom.style.width = `${(scaleImg / 100) * this.imgWidth}px`;
    this.ImgWrapDom.dispatchEvent(this.initEvent);
    this.ImgDom.style.webkitTransform = `matrix(The ${Math.cos(rotateImg * R)}.The ${Math.sin(rotateImg * R)}.The ${-1 * Math.sin(rotateImg * R)}.The ${Math.cos(rotateImg * R)}`, 0, 0);
  }
  close = () = > {
    this.setState({show: false});
    this.destroy();
  }

  destroy = () = > {
    this.ImgWrapDom = null;
    this.ImgToolDom = null;
    this.ImgViewDom = null;
    this.setState({
      scaleImg: 100.rotateImg: 0}); } scrollImg =(e) = > {
    // eslint-disable-next-line react/no-find-dom-node
    const ele = ReactDOM.findDOMNode(this);
    if (e.nativeEvent.deltaY <= 0 && ele.scrollTop <= 0) {
      /* scrolling up */
      this.scaleImgFn('plus');
      /* scrolling down */
    } else if (ele.scrollTop + ele.clientHeight >= ele.scrollHeight) {
      this.scaleImgFn('minus'); }}/ / image stabilization
  debounce = (fn, wait) = > {
    let timer = null;
    return (. args) = > {
      if (timer) { return false; }
      fn.apply(this, args);
      timer = setTimeout(() = > { timer = null; }, wait);
    };
  }

  scrollImgDebounce = this.debounce(this.scrollImg, 20).bind(this)

  render() {
    const { scaleImg = 100, data, curIndex, show} = this.state;
    return (
      show ?
        <div
          className="iamge-view-modal-wrapper"
          ref={(e)= > { this.ImgViewDom = e; }}
          style={{
            transform: 'translate(0, 0, 0)',
          }}
        >
          <div className="tool-wrapper">
            <div className="left">
              <img src="./public/assets/reverse.png" alt="" onClick={(e)= > { e.preventDefault(); this.rotate(); }} className="rotate" />
              <img src="./public/assets/plus.png" alt="" onClick={(e)= > { e.preventDefault(); this.scaleImgFn('plus'); }} className={scaleImg < 300 ? '' : 'disabled'} />
              <img src="./public/assets/minus.png" alt="" onClick={(e)= > { e.preventDefault(); this.scaleImgFn('minus'); }} className={scaleImg > 100 ? '' : 'disabled'} />
            </div>
            <div className="right">
              <img src="./public/assets/pre.png" className="pre" alt="" onClick={(e)= >{ e.preventDefault(); this.change('pre'); }} / ><img src="./public/assets/next.png" className="next" alt="" onClick={(e)= >{ e.preventDefault(); this.change('next'); }} / ><img src="./public/assets/close.png" className="close" alt="" onClick={(e)= >{ e.preventDefault(); this.close(); }} / ></div>
          </div>
          <div className="img-wrapper">
            <div className="mask" onWheel={this.scrollImgDebounce} />
            <img className="cur-img" src={data[curIndex]} alt="" />
          </div>
        </div> : null); }}const ele = document.createElement('div');
document.body.appendChild(ele);
// eslint-disable-next-line react/no-render-return-value
const imgView = ReactDOM.render(<ImageView />, ele);

export default imgView;
Copy the code

The source code post is mainly for you to point out the lack of support, github will always maintain the wheel. If useful on the big guy, I put the use of the case posted for the convenience of everyone CV:

import React from 'react';
import { render} from 'react-dom';
import ImgView from '.. /src/Index.jsx';
import './style.less';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      imgList: ['./public/exmple_img/img1.jpg'.'./public/exmple_img/img2.jpg'.'./public/exmple_img/img3.jpg']}}componentWillUnmount() {
    ImgView.close();
  }
  openImgView = (index) = > {
    const { imgList = [] } = this.state;
    console.log({data: imgList, curIndex: index});
    ImgView.open({data: imgList, curIndex: index});
  }
  render() {
    const { imgList } = this.state;
    return (
      <div className="img-list">
        {
          imgList.map((item, index) => {
            return <img src={item} key={index} onClick={() = > { this.openImgView(index);} } />;
          })
        }
      </div>
    );
  }
}
render(<App />.document.getElementById("root"));

Copy the code