<template>
  <div class="edit" @mouseup="mouseup">
    <div class="main">
      <h1 class="head">
        图像编辑器
        <el-icon class="closeMain" @click="close"><Close /></el-icon>
      </h1>
      <el-row>
        <el-col :span="6" style="padding-left: 32px">
          <h4>工具</h4>
          <el-row>
            <el-col :span="12">
              <span
                @click="select[0] = 0"
                :class="{ dark: true, active: select[0] === 0 }"
                style="border-radius: 0"
              >
                <el-icon><EditPen /></el-icon>
                绘制
              </span>
            </el-col>
            <el-col :span="12">
              <span
                @click="select[0] = 1"
                :class="{ dark: true, active: select[0] === 1 }"
                style="border-radius: 0"
              >
                <svg
                  t="1681957131845"
                  viewBox="0 0 1024 1024"
                  version="1.1"
                  xmlns="http://www.w3.org/2000/svg"
                  p-id="2773"
                  width="16"
                  height="16"
                >
                  <path
                    d="M567.8 776.8l4.2 4.2c3.5 3.5 8.1 5.3 12.7 5.3s9.2-1.8 12.7-5.3l296.1-296.1c30.3-30.3 30.3-79.7 0-110L639.7 121c-14.7-14.7-34.2-22.8-55-22.8s-40.3 8.1-55 22.8L233.6 417.2c-3.4 3.4-5.3 7.9-5.3 12.7 0 4.8 1.9 9.3 5.3 12.7l4.2 4.2-97.3 97.3c-14.7 14.7-22.8 34.2-22.8 55s8.1 40.3 22.8 55l220 220c10.6 10.6 23.7 17.7 37.9 20.8H131.6c-9.9 0-17.9 8-17.9 17.9s8 17.9 17.9 17.9h729.9c9.9 0 17.9-8 17.9-17.9s-8-17.9-17.9-17.9h-429c14.2-3.2 27.3-10.3 37.9-20.8l97.4-97.3z m-12.7-630.4c16.3-16.3 42.9-16.3 59.2 0l253.8 253.8c7.9 7.9 12.3 18.4 12.3 29.6s-4.4 21.7-12.3 29.6L584.7 742.9l-4.2-4.2-304.6-304.6-4.2-4.2 283.4-283.5zM415.5 860.9c-11.2 0-21.7-4.4-29.6-12.3l-220-220c-7.9-7.9-12.3-18.4-12.3-29.6 0-11.2 4.4-21.7 12.3-29.6l97.3-97.3 279.2 279.2-97.3 97.3c-7.9 8-18.4 12.3-29.6 12.3z"
                    fill="#ffffff"
                    p-id="2774"
                  ></path>
                </svg>
                橡皮擦
              </span>
            </el-col>
          </el-row>
          <el-row style="margin-top: 1em">
            <!-- <el-col :span="12">
              <span
                @click="fillColor"
                :class="{ dark: true, active: select[0] === 2 }"
              >
                <svg
                  t="1681957205411"
                  class="icon"
                  viewBox="0 0 1024 1024"
                  version="1.1"
                  xmlns="http://www.w3.org/2000/svg"
                  p-id="3923"
                  width="16"
                  height="16"
                >
                  <path
                    d="M903.77742 538.320685a246.196888 246.196888 0 0 0-99.597831-158.9089L456.146716 130.976744 290.523355 12.914146a49.239378 49.239378 0 1 0-55.953838 80.013988l74.418604 55.953838L80.136924 465.580696a245.637349 245.637349 0 0 0 55.953838 341.877951l239.482427 170.659206a245.637349 245.637349 0 0 0 341.87795-55.953838l142.122749-199.755202a245.077811 245.077811 0 0 0 44.203532-184.088128zM160.150912 522.653611l227.732121-319.496416 245.077811 174.575975 111.907676 81.133065a147.158594 147.158594 0 0 1 55.953838 148.277671 1941.598182 1941.598182 0 0 1-327.889491 37.489072A1690.924987 1690.924987 0 0 1 133.852608 619.453751a144.920441 144.920441 0 0 1 26.298304-96.80014zM911.610958 731.361427s-163.385207 268.578423 0 292.638573c0 0 167.301976-7.273999 0-292.638573z"
                    fill="#ffffff"
                    p-id="3924"
                  ></path>
                </svg>
                填充
              </span>
            </el-col> -->
            <el-col :span="12">
              <span
                @click="select[0] = 3"
                :class="{ dark: true, active: select[0] === 3 }"
                style="border-radius: 0"
              >
                <el-icon><Filter /></el-icon>
                取色器
              </span>
            </el-col>
          </el-row>
          <h4>颜色</h4>
          <el-color-picker v-model="select[1]" size="large" />
          <div style="padding: 10px 0">
            <div
              :class="{ colorItm: true, active: select[1] === item }"
              v-for="(item, i) in colors"
              :key="i"
              :style="'background-color:' + item"
              @click="() => colorSelect(item)"
            >
              <el-icon color="#000" class="colorIcon" v-if="select[1] === item">
                <Select />
              </el-icon>
            </div>
          </div>
          <h4>画笔尺寸</h4>
          <div>
            <div
              class="pen"
              :style="{ width: item + 'px', height: item + 'px' }"
              :class="{ active: select[2] === item }"
              @click="select[2] = item"
              v-for="(item, i) in width"
              :key="'width' + i"
            ></div>
          </div>
          <h4>不透明度</h4>
          <div class="racGroup">
            <div class="rav">
              <div
                :class="{ item: true, btm0: true, active: select[3] === 1 }"
                @click="() => selectBTM(1)"
              ></div>
            </div>
            <div class="rav">
              <div
                :class="{ item: true, btm1: true, active: select[3] === 0.8 }"
                @click="() => selectBTM(0.8)"
              ></div>
            </div>
            <div class="rav">
              <div
                :class="{ item: true, btm2: true, active: select[3] === 0.6 }"
                @click="() => selectBTM(0.6)"
              ></div>
            </div>
            <div class="rav">
              <div
                :class="{ item: true, btm3: true, active: select[3] === 0.4 }"
                @click="() => selectBTM(0.4)"
              ></div>
            </div>
            <div class="rav">
              <div
                :class="{ item: true, btm4: true, active: select[3] === 0.2 }"
                @click="() => selectBTM(0.2)"
              ></div>
            </div>
          </div>
          <h4>清晰度</h4>
          <div class="racGroup">
            <div class="rav">
              <div
                :class="{ item: true, active: select[4] === 0 }"
                @click="() => selectQXD(0)"
                style="background-color: #292b2f"
              ></div>
            </div>
            <div class="rav">
              <div
                :class="{ active: select[4] === 1 }"
                @click="() => selectQXD(1)"
              >
                <div class="qxd item" style="filter: blur(1px)"></div>
              </div>
            </div>
            <div class="rav">
              <div
                :class="{ active: select[4] === 2 }"
                @click="() => selectQXD(2)"
              >
                <div class="qxd item" style="filter: blur(3px)"></div>
              </div>
            </div>
            <div class="rav">
              <div
                :class="{ active: select[4] === 3 }"
                @click="() => selectQXD(3)"
              >
                <div class="qxd item" style="filter: blur(6px)"></div>
              </div>
            </div>
            <div class="rav">
              <div
                :class="{ active: select[4] === 4 }"
                @click="() => selectQXD(4)"
              >
                <div class="qxd item" style="filter: blur(9px)"></div>
              </div>
            </div>
          </div>
        </el-col>
        <el-col :span="12">
          <div
            :style="{
              position: 'relative',
              width: waith + 'px',
              height: height + 'px',
              margin: '0 auto',
            }"
          >
            <canvas
              class="canvasBg"
              :width="waith"
              :height="height"
              ref="canvasBg"
            ></canvas>
            <canvas
              class="canvas"
              :width="waith"
              :height="height"
              @mousedown="mousedownFunc"
              @mousemove="drawPen"
              @mouseover="mouseover"
              @mouseout="mouseout"
              ref="canvas"
            ></canvas>
          </div>
        </el-col>
        <el-col :span="6" style="position: relative">
          <h4>操作</h4>

          <span
            class="dark"
            style="display: block; width: 80%; margin: 1em auto"
            @click="fillAll"
          >
            <svg
              t="1681957205411"
              class="icon"
              viewBox="0 0 1024 1024"
              version="1.1"
              xmlns="http://www.w3.org/2000/svg"
              p-id="3923"
              width="16"
              height="16"
            >
              <path
                d="M903.77742 538.320685a246.196888 246.196888 0 0 0-99.597831-158.9089L456.146716 130.976744 290.523355 12.914146a49.239378 49.239378 0 1 0-55.953838 80.013988l74.418604 55.953838L80.136924 465.580696a245.637349 245.637349 0 0 0 55.953838 341.877951l239.482427 170.659206a245.637349 245.637349 0 0 0 341.87795-55.953838l142.122749-199.755202a245.077811 245.077811 0 0 0 44.203532-184.088128zM160.150912 522.653611l227.732121-319.496416 245.077811 174.575975 111.907676 81.133065a147.158594 147.158594 0 0 1 55.953838 148.277671 1941.598182 1941.598182 0 0 1-327.889491 37.489072A1690.924987 1690.924987 0 0 1 133.852608 619.453751a144.920441 144.920441 0 0 1 26.298304-96.80014zM911.610958 731.361427s-163.385207 268.578423 0 292.638573c0 0 167.301976-7.273999 0-292.638573z"
                fill="#ffffff"
                p-id="3924"
              ></path>
            </svg>
            填充全部
          </span>
          <span
            class="dark"
            style="display: block; width: 80%; margin: 1em auto"
            @click="clearAll"
          >
            <el-icon><Close /></el-icon>
            清除
          </span>
          <span
            class="dark"
            style="display: block; width: 80%; margin: 1em auto"
            @click="() => step(-1)"
          >
            <el-icon><RefreshLeft /></el-icon>
            上一步
          </span>
          <span
            class="dark"
            style="display: block; width: 80%; margin: 1em auto"
            @click="() => step(1)"
          >
            <el-icon><RefreshRight /></el-icon>
            下一步
          </span>

          <span
            class="dark"
            style="display: block; width: 80%; margin: 1em auto"
            @click="save"
          >
            <el-icon><FolderChecked /></el-icon>
            保 存
          </span>
        </el-col>
      </el-row>
    </div>
  </div>
