canvas实现画板功能
 
  
  - 
canvas实现画板功能
    
- Setp1构建网页基本样式
- Step2构造实现画板各个功能的js代码
- Step3加载js文件
 
  
  
 
 
 需求分析 
 1.具有基本的铅笔功能 
 2.即时直线绘制 
 3.即时绘制矩形 
 4.即时圆形 
 5.即时橡皮擦 
 7.插入图片 
 8.把画板保存为图片并下载 //此处还没做好,画板底色是黑色的 
 9.选择颜色 
 10.选择线条粗细
 
 
Setp1:构建网页基本样式
 
 
 html代码
 
 
    
    <div id="select">
        <button id="pen">铅笔button>
        <button id="line">直线button>
        <button id="rect">矩形button>
        <button id="arc">圆形button>
        <button id="robber">橡皮檫button>
        <button id="img">图片button>
        <button id="save">保存button>
        <input type="file" id="file" name="img" style="display: none"/>
        <input type="color" id="color"/>
        <input type="number" id="lineWidth"/>
    div>
    
    <canvas id="penal" width="800" height="800">canvas>
 
 
 css代码
 
 
    
    #penal {
        width: 800px;
        height: 800px;
        background-color: #ccc;
    }
 
Step2:构造实现画板各个功能的js代码
 
 
 1.构造Draw()类,并初始化必要的参数
 
 
    var Draw = function(){
        this.type = 'pen';  
        this.penal = document.getElementById('penal');
        this.pen = this.penal.getContext('2d');
        this.isDraw = false;    
        this.color = document.getElementById('color');
        this.lineWidth = document.getElementById('lineWidth');
        this.select = document.getElementById('select');    
        this.img = new Image();
    };
 
 
 2.这里只需要构造一个初始化函数init()
 
 初始化函数内部需要用到的变量
 
 
    Draw.prototype.init = function(){
        var self = this;
        var originX = null;
        var originY = null;
    }
 
 
 先绑定选择操作
 
 
    this.select.addEventListener('click',function(event){
        if(event.target.id == 'pen'){
            self.type = 'pen';
        }else if(event.target.id == 'line'){
            self.type = 'line';
        }else if(event.target.id == 'rect'){
            self.type = 'rect';
        }else if(event.target.id == 'arc'){
            self.type = 'arc';
        }else if(event.target.id == 'robber'){
            self.type = 'robber';
        }else if(event.target.id == 'img'){
            document.getElementById('file').click();    
            document.getElementById('file').onchange = function(e){
                var reader = new FileReader();          
                reader.readAsDataURL(e.target.files[0]);
                reader.onload = function(ent){          
                    var img = new Image();
                    img.src = ent.target.result;        
                    self.pen.drawImage(img,0,0);        
                }
            }
        }
        else if(event.target.id == 'save'){
            var a = document.createElement('a');
            a.href = self.penal.toDataURL('image/png');     
            a.download = 'image.jpeg';
            a.id = 'download';
            a.innerHTML = 'download';
            document.body.appendChild(a);
            document.getElementById('download').style.display = 'none';
            document.getElementById('download').click();    
        }
    },false);
 
 
 可以知道当绘画时,mousedown事件触发时,需要把this.isDraw = true,同时记录鼠标所在坐标,获取选择的color和linewidth,并开启绘画路径
 
 
    this.penal.addEventListener('mousedown',function(event){
        self.isDraw = true;
        originX = event.clientX - self.penal.offsetLeft;    
        originY = event.clientY - self.penal.offsetTop;     
        self.pen.moveTo(originX, originY);
        self.pen.strokeStyle = self.color.value;
        self.pen.lineWidth = self.lineWidth.value;
        self.pen.beginPath();
    },false);
 
 
 然后当触发mouseup事件时,可知需要结束绘画,若鼠标离开画布,即mouseleave时,也需要结束绘画,这部分很简单只需把this.isDraw = false和关闭绘画路径
 
 
    this.penal.addEventListener('mouseleave', function () {
        if(self.isDraw){
            self.pen.closePath();
            self.isDraw = false;
        }
    },false);
    this.penal.addEventListener('mouseup', function (event) {
        if(self.isDraw){
            self.pen.closePath();
            self.isDraw = false;
        }
    },false);
 
 
 接下来就是最难的部分的,当mouseover时,需要即时绘制 
 先实现铅笔功能
 
 
    this.penal.addEventListener('mousemove',function(event){
        
        if(self.isDraw){
            var x = event.clientX - self.penal.offsetLeft;  
            var y = event.clientY - self.penal.offsetTop;   
            if(self.type == 'pen'){
                self.pen.lineTo(x,y);
                self.pen.stroke();
            }
        }
    },false);
 
 
 接下来实现橡皮擦功能,实现方法是把绘画线条加粗,并颜色默认选择画布底色
 
 
    if(self.type == 'robber'){
         self.pen.strokeStyle = '#ccc';
         self.pen.clearRect(x-10,y-10,20,20);
    }
 
 
 接下来实现绘制直线,矩形和圆形的方法其实大同小异,然后为了能让我们画矩形和圆形能在所有方向都能画,我们增加了newOriginX和newOriginY两个变量
 
 
    var newOriginX  = originX,newOriginY = originY;
    if(self.type == 'line'){
        self.pen.moveTo(originX,originY);
        self.pen.lineTo(x,y);
        self.pen.stroke();
    }else if(self.type == 'rect'){
        if(x < originX){
            newOriginX = x;
        }
        if(y < originY){
            newOriginY = y;
        }
        self.pen.rect(newOriginX,newOriginY,Math.abs(x-originX),Math.abs(y-originY));
        self.pen.stroke();
    }else if(self.type == 'arc'){
        if(x < originX){
            newOriginX = x;
        }
        if(y < originY){
            newOriginY = y;
        }
        var r = Math.sqrt(Math.abs(x-originX) * Math.abs(x-originX) + Math.abs(y-originY) * Math.abs(y-originY))
        self.pen.arc(Math.abs(x-originX)+newOriginX, Math.abs(y-originY)+newOriginY , r, 0, 2*Math.PI);
        self.pen.fillStyle = self.color.value;
        self.pen.fill();
    }
 
 
 question:此时我们发现画的直线,矩形和圆形都会在画的时候留下移动的痕迹,这不是我们希望的结果,所以解决方法是: 
 在mousedown时,把当前画布内容保存为图片,并用初始化时一直没有使用过的this.img来保存,然后每次画直线等的时候先把画布全部清空,然后在把this.img画到画布上 
 把原来的mousedown事件添加一句代码
 
 
    this.penal.addEventListener('mousedown',function(event){
        self.isDraw = true;
        
        self.img.src = self.penal.toDataURL('image/png');
        originX = event.clientX - self.penal.offsetLeft;    
        originY = event.clientY - self.penal.offsetTop;     
        self.pen.moveTo(originX, originY);
        self.pen.strokeStyle = self.color.value;
        self.pen.lineWidth = self.lineWidth.value;
        self.pen.beginPath();
    },false);
 
 
 把mouseover事件的代码稍作更改
 
 
    if(self.type == 'line'){
        self.pen.clearRect(0,0,800,800);
        self.pen.drawImage(self.img, 0, 0);
        self.pen.beginPath();
        self.pen.moveTo(originX,originY);
        self.pen.lineTo(x,y);
        self.pen.stroke();
        self.pen.closePath();
    }else if(self.type == 'rect'){
        self.pen.clearRect(0,0,800,800);
        self.pen.drawImage(self.img, 0, 0);
        self.pen.beginPath();
        if(x < originX){
            newOriginX = x;
        }
        if(y < originY){
            newOriginY = y;
        }
        self.pen.rect(newOriginX,newOriginY,Math.abs(x-originX),Math.abs(y-originY));
        self.pen.stroke();
        self.pen.closePath();
    }else if(self.type == 'arc'){
        self.pen.clearRect(0,0,800,800);
        self.pen.drawImage(self.img, 0, 0);
        self.pen.beginPath();
        if(x < originX){
            newOriginX = x;
        }
        if(y < originY){
            newOriginY = y;
        }
        var r = Math.sqrt(Math.abs(x-originX) * Math.abs(x-originX) + Math.abs(y-originY) * Math.abs(y-originY))
        self.pen.arc(Math.abs(x-originX)+newOriginX, Math.abs(y-originY)+newOriginY , r, 0, 2*Math.PI);
        self.pen.fillStyle = self.color.value;
        self.pen.fill();
        self.pen.closePath();
    }
 
Step3:加载js文件
 
    <script src="draw.js">script>
    <script>
        window.onload = function (){
            var draw = new Draw();
            draw.init();
        };
    script>
 
最后简单的画板功能就是实现了,如有不足之处请指出 
 demo地址:https://github.com/1364137942/canvas-draw-panel