<template>
  <div class="image-contain">
    <div
      v-if="showGuide"
      :class="[`${prefixCls}-guide`, `${prefixCls}-guide-prev`]"
      @click.stop="showPrev"
    >
      <i class="el-icon-arrow-left"></i>
    </div>
    <div
      v-if="showGuide"
      :class="[`${prefixCls}-guide`, `${prefixCls}-guide-next`]"
      @click.stop="showNext"
    >
      <i class="el-icon-arrow-right"></i>
    </div>

    <!-- image -->
    <div
      :class="[
        `${prefixCls}-image`,
        { [`${prefixCls}-image-nosition`]: nosition },
      ]"
      :style="styles"
      v-move-ele.prevent.stop="{ mouseMove }"
    >
      <img
        :key="image.url"
        :src="image.url"
        ref="PreviewImgDetail"
        @load="resizeImage"
      />
    </div>
    <div :class="[`${prefixCls}-none`]" v-if="!image.url">
      <i class="el-icon-picture"></i>
      <p>暂无数据</p>
    </div>

    <div :class="[`${prefixCls}-loading`]" v-show="loading">
      <i class="el-icon-loading"></i>
    </div>
    <!-- action -->
    <div v-if="showAction && image.url" :class="[`${prefixCls}-action`]">
      <ul>
        <li title="合适大小" @click.stop="toOrigin">
          <i class="el-icon-rank" />
        </li>
        <li title="旋转" @click.stop="toRotate">
          <i class="el-icon-refresh-right"></i>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
import MoveEle from "../plugins/move-ele";
const prefixCls = "image-contain";

export default {
  name: "image-contain",
  props: {
    image: {
      type: Object,
      default() {
        return { url: "", filename: "" };
      },
    },
    showAction: {
      type: Boolean,
      default: true,
    },
    showGuide: {
      type: Boolean,
      default: true,
    },
  },
  directives: { MoveEle },
  data() {
    return {
      prefixCls,
      styles: { width: "", height: "", top: "", left: "", transform: "" },
      initWidth: 500,
      minScale: 0.5,
      maxScale: 5,
      transform: {
        scale: 1,
        rotate: 0,
      },
      loading: false,
      loadingSetT: null,
      nosition: false,
    };
  },
  // watch: {
  //   "image.url": {
  //     handler(val) {
  //       if (val) {
  //         this.loadingSetT = setTimeout(() => {
  //           this.loading = true;
  //         }, 300);
  //         this.styles = {
  //           width: "",
  //           height: "",
  //           top: "",
  //           left: "",
  //           transform: ""
  //         };
  //       }
  //     }
  //   }
  // },
  mounted() {
    this.registWheelHandle();
  },
  methods: {
    resizeImage() {
      const imgDom = this.$refs.PreviewImgDetail;
      const { naturalWidth, naturalHeight } = imgDom;
      const imageSize = this.getImageSizePos({
        win: {
          width: this.$el.clientWidth,
          height: this.$el.clientHeight,
        },
        img: {
          width: naturalWidth,
          height: naturalHeight,
        },
        rotate: 0,
      });

      this.styles = Object.assign(this.styles, {
        width: imageSize.width + "px",
        height: imageSize.height + "px",
        top: imageSize.top + "px",
        left: imageSize.left + "px",
        marginLeft: "auto",
        transform: "none",
      });
      this.transform = {
        scale: 1,
        rotate: 0,
      };
      this.loading = false;
      setTimeout(() => {
        this.nosition = false;
      }, 100);
    },
    getImageSizePos({ win, img, rotate }) {
      const imageSize = {
        width: 0,
        height: 0,
        top: 0,
        left: 0,
      };
      const isHorizontal = !!(rotate % 180);

      const rateWin = isHorizontal
        ? win.height / win.width
        : win.width / win.height;
      const hwin = isHorizontal
        ? {
            width: win.height,
            height: win.width,
          }
        : win;

      const rateImg = img.width / img.height;

      if (rateImg <= rateWin) {
        imageSize.height = Math.min(hwin.height, img.height);
        imageSize.width = Math.floor(
          (imageSize.height * img.width) / img.height
        );
      } else {
        imageSize.width = Math.min(hwin.width, img.width);
        imageSize.height = Math.floor(
          (imageSize.width * img.height) / img.width
        );
      }
      imageSize.left = (win.width - imageSize.width) / 2;
      imageSize.top = (win.height - imageSize.height) / 2;
      return imageSize;
    },
    showPrev() {
      this.$emit("on-prev");
    },
    showNext() {
      this.$emit("on-next");
    },
    // dome-move
    registWheelHandle() {
      this.$el.addEventListener("wheel", (e) => {
        e.preventDefault();
        this.mouseWheel(e.wheelDeltaY);
      });
    },
    mouseMove({ left, top }) {
      this.styles.left = left + "px";
      this.styles.top = top + "px";
    },
    mouseWheel(delta) {
      if (delta < 0) {
        this.toMagnify();
      } else {
        this.toShrink();
      }
    },
    setStyleTransform() {
      const { scale, rotate } = this.transform;
      this.styles.transform = `scale(${scale}, ${scale}) rotate(${rotate}deg)`;
    },
    toOrigin() {
      this.transform.scale = 1;
      this.setStyleTransform();
      this.resizeImage();
    },
    toMagnify() {
      const scale = (this.transform.scale * 1.2).toFixed(2);
      this.transform.scale = scale >= this.maxScale ? this.maxScale : scale;
      this.setStyleTransform();
    },
    toShrink() {
      const scale = (this.transform.scale * 0.75).toFixed(2);
      this.transform.scale = scale <= this.minScale ? this.minScale : scale;
      this.setStyleTransform();
    },
    toRotate() {
      this.transform.rotate = this.transform.rotate + 90;
      this.setStyleTransform();

      this.$emit(
        "on-rotate",
        this.transform.rotate >= 360 ? 0 : this.transform.rotate
      );
      // 调整图片尺寸
      const { naturalWidth, naturalHeight } = this.$refs.PreviewImgDetail;
      const imageSize = this.getImageSizePos({
        win: {
          width: this.$el.clientWidth,
          height: this.$el.clientHeight,
        },
        img: {
          width: naturalWidth,
          height: naturalHeight,
        },
        rotate: this.transform.rotate,
      });

      this.styles = Object.assign(this.styles, {
        width: imageSize.width + "px",
        height: imageSize.height + "px",
        top: imageSize.top + "px",
        left: imageSize.left + "px",
      });
      // 360度无缝切换到0度
      if (this.transform.rotate >= 360) {
        setTimeout(() => {
          this.nosition = true;
          this.transform.rotate = 0;
          this.setStyleTransform();
          setTimeout(() => {
            this.nosition = false;
          }, 100);
        }, 200);
        // 200ms当次旋转动画持续时间
      }
    },
  },
};
</script>
