使用canvas实现一个简易画板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<div>
<button onclick="cancel()">取消</button>
<button onclick="save()">保存</button>
<button onclick="prev()">上一步</button>
<button onclick="next()">下一步</button>
<button onclick="strong()">加粗</button>
<button onclick="restoreWidth()">取消加粗</button>
<input id="color" type="color" onchange="changeColor()" value="#ff0000">
<button id="eraser" onclick="handleEraser()">橡皮檫</button>
</div>
</body>
<script>
let config = {
width: 500, // 画布宽度
height: 500, // 画笔高度
lineHeight: 1, // 画笔宽度
strongLineHeight: 5, // 画笔加粗
lineStyle: 'red', // 画笔默认样式(颜色)
eraserLineWidth: 20, // 橡皮檫宽度
eraserLineStyle: 'white', // 橡皮檫样式
eraserUrl: "https://www.suxieban.com/css/font/myfont/cursor-eraser-black.svg", // 橡皮檫图标url
pencilUrl:"https://www.suxieban.com/css/font/myfont/cursor-pen-black.svg" // 笔图标url
}
// 获取相应元素
let canvas = document.getElementById('canvas')
let colorEl = document.getElementById('color')
let eraseBtn = document.getElementById('eraser')
// 设置canvas大小
canvas.width = config.width
canvas.height = config.height
// 设置canvas样式
canvas.style.border = '1px solid red'
canvas.style.cursor = `url(${config.pencilUrl}),auto`
// 存储画的历史记录
let stack = []
// 当前画的指针
let step = -1
// 获取canvas 上下文
let ctx = canvas.getContext('2d')
// 设置画的线条宽度和样式
ctx.lineWidth = config.lineHeight
ctx.strokeStyle = config.lineStyle
// 初始化canvas
function init (event) {
// 获取画笔的相关位置数据
const { offsetX, offsetY, pageX, pageY } = event
// 开始画
ctx.beginPath()
// 把画笔移动到画画的位置
ctx.moveTo(offsetX, offsetY)
// 监听画笔的移动事件 进行画画
canvas.addEventListener('mousemove', draw)
}
function draw (event) {
// 获取画笔的相关位置数据
const { offsetX, offsetY, pageX, pageY } = event
// 连线
ctx.lineTo(offsetX, offsetY)
// 描线
ctx.stroke()
}
function clearDraw (event) {
// 结束画画
ctx.closePath()
// 把canvas转化为base64数据
const base64 = canvas.toDataURL()
// 把当前数据放到stack数组中
stack.push(base64)
// 移动当前画画指针
step++
// 移除画笔移动事件 结束
canvas.removeEventListener('mousemove', draw)
}
// 取消
function cancel () {
// 清空画布
ctx.clearRect(0, 0, config.width, config.height)
}
// 上一步
function prev () {
// 如果step 大于等于0 表示有历史记录 有上一步
if (step >= 0) {
// 首先让step减一
step--
// 清空画布
ctx.clearRect(0, 0, config.width, config.height);
// 如果历史记录没有数据了 则返回
if(!stack[step]) return
// 创建image对象
let img = new Image()
// 让img对象的src属性指向上次操作的数据
img.src = stack[step]
// 等待图片加载完成
img.onload = function () {
// 加载完成后重新绘制canvas 这样就恢复了上次的操作
ctx.drawImage(img, 0, 0, config.width, config.height)
}
}else{
// 如果step 小于0 则表示没有上步操作了
console.log('没有更多数据了')
}
}
// 下一步
function next () {
// 如果step < step.length -1 表示还有历史记录 有下一步
if (step < stack.length - 1) {
// 让step累加
step++
// 清除画布
ctx.clearRect(0, 0, config.width, config.height);
// 创建img对象
let img = new Image()
// 让img对象的src属性指向下次操作的数据
img.src = stack[step]
// 等待图片加载完成
img.onload = function () {
// 加载完成后重新绘制canvas 这样就恢复了下次的操作
ctx.drawImage(img, 0, 0, config.width, config.height)
}
}else{
console.log('没有更多数据了')
}
}
// 保存为图片
function save () {
// 以上两种方法均可
// canvas.toBlob(function (data) {
// let obj = URL.createObjectURL(data)
// let a = document.createElement('a')
// a.href = obj
// a.download = Date.now()
// a.click()
// URL.revokeObjectURL(obj)
// })
const base64 = canvas.toDataURL()
let a = document.createElement('a')
a.href = base64
a.download = Date.now()
a.click()
a.remove()
}
// 加粗
function strong(){
ctx.lineWidth = config.strongLineHeight
}
// 恢复正常大小
function restoreWidth(){
ctx.lineWidth = config.lineHeight
}
// 修改颜色值
function changeColor(e){
ctx.strokeStyle = colorEl.value
}
//橡皮檫
function handleEraser(){
if(!ctx.isEraser){
ctx.strokeStyle = config.eraserLineStyle
ctx.lineWidth = config.eraserLineWidth
canvas.style.cursor = `url(${config.eraserUrl}),auto`
eraseBtn.innerHTML = '取消橡皮檫'
}else{
ctx.strokeStyle = config.lineStyle
ctx.lineWidth = config.lineHeight
canvas.style.cursor = `url(${config.pencilUrl}),auto`
eraseBtn.innerHTML = '橡皮檫'
}
ctx.isEraser = !ctx.isEraser
}
// 监听鼠标按下事件 初始化画布
canvas.addEventListener('mousedown', init)
// 监听鼠标抬起事件 清除画布
canvas.addEventListener('mouseup', clearDraw)
</script>
</html>
最终效果