闫增涛
2024-07-03 ddfc3f553120cd2dc08a2f2172f12c752adc65a0
src/components/graffiti/index.vue
@@ -1,6 +1,6 @@
<!-- 涂色连线题控件 -->
<template>
  <div class="page" :style="{height:imgHeight + 120 + 'px'}">
  <div class="page" :style="{ height: imgHeight + 120 + 'px' }">
    <div class="main">
      <div id="canvas_panel">
        <canvas
@@ -13,8 +13,12 @@
        >
      </div>
    </div>
    <div class="footer">
      <BrushSize :size="brushSize" @change-size="onChangeSize"  @change-color="onChangeColor" />
    <div class="footer" :style="{ backgroundColor: bcColor }">
      <BrushSize
        :size="brushSize"
        @change-size="onChangeSize"
        @change-color="onChangeColor"
      />
      <ToolBtns :tool="brushTool" @change-tool="onChangeTool" />
    </div>
  </div>
@@ -26,25 +30,29 @@
export default {
  name: "graffiti",
  components: { BrushSize, ToolBtns },
  props:{
    page:{
      type:Number
  props: {
    page: {
      type: Number,
    },
    bcImg:{
      type:String
    bcImg: {
      type: String,
    },
    imgWidth:{
      type:Number
    imgWidth: {
      type: Number,
    },
    imgHeight:{
      type:Number
    }
    imgHeight: {
      type: Number,
    },
    bcColor: {
      type: String,
      default: "#fff",
    },
  },
  data() {
    return {
      canvas: null,
      context: null,
      painting: false,  // 记录状态,鼠标是否在按下状态
      painting: false, // 记录状态,鼠标是否在按下状态
      historyData: [], // 存储历史数据,用于撤销
      brushSize: 5, // 笔刷大小
      brushColor: "#000000", // 笔刷颜色
@@ -53,18 +61,23 @@
        left: 0,
        top: 0,
      },
      backgroundImage:
        "",
      backgroundImage: "",
    };
  },
  mounted() {
    this.backgroundImage = this.bcImg
    this.canvas = document.getElementById("canvas");
    this.backgroundImage = this.bcImg;
    this.canvas = (this.container ? this.container : document).getElementById(
      "canvas"
    );
    if (this.canvas.getContext) {
      this.context = this.canvas.getContext("2d", { willReadFrequently: true });
      this.initCanvas();
      // window.addEventListener('resize', updateCanvasPosition);
      window.addEventListener("scroll",this.updateCanvasOffset,true); // 添加滚动条滚动事件监听器
      (this.container ? this.container : document).addEventListener(
        "scroll",
        this.updateCanvasOffset,
        true
      ); // 添加滚动条滚动事件监听器
      this.getCanvasOffset();
      this.context.lineGap = "round";
      this.context.lineJoin = "round";
@@ -74,9 +87,11 @@
      this.canvas.addEventListener("mouseleave", this.closePaint);
    }
    this.toolClear();
    const oldData = localStorage.getItem(this.config.activeBook.name + '-graffiti-' + this.page)
    if(oldData) {
      this.backgroundImage = oldData
    const oldData = localStorage.getItem(
      this.config.activeBook.name + "-graffiti-" + this.page
    );
    if (oldData) {
      this.backgroundImage = oldData;
    }
  },
  // watch:{
@@ -105,11 +120,16 @@
    },
    // 初始化 画布,设置大小背景色
    initCanvas() {
      const that = this
      const that = this;
      const resetCanvas = () => {
        const elPanel = document.getElementById("canvas_panel");
        that.canvas.width = elPanel.clientWidth;
        that.canvas.height = elPanel.clientHeight;
        const elPanel = (
          this.container ? this.container : document
        ).getElementById("canvas_panel");
        try {
          that.canvas.width = elPanel.clientWidth;
          that.canvas.height = elPanel.clientHeight;
        } catch (error) {}
        that.context = that.canvas.getContext("2d", {
          willReadFrequently: true,
        }); // 添加这一行
@@ -120,17 +140,19 @@
        // 设置画布背景图
        const imgData = new Image();
        // 分两种情况,初次的图片 直接用外部链接,需要加跨域和时间戳,二次保存的作为背景则不需要
        const oldData = localStorage.getItem(this.config.activeBook.name + '-graffiti-' + this.page)
        if(oldData) {
          imgData.src = oldData
        const oldData = localStorage.getItem(
          this.config.activeBook.name + "-graffiti-" + this.page
        );
        if (oldData) {
          imgData.src = oldData;
        } else {
          imgData.src = this.backgroundImage + '?' + new Date().getTime();
          imgData.setAttribute('crossOrigin', '');
          imgData.src = this.backgroundImage + "?" + new Date().getTime();
          imgData.setAttribute("crossOrigin", "");
        }
        imgData.onload = () => {
          this.context.drawImage(imgData,0,0,this.imgWidth,this.imgHeight)
        }
      }
          this.context.drawImage(imgData, 0, 0, this.imgWidth, this.imgHeight);
        };
      };
      resetCanvas();
      // 监听窗口大小 ,窗口改变重新渲染画布
      window.addEventListener("resize", resetCanvas);
@@ -184,7 +206,7 @@
    },
    // 重新计算画布的偏移值
    updateCanvasOffset() {
      this.getCanvasOffset();
      this.getCanvasOffset();
    },
    // 改变笔刷大小
    onChangeSize(size) {
@@ -216,45 +238,64 @@
      // 新加内容,清空后将背景图再设置上去
      const imgData = new Image();
      // 分两种情况,初次的图片 直接用外部链接,需要加跨域和时间戳,二次保存的作为背景则不需要
      const oldData = localStorage.getItem(this.config.activeBook.name + '-graffiti-' + this.page)
      if(oldData) {
        imgData.src = oldData
      const oldData = localStorage.getItem(
        this.config.activeBook.name + "-graffiti-" + this.page
      );
      if (oldData) {
        imgData.src = oldData;
      } else {
        imgData.src = this.backgroundImage + '?' + new Date().getTime();
        imgData.setAttribute('crossOrigin', '');
        imgData.src = this.backgroundImage + "?" + new Date().getTime();
        imgData.setAttribute("crossOrigin", "");
      }
      imgData.onload = () => {
        this.context.drawImage(imgData,0,0,this.imgWidth,this.imgHeight)
      }
        this.context.drawImage(imgData, 0, 0, this.imgWidth, this.imgHeight);
      };
    },
    // 保存画布背景和划线到本地方法
    toolSave() {
      var imgData = this.canvas.toDataURL({format: 'png', quality:1, width:800,});
      localStorage.setItem(this.config.activeBook.name + '-graffiti-' + this.page,imgData)
      var imgData = this.canvas.toDataURL({
        format: "png",
        quality: 1,
        width: 800,
      });
      localStorage.setItem(
        this.config.activeBook.name + "-graffiti-" + this.page,
        imgData
      );
    },
    // 保存为一张图片并下载的方法
    saveImgData() {
      var link = document.createElement("a");
      var imgData = this.canvas.toDataURL({format: 'png', quality:1, width:20000, height:4000});
      var link = (this.container ? this.container : document).createElement(
        "a"
      );
      var imgData = this.canvas.toDataURL({
        format: "png",
        quality: 1,
        width: 20000,
        height: 4000,
      });
      var strDataURI = imgData.substr(22, imgData.length);
      var blob = dataURLtoBlob(imgData);
      var objurl = URL.createObjectURL(blob);
      link.download = "grid1.png";
      link.href = objurl;
      link.click();
      function  dataURLtoBlob(dataurl) {
        var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
          bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
        while(n--){
      function dataURLtoBlob(dataurl) {
        var arr = dataurl.split(","),
          mime = arr[0].match(/:(.*?);/)[1],
          bstr = atob(arr[1]),
          n = bstr.length,
          u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        return new Blob([u8arr], {type:mime});
        return new Blob([u8arr], { type: mime });
      }
    },
    // 返回上一步方法(撤销)
    toolUndo() {
      //
      //
      if (this.historyData.length <= 0) {
        this.resetToolActive();
        return;
@@ -269,7 +310,6 @@
    saveData(data) {
      this.historyData.length >= 50 && this.historyData.shift(); // 设置储存上限为50步
      this.historyData.push(data);
      console.log('数据',this.historyData);
    },
    // 清除、撤销、保存状态不需要保持,操作完后恢复笔刷状态
    resetToolActive() {
@@ -285,7 +325,7 @@
.page {
  display: flex;
  flex-direction: column;
  width:100%;
  width: 100%;
}
.main {
@@ -297,7 +337,6 @@
  justify-content: space-around;
  align-items: center;
  height: 88px;
  background-color: #fff;
}
#canvas_panel {