<template>
<div id="app">
<div class="area">
<canvas style="width: 100vw;height:200px;border:1px solid #ccc;" ref="canvas" @touchstart="touchStart"
@touchmove="touchMove" @touchend="touchEnd">
</canvas>
<!-- <canvas ref="canvas"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="mouseUp">
</canvas> -->
</div>
<button class="btn" @click="preview">预览</button>
<button class="btn" @click="revert">撤销</button>
<button class="btn" @click="clear">清空</button>
<button class="btn" @click="save">保存</button>
<button class="btn" @click="clip">裁剪</button>
<div class="preview">
<img src="" alt="">
</div>
</div>
</template>
<script setup>
import { onMounted, reactive, ref } from 'vue';
const canvas = ref(null)
const that = reactive({
canvasRect: null, // 宽高clientRect数据
ctx: null, // 画笔对象
startX: 0,
startY: 0,
endX: 0,
endY: 0,
lineWidth: 3,
lineColor: '#000',
isCrop: true, // 剪裁
storageSteps: [], // 记录每步操作
isDrawing: false, // 是否正在绘制
isEmpty: true, // 画板是否为空
})
onMounted(() => {
console.log('asas')
init()
// 在画板以外松开鼠标后冻结画笔
document.onmouseup = () => {
that.isDrawing = false
}
})
const init = () => {
const canvass = canvas.value;
that.canvasRect = canvass.getBoundingClientRect();
console.log('init', that.canvasRect)
canvass.width = that.canvasRect.width;
canvass.height = that.canvasRect.height;
that.ctx = canvass.getContext('2d')
}
const touchStart = (e) => {
e.preventDefault();
that.startX = e.targetTouches[0].clientX - that.canvasRect.left;
that.startY = e.targetTouches[0].clientY - that.canvasRect.top;
that.endX = that.startX;
that.endY = that.startY;
draw();
}
const touchMove = (e) => {
e.preventDefault();
that.endX = e.targetTouches[0].clientX - that.canvasRect.left;
that.endY = e.targetTouches[0].clientY - that.canvasRect.top;
draw()
that.startX = that.endX;
that.startY = that.endY;
}
const touchEnd = (e) => {
e.preventDefault();
that.endX = e.changedTouches[0].clientX - that.canvasRect.left;
that.endY = e.changedTouches[0].clientY - that.canvasRect.top;
let imgData = that.ctx.getImageData(0, 0, that.canvasRect.width, that.canvasRect.height)
console.log(imgData)
that.storageSteps.push(imgData)
}
// 绘制
const draw = () => {
that.ctx.beginPath();
that.ctx.moveTo(that.startX, that.startY);
that.ctx.lineTo(that.endX, that.endY);
that.ctx.lineCap = 'round';
that.ctx.lineJoin = 'round';
that.ctx.lineWidth = that.lineWidth;
that.ctx.strokeStyle = that.lineColor;
that.ctx.stroke();
that.ctx.closePath();
that.isEmpty = false;
}
// 清空
const clear = () => {
that.ctx.clearRect(0, 0, that.canvasRect.width, that.canvasRect.height);
that.storageSteps = []; // 清空清楚步骤记录
that.isEmpty = true; // 清空标记
}
// touched事件
const touchEnds = (e) => {
e.preventDefault();
that.endX = e.changedTouches[0].clientX - that.canvasRect.left;
that.endY = e.changedTouches[0].clientY - that.canvasRect.top;
let imgData = that.ctx.getImageData(0, 0, that.canvasRect.width, that.canvasRect.height) // 绘制结束记录当前画布信息
console.log(imgData)
that.storageSteps.push(imgData)
}
// 撤销
const revert = () => {
that.storageSteps.pop()
const len = that.storageSteps.length;
if (len) {
that.ctx.putImageData(that.storageSteps[len - 1], 0, 0);
} else {
clear()
}
}
// 预览
const preview = () => {
const base64 = canvas.value.toDataURL('image/png');
console.log(base64)
const img = document.querySelector('.preview img');
img.src = base64;
img.width = that.canvasRect.width;
img.height = that.canvasRect.height;
}
// 保存
const save = () => {
if (that.isEmpty) {
console.log('画布为空!')
return
}
const name = prompt('请输入名称', 'canvas签名');
if (name && name.trim()) {
const a = document.createElement('a');
a.download = name;
a.href = this.$refs.canvas.toDataURL('image/png');
a.dispatchEvent(new MouseEvent('click'));
}
}
</script>
适用于移动端
pc端使用只需要修改html中事件名即可