通过canvas实现一个简易的电子画板

通过canvas实现一个简易的电子画板

月光魔力鸭

2018-09-26 15:38 阅读 1750 喜欢 0 canvas画图 canvas画板

通过canvas可以进行画图实现一些动画效果等,今天练习下通过canvas来实现一个简易的电子画板,可以在白板上进行画画,然后指定不同的颜色、线条粗细,加载不同的背景以及擦除效果。

功能划分

canvas功能点

根据以上操作,实际上用到的函数比较少,主要是:

基本上就用到了这么几个,因为功能比较简单,所以用到的函数比较少。

大体思路

思路的话,其实就是初始化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,用到生产是绝对不行滴。

undefined

转载请注明出处: https://chrunlee.cn/article/canvas-board-demo.html


感谢支持!

赞赏支持
提交评论
评论信息 (请文明评论)
暂无评论,快来快来写想法...
推荐
之前的时候都是在各大主机厂商手动进行申请免费的,直到阿里的免费期限变更为3个月.. 我就开始觉的有些麻烦了,还不如使用这个let's encrypt进行部署呢。
之前一直没面试过前端,今天有一个,先整理下需要问的问题和答案。这里都是一些简单的问题,关于当下比较流行的框架并没有涉及到..
关于web打印,需要对页面内容进行页面样式设置,呈现出分页的样子,同时对于题目中的图片或表格尽量不分到两个页面中,因此实现了一个jquery的web打印插件,当然,这个插件目前只适用于部分情况,仅供借鉴
web开发中,前台有时候会需要一个随机数或序列,通常来说,这个随机数可能只在当前页面中使用,并不需要太过严格,大体上重复率低即可。
当一些业务必须通过横屏来实现,但是又没有原生来做,只能通过h5的时候怎么办?
前端时间搞了个小转码,放在后台,但是特别占带宽,想着能不能从前台把这个事搞定呢?读取图片的二进制,然后将字节流处理后重新生成图片展示处理啊。
突然来了一个调研任务,想要实现一个类似3D虚拟展厅类似的需求,主要就是放一些学生的作品,然后预览啥的,效果还是要全景的效果。 经过一番调查,最终锁定了以前从未接触过的krpano。
在我们通过canvs画图的时候经常会用到圆,且需要计算出圆上某点的坐标,由于我数学没学好,总是记不得怎么获取,这里记录下,加深记忆