1. 程式人生 > >【js案例】使用js製作寫字畫布

【js案例】使用js製作寫字畫布

canvas實現畫板功能

需求分析 
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();          //這是H5新增加的讀取檔案函式
                reader.readAsDataURL(e.target.files[0]);
                reader.onload = function(ent){          //檔案讀取完畢後觸發操作
                    var img = new Image();
                    img.src = ent.target.result;        //讀取的結果預設存放在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');     //把畫布轉化為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();    //默認出發下載操作

        }
    },false);

可以知道當繪畫時,mousedown事件觸發時,需要把this.isDraw = true,同時記錄滑鼠所在座標,獲取選擇的colorlinewidth,並開啟繪畫路徑

    this.penal.addEventListener('mousedown',function(event){
        self.isDraw = true;
        originX = event.clientX - self.penal.offsetLeft;    //原點x座標
        originY = event.clientY - self.penal.offsetTop;     //原點y座標
        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;  //移動過程中的x座標
            var y = event.clientY - self.penal.offsetTop;   //移動過程中的y座標

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

接下來實現繪製直線,矩形和圓形的方法其實大同小異,然後為了能讓我們畫矩形和圓形能在所有方向都能畫,我們增加了newOriginXnewOriginY兩個變數

    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;    //原點x座標
        originY = event.clientY - self.penal.offsetTop;     //原點y座標
        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>

轉自: https://blog.csdn.net/ali1995/article/details/52734253

相關推薦

js案例使用js製作寫字畫布

canvas實現畫板功能需求分析 1.具有基本的鉛筆功能 2.即時直線繪製 3.即時繪製矩形 4.即時圓形 5.即時橡皮擦 7.插入圖片 8.把畫板儲存為圖片並下載 //此處還沒做好,畫板底色是黑色的 9.選擇顏色 10.選擇線條粗細Setp1:構建網頁基本樣式html程式碼

幹貨JS相關知識點總結

名稱 javascrip 過程 進行 匿名函數 wid logs def image 一、獲取元素方法 可以使用內置對象document上的getElementById方法來獲取頁面上設置了id屬性的元素,獲取到的是一個html對象,然後將它賦值給一個變量。如下: 上面的

學習隨筆JS初涉

method this date 語法 新的 傳遞值 prop 現在 語言 JS = JavaScript 他是一種輕量級別的編程語言 可插入HTML的頁面代碼 插入HTML頁面後,可由所有的現在瀏覽器執行 輸出語句: document.writie(); 聲明變量

js 實踐js 實現木桶布局

cto enter 最後一行 scrip fine inner get code 兩個 還有兩個月左右就要準備實習了,所以特意練一練,今天終於搞定了js 的木桶布局了 這一個是按照一個插件的規格去寫的以防以後工作需要,詳細的解釋在前端網這裏 http://www.qdfun

牛腩-JS錯誤

前言        在做牛腩新聞釋出系統時,JS(PS:JS不等於 雞屎)這塊出現錯誤了,對JS一無所知的我,也是很難受。要想解決問題就要先弄清楚它是幹嘛的。 JavaScript 官話: JavaScript一種直

總結篇js編寫的2048小遊戲開發(上:思路)

2048是大家都熟悉的一款魔性小遊戲,其操作簡單,卻極其有效地殺時間。本篇將詳細講解如何構建這款小遊戲的開發思路、如何根據玩法進一步分析設計程式設計結構,適合有一定html、css、js、jquery語言基礎的讀者閱讀。 一.遊戲試玩       遊戲玩法大家都很

知識筆記js中undefined和null的區別和聯絡

在JavaScript中存在這樣兩種原始型別:Null與Undefined。這兩種型別常常會使JavaScript的開發人員產生疑惑,在什麼時候是Null,什麼時候又是Undefined?Undefined型別只有一個值,即undefined。當宣告的變數還未被初始化時,變數的預設值為undefined。Nu

37.專案案例消防工程師培訓網站製作1--專案準備

1. 專案介紹 專案包括首頁,列表頁,內容頁以及後臺管理四個部分。 2. 專案準備 2.1 資料庫 2.2 jar包 2.3 html頁面 3.專案建立 3.1 建立web專案 建立web專案 EduPro 3.2 匯入jar包 3.3 配置C3P0資料連線池

持續更新JS codewars題目

1.在這個kata中,您將建立一個函式,該函式獲取非負整數和字串的列表,並返回一個新的列表,其中過濾掉了字串 mycode function filter_list(l) { var arr2 =[];//arr2=new Ar

js例項js傳送驗證碼後倒計時60秒

首先寫一個按鈕: <input type="button" id="btn" value="免費獲取驗證碼" onclick="settime(this)" /> 然後寫js程式碼: //定義一個60秒計時器變數 var countdo

線上程式碼js中使用freemarker標籤操作list及list巢狀

背景說明:頁面中使用freemarker作為模板,現需要將後端返回的資料通過js的方式儲存資料。記錄之! 後臺返回資料 注:圖中為後臺返回有用資料,主要是紅框中的資料在前端要用到。 前端js操作

前端面試 JS非同步程式設計

callback回撥方法 function fn1 () { console.log('Function 1') } function fn2 () { setTimeout(() => { console.log('Functio

重溫基礎JS中的常用高階函式介紹

Ps. 晚上加班到快十點,回來趕緊整理整理這篇文章,今天老大給我推薦了一篇文章,我從寫技術部落格中收穫到了什麼?- J_Knight_,感受也是很多,自己也需要慢慢養成記錄部落格的習慣,即使起步艱難,難以堅持,但還是要讓自己加油加油。 前兩天把我整理的【複習資料】ES6/ES7/ES8/ES

h5-egretjs載入成第三方庫

 js: JS下面寫的方法: function jsFunc(){window.alert("hello world"); }ts: TS下面對應的是: declare function jsFu

web前端js json轉陣列,陣列轉json,字串轉數字

,學習記錄 //陣列轉json串 var arr = [1,2,3, { a : 1 } ]; JSON.stringify( arr ); //json字串轉陣列 var jsonStr =

js基礎js基礎鞏固——DOM操作(四)

NODE型別 js中所有的節點型別都繼承自Node型別,因此所有節點都享受這相同的基本屬性和方法。 nodeType屬性,用於表明節點型別。最常用的是NODE.ELEMENT_NODE(1), NODE.TEXT_NODE(3). nodeName和nod

WEB基礎js控制表單提交

1.document.forms.from.submit(); document.form.sumbit(); document.form.submit.click(); this.form.submit(); 以上幾種形式的js表單提交在firefox瀏覽器下是不起作用

網頁前端JS呈現時間戳為與當前時間比較結果

轉載連結:http://www.cnblogs.com/inns/p/5586358.html 1、時間戳顯示 經常可以看到論壇或者新聞上,時間戳為剛剛,xx分鐘前,xx小時前等字樣,前端如何實現呢? 2、時間戳實現 這個功能比較簡單,直接上函式,time_str是時間戳的字串結果,轉換成Date物件,

js例項js實現點選標題標籤切換顯示對應內容

var box = document.getElementById("tab"); //獲取滑動標籤最外層元素 var olis = box.getElementsByTagName("li"); //獲取標籤元素 var odivs = box.getElementsByTagNa

s:checkboxlistJS中取s:checkboxlist選中的value傳入後臺例項

body中: <td width="35%">      <s:checkboxlist name="cc" id="kscc1" list="#{'AM':'上午','PM':'下午' }" value="" cssStyle="width:20px;