Canvas 塗鴉

第一步,咱們先實現簡單的繪製,而且在繪製以後將圖片保存到本地

var canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d'),
    iptColor = document.getElementById('iptColor'),//畫筆顏色
    iptSize = document.getElementById('iptSize'),//畫筆大小
    btnClear = document.getElementById('btnClear'), //清除按鈕
    btnSave = document.getElementById('btnSave'),//保存按鈕
    canvasWidth = 800,
    canvasHeight = 600;
    canvas.setAttribute('width',canvasWidth);
    canvas.setAttribute('height',canvasHeight);    

    iptSize.oninput = function() {
        document.querySelector('.txt-size').innerHTML = iptSize.value
    }

    canvas.addEventListener('mousedown',function(e){
        var e = e || window.event;
        ctx.lineWidth = iptSize.value; 
        ctx.strokeStyle = iptColor.value;
        ctx.lineCap = "round";
        ctx.lineJoin = "round";
        ctx.beginPath();
        ctx.moveTo(e.clientX - canvas.offsetLeft,e.clientY - canvas.offsetTop); //線條起始位置
        document.onmousemove = function(e) {
            var e = e || window.event;        
            ctx.lineTo(e.clientX - canvas.offsetLeft,e.clientY - canvas.offsetTop);
            ctx.stroke();//繪製線條
        };
        canvas.onmouseup = function() {
            document.onmousemove = null;
            document.onmouseup = null;
        };
    })
    //清除畫布
    btnClear.addEventListener('click',function(){
        ctx.clearRect(0, 0, canvasWidth, canvasHeight);
    })
    
    //保存圖片到本地
    btnSave.addEventListener('click',function(){
        var imgData = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
        var filename = '圖片.png';
        saveFile(imgData,filename)
    })
    
    var saveFile = function(data, filename) {  
        var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');  
        save_link.href = data;  
        save_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);  
        save_link.dispatchEvent(event);  
    };

這樣看起來雖說好像沒問題,可是這一句有一些問題:html

e.clientX - canvas.offsetLeft,e.clientY - canvas.offsetTop

若是頁面比較高,產生了滾動條,當滾動條向上滑的時候,繪圖的位置就不許確了,示例如:https://codepen.io/jianxiujiu...canvas

因此此處應該使用工具

e.clientX - canvas.getBoundingClientRect().left,e.clientY - canvas.getBoundingClientRect().top

來替換。this

第二步,消除塗鴉鋸齒的辦法

簡單的繪製和圖片保存完成了,可是在這種狀況下,線條會有很明顯的鋸齒(靈魂畫手來了)。
圖片描述spa

有一個簡單粗暴的方法,將線條的邊緣進行模糊:code

ctx.shadowBlur = 1;
ctx.shadowColor = iptColor.value;

示例:https://codepen.io/jianxiujiu...
加上邊緣模糊以後,線條明顯柔和了許多,可是仍是有一個問題,就是在畫筆收筆的地方,線條會變小(靈魂畫手又來了)。
圖片描述htm

在通過搜索查閱以後,發現有一個繪製辦法能夠下降鋸齒的問題。
原理如圖:
圖片描述
繪製一個圓點,在下一個圓點之間,繪製一個矩形進行填充。這樣繪製出來的線條的銜接會是圓滑的。圖片

var canvas = document.getElementById('canvas'),
        ctx = canvas.getContext('2d'),
        btnClear = document.getElementById('btnClear'),
        btnSave = document.getElementById('btnSave'),
        iptColor = document.getElementById('iptColor'),
        iptSize = document.getElementById('iptSize'),
        canvasWidth = 800,
        canvasHeight = 600;
    canvas.setAttribute('width',canvasWidth);
    canvas.setAttribute('height',canvasHeight);    
    
    iptSize.oninput = function() {
        document.querySelector('.txt-size').innerHTML = iptSize.value
    }
    canvas.addEventListener('mousedown',function(e){
        var e = e || window.event;
        var x1 = e.clientX - canvas.getBoundingClientRect().left,
            y1 = e.clientY - canvas.getBoundingClientRect().top;
        
        lineSize = iptSize.value;
        lineColor = iptColor.value;
        ctx.beginPath();
        ctx.fillStyle = lineColor;
        ctx.lineCap = "round";
        ctx.lineJoin = "round";
        ctx.arc(x1, y1, lineSize, 0, 2 * Math.PI);
        ctx.fill();
        ctx.closePath();
        
        document.onmousemove = function(e) {
            var e = e || window.event;    
            var x2 = e.clientX - canvas.getBoundingClientRect().left,
                y2 = e.clientY - canvas.getBoundingClientRect().top;
            var asin = lineSize * Math.sin(Math.atan((y2 - y1) / (x2 - x1)));
            var acos = lineSize * Math.cos(Math.atan((y2 - y1) / (x2 - x1)));
            //分別獲取矩形的四個點的xy軸位置
            var x3 = x1 + asin;
            var y3 = y1 - acos;
            var x4 = x1 - asin;
            var y4 = y1 + acos;
            var x5 = x2 + asin;
            var y5 = y2 - acos;
            var x6 = x2 - asin;
            var y6 = y2 + acos;
                                
            ctx.beginPath();
            ctx.fillStyle = lineColor;
            ctx.arc(x2, y2, lineSize, 0, 2 * Math.PI);
            ctx.fill();
            ctx.closePath();
            ctx.beginPath();
            ctx.fillStyle = lineColor;
            ctx.moveTo(x3, y3);
            ctx.lineTo(x5, y5);
            ctx.lineTo(x6, y6);
            ctx.lineTo(x4, y4);
            ctx.fill();
            ctx.closePath();
            x1 = x2;
            y1 = y2;
        };
        canvas.onmouseup = function() {
            document.onmousemove = null;
            document.onmouseup = null;
        };
    })

    btnClear.addEventListener('click',function(){
        ctx.clearRect(0, 0, canvasWidth, canvasHeight);
    })

    btnSave.addEventListener('click',function(){
        var imgData = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
        var filename = '圖片.png';
        saveFile(imgData,filename)
        
    })
    
    var saveFile = function(data, filename) {  
        var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');  
        save_link.href = data;  
        save_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);  
        save_link.dispatchEvent(event);  
    };

