超酷的HTML5 Canvas網路畫板教程
本文由碼農網 – 小峰原創,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃!
在今天的HTML教程裡,我們要學習一下如何使用HTML5 Canvas實現一個超酷而又簡單的網路畫板功能。在這個教程中,我們可以選擇筆刷的型別、筆刷的大小以及筆刷的顏色,當然作為畫板還需要很多功能,這裡只是最基本的繪製功能,大家可以自己實現類似矩形、橢圓等複雜元素的繪製。
你也可以再這裡檢視DEMO演示
下面我們來簡單地分析一下實現這個HTML5網頁畫板的原理及程式碼,程式碼由HTML以及Javascript組成,主要還是Javascript程式碼。
HTML程式碼:
<div style="width:530px;margin:10px auto"> <div id="canvasDiv"></div> </div>
HTML程式碼非常簡單,僅僅是構造了一個canvas容器,我們的畫板就在這個地方生成。
Javascript程式碼:
首先我們通過一組變數來定義畫板的樣式,以及一些資料的初始化:
var canvas; var context; var canvasWidth = 490; var canvasHeight = 220; var padding = 25; var lineWidth = 8; var colorPurple = "#cb3594"; var colorGreen = "#659b41"; var colorYellow = "#ffcf33"; var colorBrown = "#986928"; var outlineImage = new Image(); var crayonImage = new Image(); var markerImage = new Image(); var eraserImage = new Image(); var crayonBackgroundImage = new Image(); var markerBackgroundImage = new Image(); var eraserBackgroundImage = new Image(); var crayonTextureImage = new Image(); var clickX = new Array(); var clickY = new Array(); var clickColor = new Array(); var clickTool = new Array(); var clickSize = new Array(); var clickDrag = new Array(); var paint = false; var curColor = colorPurple; var curTool = "crayon"; var curSize = "normal"; var mediumStartX = 18; var mediumStartY = 19; var mediumImageWidth = 93; var mediumImageHeight = 46; var drawingAreaX = 111; var drawingAreaY = 11; var drawingAreaWidth = 267; var drawingAreaHeight = 200; var toolHotspotStartY = 23; var toolHotspotHeight = 38; var sizeHotspotStartY = 157; var sizeHotspotHeight = 36; var sizeHotspotWidthObject = new Object(); sizeHotspotWidthObject.huge = 39; sizeHotspotWidthObject.large = 25; sizeHotspotWidthObject.normal = 18; sizeHotspotWidthObject.small = 16; var totalLoadResources = 8; var curLoadResNum = 0;
接下來開始準備畫布,也就是初始化Canvas物件:
function prepareCanvas() { // Create the canvas (Neccessary for IE because it doesn't know what a canvas element is) var canvasDiv = document.getElementById('canvasDiv'); canvas = document.createElement('canvas'); canvas.setAttribute('width', canvasWidth); canvas.setAttribute('height', canvasHeight); canvas.setAttribute('id', 'canvas'); canvasDiv.appendChild(canvas); if(typeof G_vmlCanvasManager != 'undefined') { canvas = G_vmlCanvasManager.initElement(canvas); } context = canvas.getContext("2d"); // Grab the 2d canvas context // Note: The above code is a workaround for IE 8 and lower. Otherwise we could have used: // context = document.getElementById('canvas').getContext("2d"); // Load images // ----------- crayonImage.onload = function() { resourceLoaded(); }; crayonImage.src = "images/crayon-outline.png"; //context.drawImage(crayonImage, 0, 0, 100, 100); markerImage.onload = function() { resourceLoaded(); }; markerImage.src = "images/marker-outline.png"; eraserImage.onload = function() { resourceLoaded(); }; eraserImage.src = "images/eraser-outline.png"; crayonBackgroundImage.onload = function() { resourceLoaded(); }; crayonBackgroundImage.src = "images/crayon-background.png"; markerBackgroundImage.onload = function() { resourceLoaded(); }; markerBackgroundImage.src = "images/marker-background.png"; eraserBackgroundImage.onload = function() { resourceLoaded(); }; eraserBackgroundImage.src = "images/eraser-background.png"; crayonTextureImage.onload = function() { resourceLoaded(); }; crayonTextureImage.src = "images/crayon-texture.png"; outlineImage.onload = function() { resourceLoaded(); }; outlineImage.src = "images/watermelon-duck-outline.png"; // Add mouse events // ---------------- $('#canvas').mousedown(function(e) { // Mouse down location var mouseX = e.pageX - this.offsetLeft; var mouseY = e.pageY - this.offsetTop; if(mouseX < drawingAreaX) // Left of the drawing area { if(mouseX > mediumStartX) { if(mouseY > mediumStartY && mouseY < mediumStartY + mediumImageHeight){ curColor = colorPurple; }else if(mouseY > mediumStartY + mediumImageHeight && mouseY < mediumStartY + mediumImageHeight * 2){ curColor = colorGreen; }else if(mouseY > mediumStartY + mediumImageHeight * 2 && mouseY < mediumStartY + mediumImageHeight * 3){ curColor = colorYellow; }else if(mouseY > mediumStartY + mediumImageHeight * 3 && mouseY < mediumStartY + mediumImageHeight * 4){ curColor = colorBrown; } } } else if(mouseX > drawingAreaX + drawingAreaWidth) // Right of the drawing area { if(mouseY > toolHotspotStartY) { if(mouseY > sizeHotspotStartY) { var sizeHotspotStartX = drawingAreaX + drawingAreaWidth; if(mouseY < sizeHotspotStartY + sizeHotspotHeight && mouseX > sizeHotspotStartX) { if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.huge){ curSize = "huge"; }else if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){ curSize = "large"; }else if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.normal + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){ curSize = "normal"; }else if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.small + sizeHotspotWidthObject.normal + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){ curSize = "small"; } } } else { if(mouseY < toolHotspotStartY + toolHotspotHeight){ curTool = "crayon"; }else if(mouseY < toolHotspotStartY + toolHotspotHeight * 2){ curTool = "marker"; }else if(mouseY < toolHotspotStartY + toolHotspotHeight * 3){ curTool = "eraser"; } } } } else if(mouseY > drawingAreaY && mouseY < drawingAreaY + drawingAreaHeight) { // Mouse click location on drawing area } paint = true; addClick(mouseX, mouseY, false); redraw(); }); $('#canvas').mousemove(function(e){ if(paint==true){ addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true); redraw(); } }); $('#canvas').mouseup(function(e){ paint = false; redraw(); }); $('#canvas').mouseleave(function(e){ paint = false; }); }
看起來很複雜,前面主要是初始化canvas的背景圖片,後面主要是初始化畫筆事件,像click、mouseup、mouseleave等滑鼠事件。
下面是draw的主要方法:
function redraw() { // Make sure required resources are loaded before redrawing if(curLoadResNum < totalLoadResources){ return; } clearCanvas(); var locX; var locY; if(curTool == "crayon") { // Draw the crayon tool background context.drawImage(crayonBackgroundImage, 0, 0, canvasWidth, canvasHeight); // Purple locX = (curColor == colorPurple) ? 18 : 52; locY = 19; context.beginPath(); context.moveTo(locX + 41, locY + 11); context.lineTo(locX + 41, locY + 35); context.lineTo(locX + 29, locY + 35); context.lineTo(locX + 29, locY + 33); context.lineTo(locX + 11, locY + 27); context.lineTo(locX + 11, locY + 19); context.lineTo(locX + 29, locY + 13); context.lineTo(locX + 29, locY + 11); context.lineTo(locX + 41, locY + 11); context.closePath(); context.fillStyle = colorPurple; context.fill(); if(curColor == colorPurple){ context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight); }else{ context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight); } // Green locX = (curColor == colorGreen) ? 18 : 52; locY += 46; context.beginPath(); context.moveTo(locX + 41, locY + 11); context.lineTo(locX + 41, locY + 35); context.lineTo(locX + 29, locY + 35); context.lineTo(locX + 29, locY + 33); context.lineTo(locX + 11, locY + 27); context.lineTo(locX + 11, locY + 19); context.lineTo(locX + 29, locY + 13); context.lineTo(locX + 29, locY + 11); context.lineTo(locX + 41, locY + 11); context.closePath(); context.fillStyle = colorGreen; context.fill(); if(curColor == colorGreen){ context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight); }else{ context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight); } // Yellow locX = (curColor == colorYellow) ? 18 : 52; locY += 46; context.beginPath(); context.moveTo(locX + 41, locY + 11); context.lineTo(locX + 41, locY + 35); context.lineTo(locX + 29, locY + 35); context.lineTo(locX + 29, locY + 33); context.lineTo(locX + 11, locY + 27); context.lineTo(locX + 11, locY + 19); context.lineTo(locX + 29, locY + 13); context.lineTo(locX + 29, locY + 11); context.lineTo(locX + 41, locY + 11); context.closePath(); context.fillStyle = colorYellow; context.fill(); if(curColor == colorYellow){ context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight); }else{ context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight); } // Yellow locX = (curColor == colorBrown) ? 18 : 52; locY += 46; context.beginPath(); context.moveTo(locX + 41, locY + 11); context.lineTo(locX + 41, locY + 35); context.lineTo(locX + 29, locY + 35); context.lineTo(locX + 29, locY + 33); context.lineTo(locX + 11, locY + 27); context.lineTo(locX + 11, locY + 19); context.lineTo(locX + 29, locY + 13); context.lineTo(locX + 29, locY + 11); context.lineTo(locX + 41, locY + 11); context.closePath(); context.fillStyle = colorBrown; context.fill(); if(curColor == colorBrown){ context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight); }else{ context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight); } } else if(curTool == "marker") { // Draw the marker tool background context.drawImage(markerBackgroundImage, 0, 0, canvasWidth, canvasHeight); // Purple locX = (curColor == colorPurple) ? 18 : 52; locY = 19; context.beginPath(); context.moveTo(locX + 10, locY + 24); context.lineTo(locX + 10, locY + 24); context.lineTo(locX + 22, locY + 16); context.lineTo(locX + 22, locY + 31); context.closePath(); context.fillStyle = colorPurple; context.fill(); if(curColor == colorPurple){ context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight); }else{ context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight); } // Green locX = (curColor == colorGreen) ? 18 : 52; locY += 46; context.beginPath(); context.moveTo(locX + 10, locY + 24); context.lineTo(locX + 10, locY + 24); context.lineTo(locX + 22, locY + 16); context.lineTo(locX + 22, locY + 31); context.closePath(); context.fillStyle = colorGreen; context.fill(); if(curColor == colorGreen){ context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight); }else{ context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight); } // Yellow locX = (curColor == colorYellow) ? 18 : 52; locY += 46; context.beginPath(); context.moveTo(locX + 10, locY + 24); context.lineTo(locX + 10, locY + 24); context.lineTo(locX + 22, locY + 16); context.lineTo(locX + 22, locY + 31); context.closePath(); context.fillStyle = colorYellow; context.fill(); if(curColor == colorYellow){ context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight); }else{ context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight); } // Yellow locX = (curColor == colorBrown) ? 18 : 52; locY += 46; context.beginPath(); context.moveTo(locX + 10, locY + 24); context.lineTo(locX + 10, locY + 24); context.lineTo(locX + 22, locY + 16); context.lineTo(locX + 22, locY + 31); context.closePath(); context.fillStyle = colorBrown; context.fill(); if(curColor == colorBrown){ context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight); }else{ context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight); } } else if(curTool == "eraser") { context.drawImage(eraserBackgroundImage, 0, 0, canvasWidth, canvasHeight); context.drawImage(eraserImage, 18, 19, mediumImageWidth, mediumImageHeight); }else{ alert("Error: Current Tool is undefined"); } if(curSize == "small"){ locX = 467; }else if(curSize == "normal"){ locX = 450; }else if(curSize == "large"){ locX = 428; }else if(curSize == "huge"){ locX = 399; } locY = 189; context.beginPath(); context.rect(locX, locY, 2, 12); context.closePath(); context.fillStyle = '#333333'; context.fill(); // Keep the drawing in the drawing area context.save(); context.beginPath(); context.rect(drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight); context.clip(); var radius; var i = 0; for(; i < clickX.length; i++) { if(clickSize[i] == "small"){ radius = 2; }else if(clickSize[i] == "normal"){ radius = 5; }else if(clickSize[i] == "large"){ radius = 10; }else if(clickSize[i] == "huge"){ radius = 20; }else{ alert("Error: Radius is zero for click " + i); radius = 0; } context.beginPath(); if(clickDrag[i] && i){ context.moveTo(clickX[i-1], clickY[i-1]); }else{ context.moveTo(clickX[i], clickY[i]); } context.lineTo(clickX[i], clickY[i]); context.closePath(); if(clickTool[i] == "eraser"){ //context.globalCompositeOperation = "destination-out"; // To erase instead of draw over with white context.strokeStyle = 'white'; }else{ //context.globalCompositeOperation = "source-over"; // To erase instead of draw over with white context.strokeStyle = clickColor[i]; } context.lineJoin = "round"; context.lineWidth = radius; context.stroke(); } //context.globalCompositeOperation = "source-over";// To erase instead of draw over with white context.restore(); // Overlay a crayon texture (if the current tool is crayon) if(curTool == "crayon"){ context.globalAlpha = 0.4; // No IE support context.drawImage(crayonTextureImage, 0, 0, canvasWidth, canvasHeight); } context.globalAlpha = 1; // No IE support // Draw the outline image context.drawImage(outlineImage, drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight); }
其實HTML5說白了還是需要很多Javascript支援,不過Canvas非常不錯,可以讓你在上面自由地繪製圖形和動畫。這款基於HTML5 Canvas的網頁畫板就是一個很好的例子。原始碼下載>>
本文連結:http://www.codeceo.com/article/cool-html5-canvas-drawing.html
本文作者:碼農網 – 小峰
[ 原創作品,轉載必須在正文中標註並保留原文連結和作者等資訊。]
相關文章
- canvas畫素畫板Canvas
- Android 利用 Canvas 畫畫板AndroidCanvas
- Canvas畫板—手機上也可以用的畫板Canvas
- canvas簡單畫板效果Canvas
- html5畫布canvasHTMLCanvas
- 超酷!!HTML5 Canvas 水流樣式 Loading 動畫HTMLCanvas動畫
- canvas小畫板--(1)平滑曲線Canvas
- canvas小畫板——(3)筆鋒效果Canvas
- 用canvas畫一個七竅板Canvas
- 用HTML5的canvas畫太陽系HTMLCanvas
- 用canvas實現一個簡單的畫板Canvas
- 利用html5 canvas 畫圖的一個例子HTMLCanvas
- canvas實現的簡單畫板效果程式碼例項Canvas
- html5中canvas元素建立畫布介紹HTMLCanvas
- 戴爾推出Canvas智慧畫板 對標微軟Surface StudioCanvas微軟
- 快速建立 HTML5 Canvas 電信網路拓撲圖HTMLCanvas
- 基於 HTML5 Canvas 電信網路拓撲圖的快速搭建HTMLCanvas
- 基於 HTML5 Canvas 繪製的電信網路拓撲圖HTMLCanvas
- 手把手教你實現一個canvas智繪畫板Canvas
- canvas 塗鴉畫板,支援筆寫、手寫、滑鼠繪圖Canvas繪圖
- HTML5的CanvasHTMLCanvas
- 魔法填充+無限擴圖,Ideogram推出AI畫板工具CanvasIDEAICanvas
- 《HTML5 Canvas基礎教程》適合你嗎?HTMLCanvas
- Winform下的畫板ORM
- HTML5 -- CanvasHTMLCanvas
- 好書短評之《HTML5 Canvas基礎教程》HTMLCanvas
- 18 款超酷的 HTML5 和 JavaScript 遊戲引擎庫HTMLJavaScript遊戲引擎
- HTML5畫布canvas隨機生成圓形和正方形HTMLCanvas隨機
- HTML5 Canvas使用路徑——繪製圓形HTMLCanvas
- 前端學習筆記----canvas實現畫板及定製畫筆(畫筆錯位,撤回,粗細,顏色)前端筆記Canvas
- 超酷HTML5 3D動畫精選HTML3D動畫
- HTML5的canvas標籤HTMLCanvas
- 超酷創意HTML5動畫演示及程式碼HTML動畫
- 網路影像的拼貼畫
- 「Photoshop2021入門教程」建立不同用途的畫板
- 淺析HTML5的Canvas——1HTMLCanvas
- 基於 Canvas 的 HTML5 互動式地鐵線路圖CanvasHTML
- Canvas 教程Canvas