美文网首页
element 预览大图组件进行修改,增加保存图片功能(base

element 预览大图组件进行修改,增加保存图片功能(base

作者: 宏_4491 | 来源:发表于2020-12-20 15:14 被阅读0次

    element 预览大图组件进行修改,增加保存图片功能(base64)

    
    <template>
      <transition name="viewer-fade">
        <div
          tabindex="-1"
          ref="el-image-viewer__wrapper"
          class="el-image-viewer__wrapper"
          :style="{ 'z-index': zIndex }"
        >
          <div class="el-image-viewer__mask"></div>
          <!-- CLOSE -->
          <span class="el-image-viewer__btn el-image-viewer__close" @click="hide">
            <i class="el-icon-circle-close"></i>
          </span>
          <!-- ARROW -->
          <template v-if="!isSingle">
            <span
              class="el-image-viewer__btn el-image-viewer__prev"
              :class="{ 'is-disabled': !infinite && isFirst }"
              @click="prev"
            >
              <i class="el-icon-arrow-left" />
            </span>
            <span
              class="el-image-viewer__btn el-image-viewer__next"
              :class="{ 'is-disabled': !infinite && isLast }"
              @click="next"
            >
              <i class="el-icon-arrow-right" />
            </span>
          </template>
          <!-- ACTIONS -->
          <div class="el-image-viewer__btn el-image-viewer__actions">
            <div class="el-image-viewer__actions__inner">
              <i class="el-icon-zoom-out" @click="handleActions('zoomOut')"></i>
              <i class="el-icon-zoom-in" @click="handleActions('zoomIn')"></i>
              <i class="el-image-viewer__actions__divider"></i>
              <i :class="mode.icon" @click="toggleMode"></i>
              <i class="el-image-viewer__actions__divider"></i>
              <i class="el-icon-download" @click="download"></i>
              <i class="el-icon-refresh-left" @click="handleActions('anticlocelise')"></i>
              <i class="el-icon-refresh-right" @click="handleActions('clocelise')"></i>
            </div>
          </div>
          <!-- CANVAS -->
          <div class="el-image-viewer__canvas">
            <img
              v-for="(url, i) in urlList"
              v-if="i === index"
              ref="img"
              class="el-image-viewer__img"
              :key="url"
              :src="currentImg"
              :style="imgStyle"
              @load="handleImgLoad"
              @error="handleImgError"
              @mousedown="handleMouseDown"
            />
          </div>
        </div>
      </transition>
    </template>
    
    <script>
    import { on, off } from "element-ui/src/utils/dom";
    import { rafThrottle, isFirefox } from "element-ui/src/utils/util";
    
    const Mode = {
      CONTAIN: {
        name: "contain",
        icon: "el-icon-full-screen",
      },
      ORIGINAL: {
        name: "original",
        icon: "el-icon-c-scale-to-original",
      },
    };
    
    const mousewheelEventName = isFirefox() ? "DOMMouseScroll" : "mousewheel";
    
    export default {
      name: "elImageViewer",
    
      props: {
        urlList: {
          type: Array,
          default: () => [],
        },
        zIndex: {
          type: Number,
          default: 2000,
        },
        onSwitch: {
          type: Function,
          default: () => {},
        },
        onClose: {
          type: Function,
          default: () => {},
        },
        initialIndex: {
          type: Number,
          default: 0,
        },
      },
    
      data() {
        return {
          index: this.initialIndex,
          isShow: false,
          infinite: true,
          loading: false,
          mode: Mode.CONTAIN,
          transform: {
            scale: 1,
            deg: 0,
            offsetX: 0,
            offsetY: 0,
            enableTransition: false,
          },
        };
      },
      computed: {
        isSingle() {
          return this.urlList.length <= 1;
        },
        isFirst() {
          return this.index === 0;
        },
        isLast() {
          return this.index === this.urlList.length - 1;
        },
        currentImg() {
          return this.urlList[this.index];
        },
        imgStyle() {
          const { scale, deg, offsetX, offsetY, enableTransition } = this.transform;
          const style = {
            transform: `scale(${scale}) rotate(${deg}deg)`,
            transition: enableTransition ? "transform .3s" : "",
            "margin-left": `${offsetX}px`,
            "margin-top": `${offsetY}px`,
          };
          if (this.mode === Mode.CONTAIN) {
            style.maxWidth = style.maxHeight = "100%";
          }
          return style;
        },
      },
      watch: {
        index: {
          handler: function (val) {
            this.reset();
            this.onSwitch(val);
          },
        },
        currentImg(val) {
          this.$nextTick((_) => {
            const $img = this.$refs.img[0];
            if (!$img.complete) {
              this.loading = true;
            }
          });
        },
      },
      methods: {
        hide() {
          this.deviceSupportUninstall();
          this.onClose();
        },
        deviceSupportInstall() {
          this._keyDownHandler = rafThrottle((e) => {
            const keyCode = e.keyCode;
            switch (keyCode) {
              // ESC
              case 27:
                this.hide();
                break;
              // SPACE
              case 32:
                this.toggleMode();
                break;
              // LEFT_ARROW
              case 37:
                this.prev();
                break;
              // UP_ARROW
              case 38:
                this.handleActions("zoomIn");
                break;
              // RIGHT_ARROW
              case 39:
                this.next();
                break;
              // DOWN_ARROW
              case 40:
                this.handleActions("zoomOut");
                break;
            }
          });
          this._mouseWheelHandler = rafThrottle((e) => {
            const delta = e.wheelDelta ? e.wheelDelta : -e.detail;
            if (delta > 0) {
              this.handleActions("zoomIn", {
                zoomRate: 0.015,
                enableTransition: false,
              });
            } else {
              this.handleActions("zoomOut", {
                zoomRate: 0.015,
                enableTransition: false,
              });
            }
          });
          on(document, "keydown", this._keyDownHandler);
          on(document, mousewheelEventName, this._mouseWheelHandler);
        },
        deviceSupportUninstall() {
          off(document, "keydown", this._keyDownHandler);
          off(document, mousewheelEventName, this._mouseWheelHandler);
          this._keyDownHandler = null;
          this._mouseWheelHandler = null;
        },
        handleImgLoad(e) {
          this.loading = false;
        },
        handleImgError(e) {
          this.loading = false;
          e.target.alt = "加载失败";
        },
        handleMouseDown(e) {
          if (this.loading || e.button !== 0) return;
    
          const { offsetX, offsetY } = this.transform;
          const startX = e.pageX;
          const startY = e.pageY;
          this._dragHandler = rafThrottle((ev) => {
            this.transform.offsetX = offsetX + ev.pageX - startX;
            this.transform.offsetY = offsetY + ev.pageY - startY;
          });
          on(document, "mousemove", this._dragHandler);
          on(document, "mouseup", (ev) => {
            off(document, "mousemove", this._dragHandler);
          });
    
          e.preventDefault();
        },
        reset() {
          this.transform = {
            scale: 1,
            deg: 0,
            offsetX: 0,
            offsetY: 0,
            enableTransition: false,
          };
        },
        toggleMode() {
          if (this.loading) return;
    
          const modeNames = Object.keys(Mode);
          const modeValues = Object.values(Mode);
          const index = modeValues.indexOf(this.mode);
          const nextIndex = (index + 1) % modeNames.length;
          this.mode = Mode[modeNames[nextIndex]];
          this.reset();
        },
        prev() {
          if (this.isFirst && !this.infinite) return;
          const len = this.urlList.length;
          this.index = (this.index - 1 + len) % len;
        },
        next() {
          if (this.isLast && !this.infinite) return;
          const len = this.urlList.length;
          this.index = (this.index + 1) % len;
        },
        handleActions(action, options = {}) {
          if (this.loading) return;
          const { zoomRate, rotateDeg, enableTransition } = {
            zoomRate: 0.2,
            rotateDeg: 90,
            enableTransition: true,
            ...options,
          };
          const { transform } = this;
          switch (action) {
            case "zoomOut":
              if (transform.scale > 0.2) {
                transform.scale = parseFloat(
                  (transform.scale - zoomRate).toFixed(3)
                );
              }
              break;
            case "zoomIn":
              transform.scale = parseFloat((transform.scale + zoomRate).toFixed(3));
              break;
            case "clocelise":
              transform.deg += rotateDeg;
              break;
            case "anticlocelise":
              transform.deg -= rotateDeg;
              break;
          }
          transform.enableTransition = enableTransition;
        },
        // 下载当前图片
        download() {
          let url = this.urlList[this.initialIndex];
          let _date = new Date()
          this.downloadFile(url, `xxx ${_date.getFullYear()}-${_date.getMonth() + 1}-${_date.getDate()}`)
        },
        downloadFile(content, fileName) {
          //下载base64图片
          var base64ToBlob = function (code) {
            let parts = code.split(";base64,");
            let contentType = parts[0].split(":")[1];
            let raw = window.atob(parts[1]);
            let rawLength = raw.length;
            let uInt8Array = new Uint8Array(rawLength);
            for (let i = 0; i < rawLength; ++i) {
              uInt8Array[i] = raw.charCodeAt(i);
            }
            return new Blob([uInt8Array], {
              type: contentType,
            });
          };
          let aLink = document.createElement("a");
          let blob = base64ToBlob(content); //new Blob([content]);
          let evt = document.createEvent("HTMLEvents");
          evt.initEvent("click", true, true); //initEvent 不加后两个参数在FF下会报错  事件类型,是否冒泡,是否阻止浏览器的默认行为
          aLink.download = fileName;
          aLink.href = URL.createObjectURL(blob);
          aLink.click();
        },
      },
      mounted() {
        this.deviceSupportInstall();
        // add tabindex then wrapper can be focusable via Javascript
        // focus wrapper so arrow key can't cause inner scroll behavior underneath
        this.$refs["el-image-viewer__wrapper"].focus();
      },
    };
    </script>
    
    image.png

    文章来源于:https://www.jianshu.com/p/f0487f789acc

    相关文章

      网友评论

          本文标题:element 预览大图组件进行修改,增加保存图片功能(base

          本文链接:https://www.haomeiwen.com/subject/edrknktx.html