</template>

<script setup>
import { defineProps, defineEmits, ref, onMounted, nextTick } from 'vue';
const props = defineProps({
  file: Object,
});

let mouseDown = false;
const colors = [
  'rgb(234, 153, 153)',
  'rgb(224, 102, 102)',
  'rgb(204, 0, 0)',
  'rgb(153, 0, 0)',
  'rgb(102, 0, 0)',
  'rgb(249, 203, 156)',
  'rgb(246, 178, 107)',
  'rgb(230, 145, 56)',
  'rgb(180, 95, 6)',
  'rgb(120, 63, 4)',
  'rgb(255, 229, 153)',
  'rgb(255, 217, 102)',
  'rgb(241, 194, 50)',
  'rgb(191, 144, 0)',
  'rgb(127, 96, 0)',
  'rgb(182, 215, 168)',
  'rgb(147, 196, 125)',
  'rgb(106, 168, 79)',
  'rgb(56, 118, 29)',
  'rgb(39, 78, 19)',
  'rgb(164, 194, 244)',
  'rgb(109, 158, 235)',
  'rgb(60, 120, 216)',
  'rgb(17, 85, 204)',
  'rgb(28, 69, 135)',
  'rgb(180, 167, 214)',
  'rgb(142, 124, 195)',
  'rgb(103, 78, 167)',
  'rgb(53, 28, 117)',
  'rgb(32, 18, 77)',
  'rgb(213, 166, 189)',
  'rgb(194, 123, 160)',
  'rgb(166, 77, 121)',
  'rgb(116, 27, 71)',
  'rgb(76, 17, 48)',
  'rgb(255, 255, 255)',
  'rgb(192, 192, 192)',
  'rgb(131, 131, 131)',
  'rgb(82, 82, 82)',
  'rgb(0, 0, 0)',
];
const canvas = ref(null);
const canvasBg = ref(null);
let ctx = undefined;
let ctxBg = undefined;
let isclean = false;
const select = ref([0, 'rgb(241, 194, 50)', 48, 1, 0]);
const emit = defineEmits(['closemain', 'getimage']);
const close = () => {
  emit('closemain');
};

