版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
为了方便以后的使用我将canvas画板封装成了一个对象,使用的时候只需引入之后new成对象即可使用。并有清空画板、改变画笔颜色、粗细、历史上一笔、下一笔等功能
html
<template>
<div class="canvas">
<div class="btnBox">
<div class="item">
<el-button @click="drawCanvas.resetCanvas()">清空canvas</el-button>
</div>
<div class="item">
<el-color-picker
@change="drawCanvas.setColor(color)"
v-model="color" />
</div>
<div class="item">
<el-slider
v-model="size"
:max="15"
:min="1"
input-size="mini"
@change="drawCanvas.setPenSize(size)"
@input="drawCanvas.setPenSize(size)"
show-input />
<div
class="size"
:style="{
width: size * 2 + 'px',
height: size * 2 + 'px',
background: color
}"></div>
</div>
<div class="item">
<el-button @click="drawCanvas.init(list)">初始化</el-button>
</div>
<div class="item">
<el-button @click="front">前一笔</el-button>
</div>
<div class="item">
<el-button @click="after">后一笔</el-button>
</div>
</div>
<canvas width="500" height="300" id="canvas" ref="canvas"></canvas>
</div>
</template>
<script>
import Draw from "../util/drawClass";
export default {
name: "canvas",
components: {},
data() {
return {
drawCanvas: null,
color: "#409EFF",
size: 2
};
},
mounted() {
this.drawCanvas = new Draw("canvas", [], '#999999', this.color, this.size); //不能直接在data赋值响因为刚完成响应式转换还没有dom元素
},
computed: {
list() {
return this.$store.state.canvasList;
}
},
watch: {
list(value) {
console.log(value);
}
},
methods: {
front() {
const res = this.drawCanvas.front();
if (res.code === 404) this.$message.warning(res.msg);
},
after() {
const res = this.drawCanvas.after();
if (res.code === 404) this.$message.warning(res.msg);
}
}
};
</script>
<style lang="scss">
.btnBox {
margin: 0 auto 20px auto;
width: 300px;
padding: 10px;
box-sizing: border-box;
.item{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
.el-button{
width: 100%
}
.size{
margin: 0 10px;
border-radius: 50%;
}
.el-slider{
flex: 1;
.el-slider__runway.show-input{
margin-right: 110px;
}
.el-slider__input{
width: 95px
}
}
}
}
</style>
封装的对象
import store from '../vuex_study_module/store'
/**
* canvas画板
* 兼容移动端touch事件
* ----------传入的参数-----------
* @tag canvas的id
* @historyList 历史纪录的点
* @background 背景色
* @color 画笔颜色
* @size 画笔大小
* ----------提供的方法-----------
* @resetCanvas 清空canvas的方法
* @init 还原所有画笔的画布 options {[{size: String,color: Number,list: [[12,13],[14,15]]}]}
* @after 后一步画布
* @front 前一步画布
* @getPointList 获取画笔记录
* @setColor 设置颜色 options String
* @setPenSize 设置画笔的大小 options Number
*/
export default class Draw {
constructor(tag, historyList, background, color, size) {
this.canvas = document.getElementById(tag)
this.ctx = this.canvas.getContext("2d")
this.width = this.canvas.offsetWidth
this.height = this.canvas.offsetHeight
this.canvas.width = this.width
this.canvas.height = this.height
this.canvasOffsetTop = this.canvas.offsetTop//移动端canvas距离顶部的距离
this.canvasOffsetLeft = this.canvas.offsetLeft//移动端canvas距离左边的距离
this.startPosition = []//当前的点
this.isdraw = false//是否在作画
this.history = historyList ? historyList : []//所有的历史画笔集合
this.isInit = false//是否为初始化
this.currentPen = []//当前画笔
this.drawStep = 0//当前第几笔画
this.penSize = size//画笔大小
this.penColor = color//画笔颜色
this.backGround = background ? background : '#999999'//画布背景色
this.ctx.fillStyle = this.backGround
this.ctx.lineWidth = size * 2 + 1//线的宽度
this.ctx.strokeStyle = color//点的颜色
this.ctx.fillRect(0, 0, this.width, this.height)//画布大小
this.canvas.addEventListener('touchmove', function (e) { //禁止页面滚动
e.preventDefault();
}, {passive: false}); //passive 参数不能省略,用来兼容ios和android
this.canvas.removeEventListener('touchend', function (e) { //解除页面滚动
e.preventDefault();
}, {passive: false});
this.canvas.onmousedown = res => {
//指针在canvas上点击
this.isdraw = true;
this.startPosition[0] = res.offsetX;
this.startPosition[1] = res.offsetY;
this.drawLine(this.startPosition[0], this.startPosition[1]);
}
this.canvas.onmouseup = res => {
//指针在canvas上放开
if (!this.isdraw) return;
this.clear();
}
this.canvas.onmouseout = res => {
//指针移出canvas
if (!this.isdraw) return;
this.clear();
}
this.canvas.onmousemove = res => {
//指针在canvas移动
if (!this.isdraw) return;
this.drawLine(res.offsetX, res.offsetY);
}
this.canvas.ontouchstart = res => {
// 手指触摸开始
this.isdraw = true;
this.startPosition[0] = res.changedTouches[0].pageX - this.canvasOffsetLeft;
this.startPosition[1] = res.changedTouches[0].pageY - this.canvasOffsetTop;
this.drawLine(this.startPosition[0], this.startPosition[1]);
}
this.canvas.ontouchmove = res => {
//手指触摸移动
if (!this.isdraw) return;
this.drawLine(res.changedTouches[0].pageX - this.canvasOffsetLeft, res.changedTouches[0].pageY - this.canvasOffsetTop);
}
this.canvas.ontouchend = res => {
// 手指触摸结束
if (!this.isdraw) return;
this.clear();
}
}
drawLine(X, Y) {
//画图
if (!this.isdraw) return;
this.ctx.beginPath();//画圆
this.ctx.arc(X, Y, this.penSize, 0, 2 * Math.PI)
this.ctx.closePath();
this.ctx.fillStyle = this.penColor;
this.ctx.fill();
this.ctx.beginPath()//画线
this.ctx.moveTo(this.startPosition[0], this.startPosition[1] + 0.5);
this.ctx.lineTo(X, Y + 0.5);
this.ctx.stroke();
this.ctx.save();
this.startPosition = [X, Y];
if (!this.isInit) this.currentPen.push(this.startPosition)
}
clear() {
// 停止画笔
this.isdraw = false;
this.startPosition = [];
this.history.push({size: this.penSize,color: this.penColor,list: this.currentPen});
this.currentPen = [];
this.drawStep = this.history.length - 1
store.commit('setPenList', this.history)
}
historyDrawPen(penList = []) {
// 画历史画笔
this.history = penList
this.isdraw = true
this.isInit = true
this.resetCanvas()
for(let i = 0;i < penList.length;i++) {
if (this.drawStep < i) break;
if (penList[i].list.length == 0) {
this.resetCanvas()
} else {
this.setColor(penList[i].color)
this.setPenSize(penList[i].size)
this.startPosition = [];//避免画笔的最后一点会和下一个画笔的前一点链接起来
for(let j = 0;j < penList[i].list.length;j++) {
this.drawLine(penList[i].list[j][0], penList[i].list[j][1])
}
}
}
this.isdraw = false
this.isInit = false
this.startPosition = []
}
getHistoryPoint() {
// 返回画笔记录
return this.history
}
setColor(color) {
// 设置画笔的颜色
this.ctx.strokeStyle = color
this.penColor = color
}
setPenSize(size) {
// 设置画笔的粗细
this.penSize = size
this.ctx.lineWidth = size * 2 + 1
}
resetCanvas() {
//清空canvas
this.currentPen = [];
this.ctx.fillStyle = this.backGround;
this.ctx.fillRect(0, 0, this.width, this.height)
if (this.isInit) return
this.history.push({size: this.penSize,color: this.penColor,list: []});
this.drawStep = this.history.length - 1
store.commit('setPenList',this.history)
}
init(penList) {
// 初始化画布
this.drawStep = penList ? penList.length - 1 : 0
this.historyDrawPen(penList)
}
after() {
// 下一笔
if (this.drawStep >= this.history.length - 1) return {code: 404, msg: '没有下一个笔画了'}
this.drawStep = this.drawStep + 1
this.historyDrawPen(this.history)
return {code: 200, msg: '恢复下一笔'}
}
front() {
// 上一笔
if (this.drawStep < 0) return {code: 404, msg: '没有前一个笔画了'}
this.drawStep = this.drawStep - 1
this.historyDrawPen(this.history)
return {code: 200, msg: '恢复前一笔'}
}
}