vue3.2 setup语法糖实现手写签名

<template>
  <div class="signature" @touchmove.prevent>
    <div class="boardBox" ref="boardBox">
      <canvas ref="board" id="canvas" @touchstart="mStart" @touchmove="mMove" @touchend="mEnd"></canvas>
    </div>
    <div class="bar" ref="barrie">
      <div class="item" @click="goback">
        <div class="ico">
        </div>
        <!-- <div class="text">取消</div> -->
        <van-button style="width: 80px;" type="default">取消</van-button>
      </div>
      <div class="item" @click="clearCanvas">
        <div class="ico">
        </div>
        <van-button style="width: 80px;" type="warning">重绘</van-button>
      </div>
      <div class="item" @click="getcanvas">
        <div class="ico">
        </div>
        <van-button style="width: 80px;" type="primary">保存</van-button>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {onMounted, reactive, ref} from "vue";
import {uploadFileApi} from "@/api/PublicApi";
import {base64toFile} from "@/utils/common";

const baseData = ref("")
const ctx = ref<any>(null)
const point = reactive({
  x: 0,
  y: 0
})
const moving = ref(false)
const mubHeight = ref(0)

const board = ref(); // 获取DOM
const boardBox = ref();
const barrie = ref()

/*初始化*/
onMounted(() => {
  board.value.width = boardBox.value.offsetWidth; // 设置画布宽
  board.value.height = boardBox.value.offsetHeight; // 设置画布高
  ctx.value = board.value.getContext("2d"); // 二维绘图
  ctx.value.strokeStyle = "#000"; // 颜色
  ctx.value.lineWidth = 3; // 线条宽度
  mubHeight.value = document.body.clientHeight - (boardBox.value.offsetHeight + barrie.value.offsetHeight)
})

// 滑动开始
const mStart = (e: any) => {
  const x = e.touches[0].clientX - e.target.offsetLeft
  const y = e.touches[0].clientY - mubHeight.value // 获取触摸点在画板(canvas)的坐标
  // console.log(x, 555);
  // console.log(y, 555);
  point.x = x;
  point.y = y;
  ctx.value.beginPath();
  moving.value = true;
}

// 滑动
const mMove = (e: any) => {
  if (moving.value) {
    mubHeight.value
    const x = e.touches[0].clientX - e.target.offsetLeft
    const y = e.touches[0].clientY - mubHeight.value; // 获取触摸点在画板(canvas)的坐标
    ctx.value.moveTo(point.x, point.y); // 把路径移动到画布中的指定点,不创建线条(起始点)
    ctx.value.lineTo(x, y); // 添加一个新点,然后创建从该点到画布中最后指定点的线条,不创建线条
    ctx.value.stroke(); // 绘制
    point.x = x;
    point.y = y; // 重置点坐标为上一个坐标
  }
}

// 滑动结束
const mEnd = () => {
  if (moving.value) {
    ctx.value.closePath(); // 停止绘制
    moving.value = false; // 关闭绘制开关
  }
}

// 保存
const getcanvas = () => {
  //绘画转图片
  const d = document.getElementById("canvas") as any
  d.toDataURL("image/png");
  d.toBlob(async (blobObj: any) => {
    const file1 = new File([blobObj], "pic.png", {
      type: blobObj.type,
      lastModified: Date.now(),
    });
    convertImg(file1);
  });
}

//旋转图片
const convertImg = (file: any) => {
  var canvas1 = document.createElement("canvas");
  var context1 = canvas1.getContext("2d") as any
  var oReader = new FileReader();
  oReader.readAsDataURL(file);
  oReader.onload = function (e: any) {
    var img = new Image() as any
    img.src = e.target.result;
    img.onload = function () {
      // 图片原始尺寸
      var originWidth = this.width;
      var originHeight = this.height;
      // 最大尺寸限制
      var maxWidth = 1080,
          maxHeight = 1080;
      // 目标尺寸
      var targetWidth = originWidth,
          targetHeight = originHeight;
      // 图片尺寸超过300x300的限制
      if (originWidth > maxWidth || originHeight > maxHeight) {
        if (originWidth / originHeight > maxWidth / maxHeight) {
          targetWidth = maxWidth;
          targetHeight = Math.round(
              maxWidth * (originHeight / originWidth)
          );
        } else {
          targetHeight = maxHeight;
          targetWidth = Math.round(
              maxHeight * (originWidth / originHeight)
          );
        }
      }
      const type = "image/jpeg";
      // canvas对图片进行缩放
      canvas1.width = targetHeight;
      canvas1.height = targetWidth;
      // 旋转90度
      context1.translate(0, 0);
      context1.rotate(Math.PI / 2);
      // (0,-imgHeight) 从旋转原理图那里获得的起始点
      // context.clearRect(0,  -targetHeight, targetWidth, targetHeight);
      context1.drawImage(img, 0, -targetHeight, targetWidth, targetHeight);
      // 将canvas的透明背景设置成白色
      var imageData = context1.getImageData(
          0,
          0,
          canvas1.width,
          canvas1.height
      );
      for (var i = 0; i < imageData.data.length; i += 4) {
        // 当该像素是透明的,则设置成白色
        if (imageData.data[i + 3] == 0) {
          imageData.data[i] = 255;
          imageData.data[i + 1] = 255;
          imageData.data[i + 2] = 255;
          imageData.data[i + 3] = 255;
        }
      }
      context1.putImageData(imageData, 0, 0);
      const dataurl = canvas1.toDataURL(type);
      baseData.value = dataurl;
      let newFile = base64toFile(dataurl, "lll.png")
      let param = new FormData()
      param.append('file', newFile)
      uploadFileApi(param).then((res: any) => {
        console.log()
      })

    };
  };
}

//清除画布
function clearCanvas() {
  var c = document.getElementById("canvas") as any;
  c.height = c.height;
  ctx.value.lineWidth = 3;
}

//返回上一级
function goback() {
  // router.go(-1)
}
</script>

<style scoped lang="scss">
.loadingtext {
  transform: rotate(-90deg);
  color: red;
}

// .item {
//   -webkit-transform: rotate(-90deg);
// }

.text {
  text-align: center;
}

.boardBox {
  width: 100vw;
  height: 90vh;
  background: #f9f9f9;
}

.bar {
  box-sizing: border-box;
  padding: 0rem 1rem;
  display: flex;
  width: 100vw;
  height: 10vh;
  background-color: #ffffff;
  justify-content: space-around;
  align-items: center;
}

.shade {
  width: 100vw;
  height: 50vh;
  position: fixed;
  top: 0;
  background-color: #333333;
  z-index: 66666;
  opacity: 0.9;

  .minishade {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
</style>

猜你喜欢

转载自blog.csdn.net/weixin_42078172/article/details/128497663