<template>
  <div class="main_body">
    <!-- 绘制工具栏 -->
    <div class="toolbar" v-if="toolbarShow">
      <el-button
        type="text"
        :style="`background-image: url(${btnBg.text})`"
        class="icon_toolbar icon_title"
        :class="[type === 'text' ? 'icon_active' : '']"
        title="文本"
        @click="handleDrawCanvas('text', '文本', 'text')"
      />
      <!-- <el-button type="text" class="icon_toolbar icon_line" :class="[type === 'line' ? 'icon_active' : '']" title="折线" @click="handleDrawCanvas('crosshair', '折线', 'line')" />-->
      <!-- <el-button type="text" class="icon_toolbar icon_rectangle" :class="[type === 'rectangle' ? 'icon_active' : '']" title="矩形" @click="handleDrawCanvas('crosshair', '矩形', 'rectangle')" />  -->
      <!-- <el-button type="text" class="icon_toolbar icon_circle" :class="[type === 'circle' ? 'icon_active' : '']" title="圆形" @click="handleDrawCanvas('crosshair', '圆形', 'circle')" /> -->
      <el-button
        type="text"
        class="icon_toolbar icon_rectangle"
        :class="[type === 'cloud' ? 'icon_active' : '']"
        title="云线"
        :style="`background-image: url(${btnBg.cloud})`"
        @click="handleDrawCanvas('crosshair', '云线', 'cloud')"
      />
      <!-- <el-button type="text" class="icon_toolbar icon_rubber" :class="[type === 'rubber' ? 'icon_active' : '']" title="橡皮擦" @click="handleDrawCanvas('eraser', '橡皮', 'rubber')" />-->
      <el-button type="text" class="icon_toolbar icon_color" title="颜色">
        <el-color-picker
          v-model="defaultColor"
          popper-class="popperClass"
          @change="colorChange"
        ></el-color-picker>
      </el-button>
      <el-button
        type="text"
        :style="`background-image: url(${btnBg.clear})`"
        class="text_toolbar icon_clear"
        @click="clearAnn"
        title="清除"
      ></el-button>
      <el-button
        type="text"
        :style="`background-image: url(${btnBg.cancel})`"
        class="text_toolbar icon_cancel"
        @click="cancel"
        title="取消"
      ></el-button>
      <el-button
        type="text"
        :style="`background-image: url(${btnBg.save})`"
        class="text_toolbar icon_save"
        @click="saveDrawing"
        title="保存"
      ></el-button>
    </div>
    <div class="canvas_container" id="canvas_container">
      <canvas id="ctx_base" ref="ctx_base" :style="'cursor:' + cursorStyle"></canvas>
      <input
        name="text"
        id="text"
        @keyup.enter="handleTextBlur"
        @blur="handleTextBlur"
        v-model="text"
        autofocus
        autocomplete="off"
        :style="'font-size:' + (this.slide * 10 + 14) + 'pxcolor:' + defaultColor"
        placeholder="输入完成请按回车键"
      />
    </div>
  </div>
</template>

<script>
var canvas_base = null,
  ctx_base = null,
  recordImg = null;
var canvas_container = null,
  startPoint = null,
  currentPoint = null;
let originalImageWidth = 0,
  originalImageHeight = 0,
  displayImageWidth = 0,
  displayImageHeight = 0,
  translateX = 0,
  translateY = 0;
