【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
,同時記錄滑鼠所在座標,獲取選擇的color
和linewidth
,並開啟繪畫路徑
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);
}
接下來實現繪製直線,矩形和圓形的方法其實大同小異,然後為了能讓我們畫矩形和圓形能在所有方向都能畫,我們增加了
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; //原點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-egret】js載入成第三方庫
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:checkboxlist】JS中取s:checkboxlist選中的value傳入後臺例項
body中: <td width="35%"> <s:checkboxlist name="cc" id="kscc1" list="#{'AM':'上午','PM':'下午' }" value="" cssStyle="width:20px;