工具函数4:图片放大镜

193 阅读1分钟

效果

test2.gif

demo地址

codepen地址

支持功能点

  1. 放大预览
  2. 支持自定义放大区域size(矩形
  3. 支持动态更新放大设置
  4. 支持自定义查看区域scale
  5. 自定义查看区域dom
  6. 自定义原图size(设置不正确时可能存在溢出不显示的问题)

原理

  1. 对查看区域的dom进行background-position以及background-size进行动态设置

缺点

  1. 未提供destroy api
  2. 未使用canvas,不好进行导出等操作

demo代码展示

    <div id="example" style="display: inline-block;"></div>
    <div class="piece" style="display: inline-block;"></div>
    class ImgScopePreview {
      constructor({
        el,
        imgInfo: [imgW, imgH, imgSrc],
        scopeSize: [scopeW, scopeH],
        scale,
        targetEl
      }) {
        this.imgSrc = imgSrc;
        this.imgW = imgW || 1200;
        this.imgH = imgH || 675;
        this.scopeW = scopeW || 100;
        this.scopeH = scopeH || 100;
        this.scale = scale || 2;
        this.el = document.querySelector(el);
        this.targetEl = document.querySelector(targetEl);
        this.innerScopeDom = null;
        this.moveListener = null; //监听函数,用于解绑等
        this.init();
      }

      init() {
        this.initDom();
        this.bindListener();
      }

      initDom() {
        this.el.innerHTML = "";
        this.innerScopeDom = document.createElement("div");
        Object.assign(this.innerScopeDom.style, {
          width: `${this.scopeW}px`,
          height: `${this.scopeH}px`,
          position: "absolute",
          top: 0,
          left: 0,
          backgroundColor: "#00000066",
          pointerEvents: "none"
        });
        this.el.appendChild(this.innerScopeDom);

        Object.assign(this.el.style, {
          cursor: "move",
          position: "relative",
          backgroundImage: `url(${this.imgSrc})`,
          backgroundSize: `100%`,
          width: `${this.imgW}px`,
          height: `${this.imgH}px`
        });

        Object.assign(this.targetEl.style, {
          width: `${this.scopeW * this.scale}px`,
          height: `${this.scopeH * this.scale}px`,
          backgroundImage: `url(${this.imgSrc})`,
          backgroundSize: `${this.imgW * this.scale}px ${this.imgH * this.scale}px`,
          backgroundRepeat: `no-repeat`
        });
      }

      bindListener() {
        this.el.removeEventListener("mousemove", this.moveListener);

        let { imgW, imgH, scopeW, scopeH, scale } = this;

        this.moveListener = evnt => {
          let { offsetX, offsetY } = evnt;
          let scopeLeft =
            offsetX < scopeW / 2
              ? 0
              : offsetX > imgW - scopeW / 2
              ? imgW - scopeW
              : offsetX - scopeW / 2;
          let scopeTop =
            offsetY < scopeH / 2
              ? 0
              : offsetY > imgH - scopeH / 2
              ? imgH - scopeH
              : offsetY - scopeH / 2;

          Object.assign(this.innerScopeDom.style, {
            left: `${scopeLeft}px`,
            top: `${scopeTop}px`
          });

          Object.assign(this.targetEl.style, {
            backgroundPosition: `-${scopeLeft * this.scale}px -${scopeTop * this.scale}px`
          });
        };

        this.el.addEventListener("mousemove", this.moveListener);
      }

      getOptions() {
        return {
          imgInfo: [this.imgW, this.imgH, this.imgSrc],
          scopeSize: [this.scopeW, this.scopeH],
          scale: this.scale
        };
      }

      loadOptions({ imgInfo: [imgW, imgH, imgSrc], scopeSize: [scopeW, scopeH], scale }) {
        Object.assign(this, {
          imgW,
          imgH,
          imgSrc,
          scopeW,
          scopeH,
          scale
        });
        this.init();
      }
    }

    let imgpreviewer = new ImgScopePreview({
      el: "#example",
      imgInfo: [900, 784, "https://pic2.zhimg.com/80/v2-43db8765a0f2c6cbe55fb785ea538d20_hd.jpeg"],
      scopeSize: [200, 400],
      scale: 2,
      targetEl: ".piece"
    });