签名画板案例
01. 绘制一个画板
js
// 1、获取canvas画布
var c1 = document.querySelector("#c1");
if (!c1.getContext) {
console.log('当前浏览器不支持canvas,请下载最新的浏览器');
}
// 2. 获取画笔,上下文对象
var ctx = c1.getContext('2d')
// 连接点和末端为圆形
ctx.lineJoin = 'round';
ctx.lineCap = 'round'
// 3.获取输入框和按钮
var boldBtn = document.getElementById('boldBtn')
var thinBtn = document.getElementById('thinBtn')
var saveBtn = document.getElementById('saveBtn')
var color = document.getElementById('color')
var eraserBtn = document.getElementById('eraserBtn')
var clearBtn = document.getElementById('clearBtn')
// 是否在画
var isDraw = false
c1.onmousedown = (e) => {
isDraw = true
ctx.beginPath();
var x = e.offsetX;
var y = e.offsetY;
ctx.moveTo(x, y);
}
function mouseEvent(e) {
if (isDraw) {
var x = e.offsetX;
var y = e.offsetY;
ctx.lineTo(x, y)
ctx.stroke()
}
}
c1.onmousemove = (e) => {
mouseEvent(e)
}
c1.onmouseup = () => {
isDraw = false
ctx.closePath()
}
c1.onmouseleave = () => {
isDraw = false
ctx.closePath()
}
boldBtn.addEventListener('click', () => {
ctx.globalCompositeOperation = 'source-over'
ctx.lineWidth = 20
boldBtn.classList.add('active')
thinBtn.classList.remove('active')
eraserBtn.classList.remove('active')
})
thinBtn.addEventListener('click', () => {
ctx.globalCompositeOperation = 'source-over'
ctx.lineWidth = 1
boldBtn.classList.remove('active')
eraserBtn.classList.remove('active')
thinBtn.classList.add('active')
})
eraserBtn.addEventListener('click', () => {
// 修改模式
ctx.globalCompositeOperation = 'destination-out'
ctx.lineWidth = 30
boldBtn.classList.remove('active')
thinBtn.classList.remove('active')
eraserBtn.classList.add('active')
})
clearBtn.addEventListener('click', () => {
ctx.clearRect(0, 0, c1.width, c1.height)
})
function setWhiteBackground() {
// 获取图片数据
var imgData = ctx.getImageData(
0,
0,
c1.width,
c1.height
);
for (var i = 0; i < imgData.data.length; i += 4) {
// 当该像素是透明的,则设置成白色
if (imgData.data[i + 3] == 0) {
imgData.data[i] = 255;
imgData.data[i + 1] = 255;
imgData.data[i + 2] = 255;
imgData.data[i + 3] = 255;
}
}
ctx.putImageData(imgData, 0, 0);
}
saveBtn.addEventListener('click', () => {
setWhiteBackground()
var dataUrl = c1.toDataURL()
const elem = window.document.createElement('a')
elem.href = dataUrl
elem.download = '签名.png'
elem.click()
})
colorInput.addEventListener('change', () => {
ctx.strokeStyle = colorInput.value
})
<template>
<div>
<!-- id,标识元素的唯一性,width,height 画布的宽高 -->
<canvas id="canvas" width="600" height="400">
当前浏览器不支持canvas,请下载最新的浏览器
<a href="https://www.google.cn/chrome/index.html">立即下载</a>
</canvas>
<hr />
<n-space>
<button id="boldBtn" type="button">粗线条</button>
<button id="thinBtn" type="button">细线条</button>
<button id="saveBtn" type="button">保存签名</button>
<input type="color" name="" id="colorInput" />
<button id="eraserBtn" type="button">橡皮擦</button>
<button id="clearBtn" type="button">清除画布</button>
</n-space>
</div>
</template>
<script setup>
import { onMounted } from "vue";
onMounted(() => {
// 1、获取canvas画布
var c1 = document.querySelector("#canvas");
if (!c1.getContext) {
console.log("当前浏览器不支持canvas,请下载最新的浏览器");
}
// 2. 获取画笔,上下文对象
var ctx = c1.getContext("2d");
// 连接点和末端为圆形
ctx.lineJoin = "round";
ctx.lineCap = "round";
// 3.获取输入框和按钮
var boldBtn = document.getElementById("boldBtn");
var thinBtn = document.getElementById("thinBtn");
var saveBtn = document.getElementById("saveBtn");
var color = document.getElementById("color");
var eraserBtn = document.getElementById("eraserBtn");
var clearBtn = document.getElementById("clearBtn");
// 是否在画
var isDraw = false;
c1.onmousedown = (e) => {
isDraw = true;
ctx.beginPath();
var x = e.offsetX;
var y = e.offsetY;
ctx.moveTo(x, y);
};
function mouseEvent(e) {
if (isDraw) {
var x = e.offsetX;
var y = e.offsetY;
ctx.lineTo(x, y);
ctx.stroke();
}
}
c1.onmousemove = (e) => {
mouseEvent(e);
};
c1.onmouseup = () => {
isDraw = false;
ctx.closePath();
};
c1.onmouseleave = () => {
isDraw = false;
ctx.closePath();
};
boldBtn.addEventListener("click", () => {
ctx.globalCompositeOperation = "source-over";
ctx.lineWidth = 20;
boldBtn.classList.add("active");
thinBtn.classList.remove("active");
eraserBtn.classList.remove("active");
});
thinBtn.addEventListener("click", () => {
ctx.globalCompositeOperation = "source-over";
ctx.lineWidth = 1;
boldBtn.classList.remove("active");
eraserBtn.classList.remove("active");
thinBtn.classList.add("active");
});
eraserBtn.addEventListener("click", () => {
// 修改模式
ctx.globalCompositeOperation = "destination-out";
ctx.lineWidth = 30;
boldBtn.classList.remove("active");
thinBtn.classList.remove("active");
eraserBtn.classList.add("active");
});
clearBtn.addEventListener("click", () => {
ctx.clearRect(0, 0, c1.width, c1.height);
});
function setWhiteBackground() {
// 获取图片数据
var imgData = ctx.getImageData(0, 0, c1.width, c1.height);
for (var i = 0; i < imgData.data.length; i += 4) {
// 当该像素是透明的,则设置成白色
if (imgData.data[i + 3] == 0) {
imgData.data[i] = 255;
imgData.data[i + 1] = 255;
imgData.data[i + 2] = 255;
imgData.data[i + 3] = 255;
}
}
ctx.putImageData(imgData, 0, 0);
}
saveBtn.addEventListener("click", () => {
setWhiteBackground();
var dataUrl = c1.toDataURL();
const elem = window.document.createElement("a");
elem.href = dataUrl;
elem.download = "签名.png";
elem.click();
});
colorInput.addEventListener("change", () => {
ctx.strokeStyle = colorInput.value;
});
});
</script>
<style scoped>
canvas,
input,
button {
border: 1px solid #ccc;
}
button.active {
color: #fff;
background-color: orangered;
border-color: orangered;
}
</style>