const waith = ref(512);
const height = ref(512);
const img = new Image(); // 传入图片

let indexBase = 0; // 当前绘制到哪一步

// 线条集合
let pathList = [];
// 粗细
const width = [6, 14, 16, 24, 30, 40, 48, 64];

// 填充
// const fillColor = () => {
//   select.value[0] = 2;
//   ctxBg.beginPath();
//   ctxBg.fillRect(0, 0, waith.value, height.value);
// };
const fillAll = () => {
  const conf = {
    globalAlpha: select.value[3],
    filter: select.value[4] * 50,
    strokeStyle: select.value[1],
    shadowColor: select.value[1],
    lineWidth: select.value[2],
    lineCap: 'round',
    lineJoin: 'round',
    type: 'rect',
  };
  ctxBg.beginPath();
  ctxBg.lineCap = conf.lineCap;
  ctxBg.lineJoin = conf.lineJoin;
  conf.filter && (ctxBg.filter = 'blur(' + conf.filter + 'px)');
  ctxBg.shadowColor = conf.shadowColor;
  ctxBg.fillStyle = conf.strokeStyle;
  ctxBg.globalAlpha = conf.globalAlpha;
  pathList.push(conf);
  indexBase = pathList.length;
  ctxBg.fillRect(0, 0, waith.value, height.value);
  ctxBg.closePath();
};