DEMO:
https://codepen.io/jianxiujiu...ip

第三步,添加橡皮擦工具

用這個方法,咱們還能夠加上橡皮擦。
橡皮擦的原理是,將橡皮繪製的路徑覆蓋到原來的畫筆上。
這裏咱們將用到canvas的一個屬性globalCompositeOperation,詳解參照:
http://www.w3school.com.cn/ta...rem

var canvas = document.getElementById('canvas'),
        ctx = canvas.getContext('2d'),
        btnClear = document.getElementById('btnClear'),
        btnSave = document.getElementById('btnSave'),
        btnRestore = document.getElementById('btnRestore'),
        iptColor = document.getElementById('iptColor'),
        iptSize = document.getElementById('iptSize'),
        eraser = document.getElementById('eraser')
        pen = document.getElementById('pen'),
        canvasWidth = 800,
        canvasHeight = 600,
        isClear = 0;
    canvas.setAttribute('width',canvasWidth);
    canvas.setAttribute('height',canvasHeight);    
    
    iptSize.oninput = function() {
        document.querySelector('.txt-size').innerHTML = iptSize.value
    }
    eraser.addEventListener('click',function(){
        isClear = 1;
        this.classList.add('cho');
        pen.classList.remove('cho')
    })
    pen.addEventListener('click',function(){ 
        isClear = 0;
        this.classList.add('cho');
        eraser.classList.remove('cho')
    })
    canvas.addEventListener('mousedown',function(e){
        var e = e || window.event;
        var x1 = e.clientX - canvas.getBoundingClientRect().left,
            y1 = e.clientY - canvas.getBoundingClientRect().top;
            lineSize = iptSize.value;
        if(isClear == 0){      
            lineColor = iptColor.value;
            ctx.beginPath();
            ctx.fillStyle = lineColor;
            ctx.arc(x1, y1, lineSize, 0, 2 * Math.PI);
            ctx.fill();
            ctx.closePath();
            document.onmousemove = function(e) {
                draw();
            };
            btnClear.classList.remove('dis');
            btnSave.classList.remove('dis');
        }else{
            ctx.strokeStyle = "rgba(250,250,250,0)";
            document.onmousemove = function() {
                ctx.globalCompositeOperation = "destination-out";    
                draw();
                ctx.globalCompositeOperation = "source-over"
            }
        }

        canvas.onmouseup = function() {
            document.onmousemove = null;
            document.onmouseup = null;
        };

        draw = function(e){
            var e = e || window.event,
                x2 = e.clientX  - canvas.getBoundingClientRect().left,
                y2 = e.clientY  - canvas.getBoundingClientRect().top,
                asin = lineSize * Math.sin(Math.atan((y2 - y1) / (x2 - x1))),
                acos = lineSize * Math.cos(Math.atan((y2 - y1) / (x2 - x1))),
                x3 = x1 + asin,
                y3 = y1 - acos,
                x4 = x1 - asin,
                y4 = y1 + acos,
                x5 = x2 + asin,
                y5 = y2 - acos,
                x6 = x2 - asin,
                y6 = y2 + acos;                          
            ctx.beginPath();
            ctx.arc(x2, y2, lineSize, 0, 2 * Math.PI);
            ctx.fill();
            ctx.closePath();
            ctx.beginPath();
            ctx.fillStyle = lineColor;
            ctx.moveTo(x3, y3);
            ctx.lineTo(x5, y5);
            ctx.lineTo(x6, y6);
            ctx.lineTo(x4, y4);
            ctx.fill();
            ctx.closePath();
            x1 = x2;
            y1 = y2;
        }
    })

    // 清除
    btnClear.addEventListener('click',function(){
        ctx.clearRect(0, 0, canvasWidth, canvasHeight);
        this.classList.add('dis');
        btnSave.classList.add('dis');
    })

    //保存圖片
    btnSave.addEventListener('click',function(){
        var imgData = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
        var filename = '圖片.png';
        saveFile(imgData,filename);
        this.classList.add('dis');
        
    })
    
    var saveFile = function(data, filename) {  
        var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');  
        save_link.href = data;  
        save_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);  
        save_link.dispatchEvent(event);  
    };

地址:https://codepen.io/jianxiujiu...

相關文章
相關標籤/搜索