通过canvas可以进行画图实现一些动画效果等,今天练习下通过canvas来实现一个简易的电子画板,可以在白板上进行画画,然后指定不同的颜色、线条粗细,加载不同的背景以及擦除效果。
功能划分
- 线条涂抹
- 可以擦除指定区域画布
- 清除画布
- 可以保存到图片下载
- 可以指定不同的颜色的线条
- 可以指定线条的宽度
canvas功能点
根据以上操作,实际上用到的函数比较少,主要是:
clearRect
清除某位置区域的画布drawImage
加载图片到画布中lineTo
划线
基本上就用到了这么几个,因为功能比较简单,所以用到的函数比较少。
大体思路
思路的话,其实就是初始化canvas
元素,由于需要加载背景图层,所以设置两个canvas
元素,底层用来加载背景,上层用来绘画。
用到的事件的话就是onmousedown
onmousemove
onmouseup
三个事件,初始化的时候监听下这几个事件即可。
然后根据event
中的坐标,来绘制线条以及清除画布。
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>画板</title>
<style>
html,body{
margin:0px;
padding: 0px;
height:100%;
width: 100%;
overflow: hidden;
}
canvas{
height:100%;
width:100%;
position:absolute;
left:0px;
top:0px;
z-index:100;
background-color: transparent;
}
#bg{
background-color: #49e;
z-index:10;
}
.tool>span{
display:inline-block;
position:absolute;
width:100px;
height:30px;
border:1px solid #f2f2f2;
text-align:center;
line-height:30px;
color:#f2f2f2;
cursor:pointer;
}
.draw{left:10px;top:10px;}
.clear{left:150px;top:10px;}
.empty{left:300px;top:10px;}
.tianzige{left:450px;top:10px;}
.hengxian{left:600px;top:10px;}
.screen{left:750px;top:10px;}
.tool{
position:absolute;
left:0px;
top:0px;
z-index:99999;
}
.color{
position:absolute;
right:0px;
top:0px;
width:110px;
z-index:9999;
height:100px;
}
.color>span{
display:inline-block;
height:20px;
margin:2px;
width:50px;
line-height:20px;
text-align:center;
float:left;
cursor:pointer;
font-size:12px;
}
.c1{background-color:red;color:white;}
.c2{background-color:yellow;color:#333;}
.c3{background-color:#333;color:white;}
.c4{background-color:green;color:white;}
.c5{background-color:white;color:#333;}
.c6{background-color:purple;color:#f2f2f2;}
.linewidth{
position:absolute;
top:80px;
right:0px;
width:110px;
height:100px;
z-index:09999;
}
.linewidth>span{
width:100%;
display:inline-block;
margin-bottom:5px;
cursor:pointer;
background-color:white;
}
.line1{height:5px;}
.line2{height:10px;}
.line3{height:20px;}
</style>
</head>
<body>
<div class="tool">
<span class="draw" onclick="draw()">画笔</span>
<span class="clear" onclick="xiangpi()">橡皮</span>
<span class="empty" onclick="empty()">清除</span>
<span class="tianzige" onclick="tianzige()">田字格</span>
<span class="hengxian" onclick="hengxian()">横线</span>
<span class="screen" onclick="screena()">截屏</span>
</div>
<div class="color">
<span class="c1" onclick="changeColor('red')">红</span>
<span class="c2" onclick="changeColor('yellow')">黄</span>
<span class="c3" onclick="changeColor('#333')">黑</span>
<span class="c4" onclick="changeColor('green')">绿</span>
<span class="c5" onclick="changeColor('white')">白</span>
<span class="c6" onclick="changeColor('purple')">紫</span>
</div>
<div class="linewidth">
<span class="line1" onclick="changeWidth(5)"></span>
<span class="line2" onclick="changeWidth(10)"></span>
<span class="line3" onclick="changeWidth(20)"></span>
</div>
</body>
</html>
以上是html以及css样式,主要是针对一些按钮、设置、样式进行处理。大体效果如下:
然后针对canvas进行初始化以及事件绑定处理:
//初始化几个参数,后续可以通过用户点击按钮进行改变。
var status = 'draw';//'draw' 'clear'
var dotWidth = 50;
var color = 'white';
var lineWidth = 5;
var canvas = {
//canvas初始化
init () {
this.ele = document.createElement('canvas');
document.body.appendChild(this.ele);
this.ctx = this.ele.getContext('2d');
//背景图层
this.floor = document.createElement('canvas');
this.floor.id = 'bg';
document.body.appendChild(this.floor);
this.floorCtx = this.floor.getContext('2d');
//设定canvas的宽高
this.width = this.ele.width = this.floor.width = window.innerWidth;
this.height = this.ele.height = this.floor.height = window.innerHeight;
return this;
},
get (){
return this;
},
//加载背景图层
drawImage (imgPath){
var that = this;
// that.floorCxt.clearRect(0,0,that.width,that.height);
var img = new Image();
img.src = imgPath;
img.onload = function(){
that.floorCtx.clearRect(0,0,that.width,that.height);
that.floorCtx.drawImage(img,that.width/2 - 500,that.height/2 - 100);
}
},
//事件绑定:鼠标按钮、鼠标移动、鼠标弹起
bind(){
let ctx = this.ctx;
let startDraw = false;//标识是否开始绘制
this.ele.onmousedown = function(ev){
startDraw = true;
var x = ev.clientX,y = ev.clientY;
ctx.beginPath();
}
this.ele.onmousemove = function(ev){
if(startDraw){
console.log(status);
var x = ev.clientX,y = ev.clientY;
if(status == 'draw'){
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
ctx.lineTo(x,y);
ctx.stroke();
}else if(status == 'clear'){
//清除
ctx.strokeStyle = 'rgba(0,0,0,1)';
ctx.clearRect(x - 40,y - 40,80,80);
}
}
}
this.ele.onmouseup = function(){
ctx.closePath();
startDraw = false;
}
}
}
canvas.init().bind();
核心的绘画、移动已经可以了,剩下都是一些边边角角,增加一些点击事件即可,包括该表颜色、线条宽度以及操作状态等。
//改变全局状态的颜色
function changeColor(c){
color = c;
}
//切换绘画/清除状态
function draw(){
console.log('abc');
status = 'draw';
}
//切换绘画/清除状态
function xiangpi(){
console.log('aaa');
status = 'clear';
}
//改变线条宽度
function changeWidth(w){
lineWidth = w;
}
//加载背景图片
function tianzige(){
canvas.get().drawImage('bg.png');
}
function hengxian(){
canvas.get().drawImage('line.png');
}
//清空画布
function empty(){
var ins = canvas.get();
ins.ctx.clearRect(0,0,ins.width,ins.height);
}
//保存图片
function screena(){
//设置保存图片的类型
var type = 'jpg';
var imgdata = canvas.get().ele.toDataURL(type);
//将mime-type改为image/octet-stream,强制让浏览器下载
var fixtype = function (type) {
type = type.toLocaleLowerCase().replace(/jpg/i, 'jpeg');
var r = type.match(/png|jpeg|bmp|gif/)[0];
return 'image/' + r;
}
imgdata = imgdata.replace(fixtype(type), 'image/octet-stream')
//将图片保存到本地
var saveFile = function (data, filename) {
var link = document.createElement('a');
link.href = data;
link.download = filename;
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
}
var filename = new Date().toLocaleDateString() + '.' + type;
saveFile(imgdata, filename);
}
以上就已经通过canvas实现了一个简易的电子画板小工具,当然,目前仅仅是个Demo,用到生产是绝对不行滴。