// 上一步下一步
const step = I => {
  if (indexBase + I < 0) {
    indexBase = 0;
    drawBg();
    return;
  }
  if (indexBase + I > pathList.length) {
    indexBase = pathList.length;
    // drawBg();
    return;
  }
  indexBase += I;
  drawBg();
};
// 清除
const clearAll = () => {
  pathList = [];
  isclean = true;
  canvas.value.width = waith.value;
  canvasBg.value.width = waith.value;
};

const selectBTM = index => {
  select.value[3] = index;
};

const selectQXD = index => {
  select.value[4] = index;
};

const colorSelect = color => {
  select.value[1] = color;
};

const drawPen = ele => {
  // 绘制
  const n = !(select.value[0] === 0 || select.value[0] === 1);
  if (n || !mouseDown || !pathList.length) return;
  const w = canvas.value.width;
  canvas.value.width = w;
  ctx.beginPath();
  const o = pathList[pathList.length - 1] || {};
  o.path.push({
    x: ele.offsetX,
    y: ele.offsetY,
  });
  ctx.lineCap = o.lineCap;
  ctx.lineJoin = o.lineJoin;
  ctx.filter = 'blur(' + o.filter + 'px)';
  ctx.shadowColor = o.shadowColor;
  ctx.strokeStyle = o.strokeStyle;
  ctx.fillStyle = o.strokeStyle;
  ctx.globalAlpha = o.globalAlpha;
  ctx.lineWidth = o.lineWidth;
  for (let i = 1; i < o.path.length; i++) {
    const v = o.path[i];
    const ov = o.path[i - 1];
    ctx.quadraticCurveTo(ov.x, ov.y, v.x, v.y);
  }
  ctx.stroke();
  ctx.closePath();
};

const mousedownFunc = ele => {
  // 鼠标按下
  if (select.value[0] === 3) {
    // 取色
    const colorList =
      ctxBg.getImageData(0, 0, waith.value, height.value).data || [];
    const starts = (ele.offsetY * waith.value + ele.offsetX) * 4;
    let l = [colorList[starts], colorList[starts + 1], colorList[starts + 2]];
    if (colorList[starts + 3] == 0) {
      l = [255, 255, 255];
    }
    select.value[1] = 'rgb(' + l.join(',') + ')';
    return;
  }
  if (!(select.value[0] === 0 || select.value[0] === 1)) return;
  mouseDown = true;
  start(ele);
};