var annList = [];
let scale = 1.0; // 当前缩放比例
const MIN_SCALE = 0.1; // 最小缩放比例
const MAX_SCALE = 8.0; // 最大缩放比例
const SCALE_STEP = 0.1; // 缩放步长
let offsetX = 0; // X轴平移
let offsetY = 0; // Y轴平移
let isPanning = false; // 是否正在平移
let panStartX = 0; // 平移起始X坐标
let panStartY = 0; // 平移起始Y坐标
let isSpacePressed = false; // 空格键是否按下
import cursors from '@/utils/cursor';
import { drawCloudLines } from '@/utils/cloud';
export default {
  name: 'DrawToolbar',
  props: {
    src: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      currentImg: {
        url: null,
        width: '',
        height: '',
        scale: 1,
        index: 0,
      },
      tl: 0,
      tt: 0,
      slide: 1, // 2,
      text: '',
      toolbarShow: true,
      ctx_base: null,
      ctx_front: null,
      ctx_back: null,
      canDraw: false,
      baseMap: null,
      canvasStore: [],
      type: '',
      cloudDensity: 3,
      defaultColor: '#A90A0A', // 颜色选取
      cursorStyle: 'default', // 鼠标样式
      btnBg: {
        text: require('@static/ann-img/mark_font@2x.png'),
        cloud: require('@static/ann-img/mark_cloud@2x.png'),
        clear: require('@static/ann-img/mark_clear@2x.png'),
        cancel: require('@static/ann-img/mark_exit@2x.png'),
        save: require('@static/ann-img/mark_finish@2x.png'),
      },
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.handleInitCanvas();
    });
  },
  created() {
    console.log('created');
  },
  methods: {
    clearAnn() {
      annList.splice(0);
      this.redraw();
    },
    // 初始化图纸
    handleInitCanvas() {
      console.log('handleInitCanvas');
      this.currentImg = {
        url: this.src,
        width: '',
        height: '',
        scale: 1,
        index: 0,
      };
      canvas_container = document.getElementById('canvas_container');
      canvas_base = document.getElementById('ctx_base');
      ctx_base = canvas_base.getContext('2d');
      ctx_base.strokeStyle = this.defaultColor;

      let img = new Image();
      img.src = this.currentImg.url;
      let _this = this;
      img.onload = function () {
        recordImg = this;
        originalImageWidth = img.naturalWidth || img.width;
        originalImageHeight = img.naturalHeight || img.height;
        _this.resetView();
      };
      canvas_base.width = canvas_container.clientWidth;
      canvas_base.height = canvas_container.clientHeight;
      canvas_base.addEventListener('wheel', e => {
        e.preventDefault();
        const rect = canvas_base.getBoundingClientRect();
        const mouseX = e.clientX - rect.left;
        const mouseY = e.clientY - rect.top;
        let imagePointBeforeZoom = this.screenToImage(mouseX, mouseY);
        const zoomFactor = e.deltaY > 0 ? 0.8 : 1.2;
        const newScale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale * zoomFactor));
        scale = newScale;
        const imagePointAfterZoom = this.screenToImage(mouseX, mouseY);
        translateX += (imagePointAfterZoom.x - imagePointBeforeZoom.x) * scale;
        translateY += (imagePointAfterZoom.y - imagePointBeforeZoom.y) * scale;
        this.redraw();
      });
      canvas_base.addEventListener('mousedown', e => {
        if (e.button === 0) {
          // ctx_base.strokeStyle = this.defaultColor
          // ctx_base.lineWidth = this.slide * 2
          e = e || window.event;
          let rect = canvas_base.getBoundingClientRect();
          let screenX = e.clientX - rect.left;
          let screenY = e.clientY - rect.top;
          let imagePoint = this.screenToImage(screenX, screenY);
          startPoint = imagePoint;
          currentPoint = imagePoint;
          switch (this.type) {
            case 'rubber':
              ctx_front.putImageData(cbx, e.offsetX - 12, e.offsetY - 12);
              // this.ctx_back.putImageData(cbx, e.offsetX - 12, e.offsetY - 12)
              break;
            case 'text':
              let text = document.getElementById('text');
              // this.handleTextBlur()
              this.text = '';
              text.style.fontSize = 14 + this.slide * 10 + 'px';
              text.style.color = this.defaultColor;
              text.style.left = screenX - 5 + 'px';
              text.style.top = screenY - 20 + 'px';
              text.style.zIndex = 10;
              text.style.display = 'block';
              let textPos = this.screenToImage(screenX - 5, screenY + 10);
              this.tl = textPos.x; // currentPoint.x
              this.tt = textPos.y; // currentPoint.y
              break;
            case 'cloud':
              this.canDraw = true;
              break;
          }
          this.redraw();
        }
      });
      canvas_base.addEventListener('contextmenu', e => {
        e.preventDefault();
      });
      canvas_base.addEventListener('mousemove', e => {
        if (e.button === 0) {
          e = e || window.event;
          let rect = canvas_base.getBoundingClientRect();
          let screenX = e.clientX - rect.left;
          let screenY = e.clientY - rect.top;
          if (this.canDraw) {
            let imagePoint = this.screenToImage(screenX, screenY);
            currentPoint = imagePoint;
            this.redraw();
          }
        }
      });
      canvas_base.addEventListener('mouseup', e => {
        if (e.button === 0 && this.canDraw) {
          this.canDraw = false;
          if (this.type === 'cloud') {
            let width = Math.abs(currentPoint.x - startPoint.x);
            let height = Math.abs(currentPoint.y - startPoint.y);
            let minSize = 5 / scale;
            if (width > minSize && height > minSize) {
              annList.push({
                x: Math.min(startPoint.x, currentPoint.x),
                y: Math.min(startPoint.y, currentPoint.y),
                ex: Math.max(startPoint.x, currentPoint.x),
                ey: Math.max(startPoint.y, currentPoint.y),
                type: 'cloud',
                color: this.defaultColor,
                lineWidth: ctx_base.lineWidth,
              });
            }
            startPoint = null;
            currentPoint = null;
          }
          this.redraw();
        }
      });
    },
    resetView() {
      if (!recordImg) return;
      const containerWidth = canvas_base.width;
      const containerHeight = canvas_base.height;

      // 计算保持比例的最大尺寸
      const widthRatio = containerWidth / originalImageWidth;
      const heightRatio = containerHeight / originalImageHeight;
      const scaleRatio = Math.min(widthRatio, heightRatio);

      displayImageWidth = originalImageWidth * scaleRatio;
      displayImageHeight = originalImageHeight * scaleRatio;

      // 居中显示
      translateX = (containerWidth - displayImageWidth) / 2;
      translateY = (containerHeight - displayImageHeight) / 2;
      scale = scaleRatio;
      this.redraw();
    },
    redraw() {
      if (!recordImg) return;
      ctx_base.clearRect(0, 0, canvas_base.width, canvas_base.height);
      ctx_base.save();
      ctx_base.translate(translateX, translateY);
      ctx_base.scale(scale, scale);
      ctx_base.drawImage(recordImg, 0, 0, originalImageWidth, originalImageHeight);
      annList.forEach(item => {
        switch (item.type) {
          case 'cloud':
            this.drawCloudAnn(item);
            break;
          case 'text':
            this.drawTextAnn(item);
            break;
        }
      });
      if (this.canDraw && startPoint && currentPoint) {
        if (this.type === 'cloud') {
          let tempAnn = {
            x: Math.min(startPoint.x, currentPoint.x),
            y: Math.min(startPoint.y, currentPoint.y),
            ex: Math.max(startPoint.x, currentPoint.x),
            ey: Math.max(startPoint.y, currentPoint.y),
            type: 'cloud',
            color: this.defaultColor,
            lineWidth: ctx_base.lineWidth,
          };
          this.drawCloudAnn(tempAnn);
        }
      }
      ctx_base.restore();
    },
    // 绘制云线
    drawCloudAnn(annotation) {
      ctx_base.save();
      ctx_base.strokeStyle = annotation.color;
      ctx_base.lineWidth = annotation.lineWidth || ctx_base.lineWidth;
      ctx_base.setLineDash([]);
      ctx_base.beginPath();
      drawCloudLines(
        ctx_base,
        [
          { x: annotation.ex, y: annotation.y },
          { x: annotation.ex, y: annotation.ey },
          { x: annotation.x, y: annotation.ey },
          { x: annotation.x, y: annotation.y },
        ],
        true
      );
      ctx_base.restore();
    },
    drawTextAnn(annotation) {
      ctx_base.save();
      ctx_base.strokeStyle = annotation.color;
      ctx_base.fillStyle = annotation.color;
      ctx_base.fillText(annotation.text, annotation.x, annotation.y);
      ctx_base.restore();
    },
    // 屏幕坐标转换为图像坐标
    screenToImage(screenX, screenY) {
      const imageX = (screenX - translateX) / scale;
      const imageY = (screenY - translateY) / scale;
      return { x: imageX, y: imageY };
    },
    // 当前显示的颜色发生改变时
    colorChange(val) {
      if (this.defaultColor === null) this.defaultColor = '#A90A0A';
      this.redraw();
    },
    saveDrawing() {
      const link = document.createElement('a');
      link.download = `图纸批注_${new Date().toISOString().slice(0, 19).replace(/[:T]/g, '-')}.png`;
      link.href = canvas_base.toDataURL('image/png', 1.0);
      link.click();
    },
    handleDrawCanvas(style, type, actived) {
      if (actived !== this.type) {
        this.type = actived;
      }
      if (style !== 'eraser') this.cursorStyle = style;
      else if (style === 'eraser') this.cursorStyle = `url('${cursors.eraser}') 15 15, auto`;
      this.canDraw = false;
    },
    /** 失焦或者回车绘制文本，框隐藏*/
    handleTextBlur() {
      let realTxt = this.text.replace(/^\s+|\s+$/g, '');
      if (realTxt === '') return;
      let text = document.getElementById('text');
      let fontSize = 1.2; // text.style.fontSize / 10
      annList.push({
        type: 'text',
        x: this.tl,
        y: this.tt,
        text: realTxt,
        color: this.defaultColor,
        font: `100 ${fontSize} sans-serif`,
      });
      text.style.display = 'none';
      this.text = '';
      text.value = '';
      this.redraw();
    },
    cancel() {
      canvas_base = null;
      ctx_base = null;
      recordImg = null;
      canvas_container = null;
      startPoint = null;
      currentPoint = null;
      originalImageWidth = 0;
      originalImageHeight = 0;
      displayImageWidth = 0;
      displayImageHeight = 0;
      translateX = 0;
      translateY = 0;
      annList.splice(0);
      scale = 1.0; // 当前缩放比例
      offsetX = 0; // X轴平移
      offsetY = 0; // Y轴平移
      isPanning = false; // 是否正在平移
      panStartX = // 平移起始X坐标
        panStartY = 0; // 平移起始Y坐标
      isSpacePressed = false; // 空格键是否按下
      this.$emit('closeAnn');
    },
  },
};
</script>
<style scoped lang="scss">
.main_body {
  position: relative;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  overflow: hidden;
}
// P标签样式
.classification_title {
  margin: 0 0 10px 0;
  color: #fff;
  font-size: 14px;
  cursor: default;
}

