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

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

月光魔力鸭

2018-09-26 15:38 阅读 1386 喜欢 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,用到生产是绝对不行滴。

Demo效果参考这里

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


感谢支持!

赞赏支持
提交评论
评论信息 (请文明评论)
暂无评论,快来快来写想法...
推荐
关于web打印,需要对页面内容进行页面样式设置,呈现出分页的样子,同时对于题目中的图片或表格尽量不分到两个页面中,因此实现了一个jquery的web打印插件,当然,这个插件目前只适用于部分情况,仅供借鉴
整理下关于axios的使用,一些常用的调用、处理以及其他。
今天刷codewars的题目的时候碰到一个通过js来实现字符串转base64的题目,base64虽然在js或nodejs中经常用,但是我还真没有仔细去看过原理以及如何实现,这回绕不过去了,赶紧找了找资料看了下。
在开发过程中经常会碰到跨frame 去操作的需求,那么如何获得这个frame呢,这里写了一个工具类,用来通过name获得frame的jq对象
开发的项目中有使用到微信开发,由于之前偶尔才用一次,也是用的别人的地址和测试号,这里记录下自己的操作。防止后续遗忘。
先记录下,不定哪天就查了..防止找不到或不全
jsQR 是一款纯粹的由javascript实现的二维码识别库,可以在浏览器端使用,也可以在后端node.js环境使用。我之前使用过其他的识别库,例如:qrcode-reader 或其他,在使用上都比较麻烦,而且识别率并不高。jsQR是后来发现的,感觉(没有实际对比验证)jsQR识别率要更高些,使用起来也更简单,不需要安装其他依赖软件。
最近一直在想着抓一些网盘数据,进行资料归拢,可是当我真正开始的时候.. 还是遇到了反爬,当然我本身就有心理预期,这是肯定会碰到的,只是没想到会在代理IP上耗费这么久,之前的时候也处理过代理IP ,可是由于一知半解,导致很多配置都不理解,debug全靠猜...