const mouseup = () => {
  // 鼠标松开
  if (!mouseDown) return;
  if (!(select.value[0] === 0 || select.value[0] === 1)) return;
  drawBg();
  mouseDown = false;
};

const mouseover = ele => {
  // 鼠标移入
  start(ele);
};

const start = ele => {
  if (!mouseDown) return;
  const conf = {
    globalAlpha: select.value[3],
    filter: select.value[4] * 5,
    strokeStyle: select.value[1],
    shadowColor: select.value[1],
    lineWidth: select.value[2],
    lineCap: 'round',
    lineJoin: 'round',
    type: 'line',
    // type: select.value[4] === 0 ? 'line' : 'spray',
    path: [{ x: ele.offsetX, y: ele.offsetY }],
    isEraser: select.value[0] === 1,
  };
  if (select.value[0] === 1) {
    // 橡皮擦  绘制白色背景线条
    conf.shadowColor = 'rgb(255,255,255)';
    conf.strokeStyle = 'rgb(255,255,255)';
    ctx.globalCompositeOperation = 'destination-out';
  }
  pathList.push(conf);
  indexBase = pathList.length;

  ctx.beginPath();
  if (conf.type === 'line') {
    ctx.lineCap = conf.lineCap;
    ctx.lineJoin = conf.lineJoin;
    ctx.filter = 'blur(' + conf.filter + 'px)';
    ctx.shadowColor = conf.shadowColor;
    ctx.strokeStyle = conf.strokeStyle;
    ctx.globalAlpha = conf.globalAlpha;
    ctx.lineWidth = conf.lineWidth;
    ctx.moveTo(conf.path[0].x, conf.path[0].y);
    ctx.closePath();
  } else {
    ctx.filter = 'none';
  }
};

const mouseout = () => {
  // 鼠标移出
  if (!mouseDown) return;
  drawBg();
};

//将线条绘制到背景canvas上
const drawBg = () => {
  if (!pathList.length) return;
  const wbg = canvasBg.value.width;
  canvasBg.value.width = wbg;
  const end = Math.min(indexBase, pathList.length);
  if (!isclean && props.file.fileResult) {
    ctxBg.drawImage(img, 0, 0, waith.value, height.value);
  }else {
    ctxBg.beginPath();
    ctxBg.shadowColor = '#ffffff';
    ctxBg.fillStyle = '#ffffff';
    ctxBg.fillRect(0, 0, waith.value, height.value);
    ctxBg.closePath();
  }

  for (let o = 0; o < end; o++) {
    const config = pathList[o];
    if (config.type == 'rect') {
      ctxBg.beginPath();
      ctxBg.fillStyle = config.strokeStyle;
      ctxBg.lineCap = config.lineCap;
      ctxBg.lineJoin = config.lineJoin;
      ctxBg.filter = 'blur(' + config.filter + 'px)';
      ctxBg.shadowColor = config.shadowColor;
      ctxBg.globalAlpha = config.globalAlpha;
      ctxBg.fillRect(0, 0, waith.value, height.value);
      ctxBg.closePath();
    }
    if (config.type !== 'line') continue;
    ctxBg.beginPath();
    ctxBg.lineCap = config.lineCap;
    ctxBg.lineJoin = config.lineJoin;
    ctxBg.filter = 'blur(' + config.filter + 'px)';
    ctxBg.shadowColor = config.shadowColor;
    ctxBg.strokeStyle = config.strokeStyle;
    ctxBg.fillStyle = config.strokeStyle;
    ctxBg.globalAlpha = config.globalAlpha;
    ctxBg.lineWidth = config.lineWidth;
    if (config.isEraser) {
      ctx.globalCompositeOperation = 'destination-out';
    }
    ctxBg.moveTo(config.path[0].x, config.path[0].y);
    for (let i = 1; i < config.path.length; i++) {
      const v = config.path[i];
      const ov = config.path[i - 1];
      ctxBg.quadraticCurveTo(ov.x, ov.y, v.x, v.y);
    }
    ctxBg.stroke();
    ctxBg.closePath();
  }
  const w = canvas.value.width;
  canvas.value.width = w;
};