// 工具栏样式
.toolbar {
  z-index: 10;
  position: absolute;
  width: 520px;
  padding: 8px 16px;
  border-radius: 6px;
  box-shadow: 0px 2px 10px 0px rgba(6, 29, 44, 0.25);
  background-color: #fff;
  top: 10px;
  left: 50%;
  box-sizing: border-box;
  transform: translateX(-50%);
  display: flex;
  justify-content: space-around;
}
// 工具栏图标
.icon_toolbar,
.text_toolbar {
  float: left;
  width: 32px;
  height: 32px;
  padding: 0px !important;
  background-repeat: no-repeat;
  background-size: 24px;
  background-position: center;
}
.icon_toolbar:hover,
.text_toolbar:hover,
.icon_active {
  background-color: rgba(238, 238, 238, 1);
}

// 调色盘设置
::v-deep.icon_color .el-color-picker__trigger {
  height: 24px;
  margin-top: 4px;
  width: 24px !important;
  // opacity: 0;
  // filter: alpha(opacity=0);
}
::v-deep.el-color-picker--medium,
::v-deep.el-color-picker--medium .el-color-picker__trigger {
  width: 24px !important;
  height: 24px !important;
}

// 画布
.canvas_container {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: auto;
  box-sizing: border-box;
  // padding: 20px;

  canvas {
    position: absolute;
    left: 0;
    // top: 20px;
    // left: 20px;
  }
  #ctx_front {
    z-index: 5;
    background-color: transparent;
  }
  #ctx_back {
    z-index: 3;
  }
  #ctx_base {
    z-index: 1;
  }
}
#text {
  position: absolute;
  z-index: -1;
  resize: none;
  outline: none;
  border: 1px dashed #9c9c9c;
  overflow: hidden;
  background: transparent;
  line-height: 30px;
  display: none;
}
#text:hover {
  border: 1px dashed #53a8ff;
}
</style>
