日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無(wú)先后,達(dá)者為師

網(wǎng)站首頁(yè) 編程語(yǔ)言 正文

canvas實(shí)現(xiàn)畫板功能

作者:ALIZJLI 更新時(shí)間: 2022-04-11 編程語(yǔ)言

canvas實(shí)現(xiàn)畫板功能

  • canvas實(shí)現(xiàn)畫板功能
    • Setp1構(gòu)建網(wǎng)頁(yè)基本樣式
    • Step2構(gòu)造實(shí)現(xiàn)畫板各個(gè)功能的js代碼
    • Step3加載js文件

需求分析
1.具有基本的鉛筆功能
2.即時(shí)直線繪制
3.即時(shí)繪制矩形
4.即時(shí)圓形
5.即時(shí)橡皮擦
7.插入圖片
8.把畫板保存為圖片并下載 //此處還沒(méi)做好,畫板底色是黑色的
9.選擇顏色
10.選擇線條粗細(xì)

Setp1:構(gòu)建網(wǎng)頁(yè)基本樣式

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代碼

    /*只有一句,用來(lái)初始化畫板顏色*/
    #penal {
        width: 800px;
        height: 800px;
        background-color: #ccc;
    }

Step2:構(gòu)造實(shí)現(xiàn)畫板各個(gè)功能的js代碼

1.構(gòu)造Draw()類,并初始化必要的參數(shù)

    var Draw = function(){
        this.type = 'pen';  //選項(xiàng)類型,默認(rèn)為鉛筆
        this.penal = document.getElementById('penal');
        this.pen = this.penal.getContext('2d');
        this.isDraw = false;    //繪畫開(kāi)關(guān)
        this.color = document.getElementById('color');
        this.lineWidth = document.getElementById('lineWidth');
        this.select = document.getElementById('select');    //選擇面板
        this.img = new Image();//用于動(dòng)態(tài)繪制直線,矩形,圓形
    };

2.這里只需要構(gòu)造一個(gè)初始化函數(shù)init()

初始化函數(shù)內(nèi)部需要用到的變量

    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();    //默認(rèn)觸發(fā)選擇文件操作
            document.getElementById('file').onchange = function(e){
                var reader = new FileReader();          //這是H5新增加的讀取文件函數(shù)
                reader.readAsDataURL(e.target.files[0]);
                reader.onload = function(ent){          //文件讀取完畢后觸發(fā)操作
                    var img = new Image();
                    img.src = ent.target.result;        //讀取的結(jié)果默認(rèn)存放在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');     //把畫布轉(zhuǎn)化為base64
            a.download = 'image.jpeg';
            a.id = 'download';
            a.innerHTML = 'download';
            document.body.appendChild(a);
            document.getElementById('download').style.display = 'none';
            document.getElementById('download').click();    //默認(rèn)出發(fā)下載操作

        }
    },false);

可以知道當(dāng)繪畫時(shí),mousedown事件觸發(fā)時(shí),需要把this.isDraw = true,同時(shí)記錄鼠標(biāo)所在坐標(biāo),獲取選擇的colorlinewidth,并開(kāi)啟繪畫路徑

    this.penal.addEventListener('mousedown',function(event){
        self.isDraw = true;
        originX = event.clientX - self.penal.offsetLeft;    //原點(diǎn)x坐標(biāo)
        originY = event.clientY - self.penal.offsetTop;     //原點(diǎn)y坐標(biāo)
        self.pen.moveTo(originX, originY);
        self.pen.strokeStyle = self.color.value;
        self.pen.lineWidth = self.lineWidth.value;
        self.pen.beginPath();

    },false);

然后當(dāng)觸發(fā)mouseup事件時(shí),可知需要結(jié)束繪畫,若鼠標(biāo)離開(kāi)畫布,即mouseleave時(shí),也需要結(jié)束繪畫,這部分很簡(jiǎn)單只需把this.isDraw = false和關(guān)閉繪畫路徑

    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);

接下來(lái)就是最難的部分的,當(dāng)mouseover時(shí),需要即時(shí)繪制
先實(shí)現(xiàn)鉛筆功能

    this.penal.addEventListener('mousemove',function(event){
        //只有可繪畫時(shí)才可畫
        if(self.isDraw){
            var x = event.clientX - self.penal.offsetLeft;  //移動(dòng)過(guò)程中的x坐標(biāo)
            var y = event.clientY - self.penal.offsetTop;   //移動(dòng)過(guò)程中的y坐標(biāo)

            if(self.type == 'pen'){
                self.pen.lineTo(x,y);
                self.pen.stroke();
            }
        }
    },false);

接下來(lái)實(shí)現(xiàn)橡皮擦功能,實(shí)現(xiàn)方法是把繪畫線條加粗,并顏色默認(rèn)選擇畫布底色

    if(self.type == 'robber'){
         self.pen.strokeStyle = '#ccc';
         self.pen.clearRect(x-10,y-10,20,20);
    }

接下來(lái)實(shí)現(xiàn)繪制直線,矩形和圓形的方法其實(shí)大同小異,然后為了能讓我們畫矩形和圓形能在所有方向都能畫,我們?cè)黾恿?code>newOriginX和newOriginY兩個(gè)變量

    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:此時(shí)我們發(fā)現(xiàn)畫的直線,矩形和圓形都會(huì)在畫的時(shí)候留下移動(dòng)的痕跡,這不是我們希望的結(jié)果,所以解決方法是:
mousedown時(shí),把當(dāng)前畫布內(nèi)容保存為圖片,并用初始化時(shí)一直沒(méi)有使用過(guò)的this.img來(lái)保存,然后每次畫直線等的時(shí)候先把畫布全部清空,然后在把this.img畫到畫布上
把原來(lái)的mousedown事件添加一句代碼

    this.penal.addEventListener('mousedown',function(event){
        self.isDraw = true;

        //增加一句代碼
        self.img.src = self.penal.toDataURL('image/png');

        originX = event.clientX - self.penal.offsetLeft;    //原點(diǎn)x坐標(biāo)
        originY = event.clientY - self.penal.offsetTop;     //原點(diǎn)y坐標(biāo)
        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>

最后簡(jiǎn)單的畫板功能就是實(shí)現(xiàn)了,如有不足之處請(qǐng)指出
demo地址:https://github.com/1364137942/canvas-draw-panel

原文鏈接:https://blog.csdn.net/ali1995/article/details/52734253

欄目分類
最近更新