onMounted(() => {
  ctx = canvas.value.getContext('2d');
  ctxBg = canvasBg.value.getContext('2d');

  if (props.file.fileResult) {
    img.src = props.file.fileResult + '';
    img.onload = () => {
      height.value = (img.height * waith.value) / img.width;
      nextTick(() => {
        ctxBg.drawImage(img, 0, 0, waith.value, height.value);
      });
    };
  } else {
    ctxBg.beginPath();
    ctxBg.shadowColor = '#ffffff';
    ctxBg.fillStyle = '#ffffff';
    ctxBg.fillRect(0, 0, waith.value, height.value);
    ctxBg.closePath();
  }
});

const save = () => {
  emit('getimage', canvasBg.value.toDataURL());
  emit('closemain');
};
</script>

<style scoped>
.edit {
  position: fixed;
  z-index: 1;
  top: 0;
  left: 0;
  background-color: #00000060;
  padding: 1em;
  width: 100vw;
  height: 100vh;
}

.main {
  width: 100%;
  height: 100%;
  border-radius: 25px;
  background-color: #2f3136;
}
h1 {
  text-align: center;
  padding: 10px 0;
}
h4 {
  margin: 1em 0;
}
h4:first-child {
  margin-top: 0;
}

.closeMain {
  float: right;
  margin-right: 15px;
}

.racGroup {
  display: flex;
}
.rav {
  flex: 1;
}
.item {
  position: relative;
  width: 32px;
  height: 32px;
  border-radius: 16px;
  background: #292b2f;
  cursor: pointer;
  transition: opacity 0.25s;
  border: 1px solid #292b2f;
}

.btm0 {
  background: repeating-conic-gradient(
      rgba(0, 0, 0, 0) 0%,
      rgba(0, 0, 0, 0) 25%,
      rgba(255, 255, 255, 0) 0%,
      rgba(255, 255, 255, 0) 50%
    )
    50% center / 10px 10px;
}
.btm1 {
  background: repeating-conic-gradient(
      rgba(0, 0, 0, 0.2) 0%,
      rgba(0, 0, 0, 0.2) 25%,
      rgba(255, 255, 255, 0.2) 0%,
      rgba(255, 255, 255, 0.2) 50%
    )
    50% center / 10px 10px;
}
.btm2 {
  background: repeating-conic-gradient(
      rgba(0, 0, 0, 0.4) 0%,
      rgba(0, 0, 0, 0.4) 25%,
      rgba(255, 255, 255, 0.4) 0%,
      rgba(255, 255, 255, 0.4) 50%
    )
    50% center / 10px 10px;
}
.btm3 {
  background: repeating-conic-gradient(
      rgba(0, 0, 0, 0.6) 0%,
      rgba(0, 0, 0, 0.6) 25%,
      rgba(255, 255, 255, 0.6) 0%,
      rgba(255, 255, 255, 0.6) 50%
    )
    50% center / 10px 10px;
}
.btm4 {
  background: repeating-conic-gradient(
      rgba(0, 0, 0, 0.8) 0%,
      rgba(0, 0, 0, 0.8) 25%,
      rgba(255, 255, 255, 0.8) 0%,
      rgba(255, 255, 255, 0.8) 50%
    )
    50% center / 10px 10px;
}

.qxd {
  background: #292b2f;
  width: 30px;
  height: 30px;
  border-radius: 32px;
}

.pen {
  border-radius: 50%;
  background-color: #292b2f;
  width: 6px;
  height: 6px;
  display: inline-block;
  margin-right: 5px;
}
.colorItm {
  width: 32px;
  height: 32px;
  margin: 0 20px 5px 0;
  border-radius: 50%;
  display: inline-block;
  position: relative;
}
.colorIcon {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.dark {
  background-color: #292b2f;
  border-radius: 2em;
  padding: 5px 0;
  text-align: center;
  width: 8em;
  display: inline-block;
  border: 1px solid #00000000;
}
.active {
  border: 1px solid #3584e4;
  display: inline-block;
  border-radius: 50%;
}

.canvas {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
}
.canvasBg {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  background: #ffffff;
}
</style>
