摘要:比如弧線或圓形從到繪制一條以為圓心,為半徑的弧線,其中和用弧度表示,為時,順時針畫弧線,反之,逆時針畫弧線。
最近筆者在學(xué)習(xí)HTML5的新元素,會分享一些基礎(chǔ)知識以及小例子,最終使用實(shí)現(xiàn)一個繪制簡單圖表(條形圖、線圖或者餅圖)的js庫,會更新一到兩篇文章~
下面我們開始吧~
我們首先應(yīng)該指定標(biāo)簽即畫布的寬度和高度屬性,并在開始和閉合標(biāo)簽之間添加后備信息:
取得繪圖上下文
調(diào)用canvas的getContext()方法,這個方法接收一個參數(shù),即上下文的名字:
var canvas = document.getElementById("canvas"); if(canvas.getContext) { var context = canvas.getContext("2d") }
上述例子中,我們在調(diào)用getContext()方法時,首先檢測其是否存在,這是由于有的瀏覽器遇到HTML規(guī)范之外的標(biāo)簽時,也會創(chuàng)建一個DOM對象,比如我們在Chrome中嘗試以下代碼:
document.getElementById("ppp"); //
因此即使當(dāng)前瀏覽器不能兼容HTML規(guī)范中的canvas元素,同樣會創(chuàng)建DOM對象,可其中卻不存在getContext()。
context上下文對象中包含了繪圖需要的一系列屬性和方法,大家在閱讀本文時,記得區(qū)分屬性和方法,改變屬性會影響到后續(xù)的繪圖效果,而調(diào)用方法往往是一次性的。
2D上下文的坐標(biāo)默認(rèn)開始于左上角,原點(diǎn)坐標(biāo)為(0, 0),使用translate(x, y)可以更改坐標(biāo)原點(diǎn)。
填充,就是用指定的樣式,比如顏色、漸變或圖像填充指定區(qū)域,對應(yīng)的上下文屬性為fillStyle,默認(rèn)值為#000000, 比如:
context.fillStyle = "orange";
描邊就是在指定區(qū)域邊緣畫指定樣式的線,比如:
context.strokeStyle = "grey";
矩形是唯一一個可以在2D上下文中直接話的形狀,其他的都需要繪制路徑,可以使用3個方法直接繪制矩形。
可以繪制一個由fillStyle指定填充樣式的矩形,比如:
context.translate(100, 100) context.fillStyle = "#99cccc"; context.fillRect(-100, -50, 200, 100); context.fillStyle="#3399cc"; context.fillRect(-60, -30, 120, 60);
可以繪制一個由strokeStyle lineWidth lineCap lineJoin等屬性指定描邊樣式的矩形,比如:
context.strokeStyle = "#99cccc"; context.lineWidth = "50"; context.lineJoin = "bevel"; context.strokeRect(0, 0, 400, 200);
屬性名 | 含義 | 取值 |
---|---|---|
lineCap | 線條末端的形狀 | butt平頭round圓頭square方頭 |
lineWidth | 線條寬度 | 整數(shù) |
lineJoin | 線條相交的方式 | round圓交bevel斜交mitter斜接 |
可以清楚畫布上的指定區(qū)域,比如第一個例子中的兩個矩形,我們將中間一小塊清除:
context.translate(100, 100) context.fillStyle = "#99cccc"; context.fillRect(-100, -50, 200, 100); context.fillStyle="#3399cc"; context.clearRect(-60, -30, 120, 60);繪制路徑
使用路徑我們可以繪制出比較復(fù)雜的圖形,開始繪制前,首先執(zhí)行:
context.beginPath();
結(jié)束繪制時,執(zhí)行:
context.closePath();
以下我們列舉了繪制路徑的幾個方法:
lineTo(x, y),從當(dāng)前游標(biāo)至(x, y)畫一條直線。
moveTo(x, y) 將游標(biāo)移動至(x, y),移動過程中不畫線。比如:
context.beginPath(); context.moveTo(10, 10); context.lineTo(50, 40); context.moveTo(50, 50); context.lineTo(100, 90); context.stroke(); context.closePath();
從startAngle到endAngle繪制一條以(x, y)為圓心,radius為半徑的弧線,其中startAngle和endAngle用弧度表示,couterclockwise為false時,順時針畫弧線, 反之,逆時針畫弧線。
var canvas = document.getElementById("canvas"); if(canvas.getContext) { var context = canvas.getContext("2d"); context.beginPath(); context.arc(400, 400, 50, arcUnit()*30, arcUnit()*180, false); context.stroke(); } function arcUnit() { return Math.PI/180; }
arcTo()方法將利用當(dāng)前坐標(biāo)、起點(diǎn)(startX,startY)和終點(diǎn)(endX,endY)這三個點(diǎn)所形成的夾角,繪制一段與夾角的兩邊相切并且半徑為radius的圓上的弧線。弧線的起點(diǎn)就是當(dāng)前坐標(biāo)所在邊與圓的切點(diǎn),弧線的終點(diǎn)就是終點(diǎn)(endX,endY)所在邊與圓的切點(diǎn),并且繪制的弧線是兩個切點(diǎn)之間長度最短的那個圓弧。此外,如果當(dāng)前端點(diǎn)不是(startX,startY),arcTo()方法還將添加一條當(dāng)前端點(diǎn)到(startX,startY)的直線線段。
如果大家還記得高中數(shù)學(xué)的話,我們應(yīng)該可以猜到,使用這個方法畫弧線大致有三種情況:
** 只有一種半徑可以使弧線兩端正好在起點(diǎn)和終點(diǎn)
** 如果半徑過大,畫不出弧線
** 如果半徑較小,必定會有一條當(dāng)前端點(diǎn)到起點(diǎn)的直線
我們舉三個例子:
首先定義一些通用的
var context = canvas.getContext("2d"); var currentPoint = { x: 0, y: 0 }; var startPoint = { x: 50, y: 50 }; var endPoint = { x: 100, y: 0 };
然后繪制參考線
context.moveTo(currentPoint.x, currentPoint.y); context.lineTo(startPoint.x, startPoint.y); context.lineTo(endPoint.x, endPoint.y); context.strokeStyle = "red"; context.stroke();
畫第一條弧線
context.moveTo(currentPoint.x, currentPoint.y); context.arcTo(startPoint.x, startPoint.y, endPoint.x, endPoint.y, 80); context.strokeStyle = "grey"; context.stroke();
context.arcTo(startPoint.x, startPoint.y, endPoint.x, endPoint.y, 120);
context.arcTo(startPoint.x, startPoint.y, endPoint.x, endPoint.y, 40);
quadraticCurveTo(cpX, cpY, x, y)
上述方法可以畫一條從當(dāng)前位置到(x, y), 以(cpX, cpY)為控制點(diǎn)的貝塞爾曲線
bezierCurveTo(cpX1, cpY1, cpX2, cpY2, x, y)
上述方法可以畫一條從當(dāng)前位置到(x, y), 以(cpX1, cpY1)和(cpX2, cpY2)為控制點(diǎn)的貝塞爾曲線。
二次貝塞爾與三次貝塞爾的繪制涉及到比較復(fù)雜的數(shù)學(xué)運(yùn)算,筆者在此就忽略啦...
當(dāng)然,大部分前端人士可能都跟筆者一樣,只希望能畫出一條優(yōu)美的曲線,并不關(guān)心實(shí)現(xiàn)細(xì)節(jié),那么一般認(rèn)為什么樣的曲線才算是優(yōu)美的曲線呢:
對稱的曲線
有一個適度的弧度
根據(jù)以上規(guī)則,我們寫一個工具方法:
function drawCurvePath( ctx, start, end, curveness ) { var cp = [ ( start.x + end.x ) / 2 - ( start.y - end.y ) * curveness, ( start.y + end.y ) / 2 - ( end.x - start.x ) * curveness ]; ctx.moveTo( start.x, start.y ); ctx.quadraticCurveTo( cp[ 0 ], cp[ 1 ], end.x, end.y ); ctx.stroke(); }
以上參考自用canvas繪制一個曲線動畫——深入理解貝塞爾曲線,大家可以前往了解更深入的貝塞爾曲線畫法。
使用rect(x, y, width, height)可以繪制一個左上角坐標(biāo)為(x, y),寬width,高h(yuǎn)eight的矩形路徑。
context.rect(300, 300, 100, 200); context.stroke();繪制文本
在繪制本文之前,如果有必要,我們首先應(yīng)該指定context的幾個屬性, 比如:
context.font = "bold 14px Arial"; // 格式同css中指定字體樣式 context.textAlign = "center"; // start end center left right context.textBaseline = "middle"; // top hanging middle alphabetic ideographic bottom
fillText(text, x, y, maxWidth)使用fillStyle屬性顯示文本,strokeText(text, x, y, maxWidth)使用strokeStyle屬性為文本描邊。
使用measureText(text)方法可以獲得文本的寬度。如果我們并不清楚指定的寬度夠不夠顯示當(dāng)前字體設(shè)置下的一段文字,可以使用如下方法:
var fontSize = 50; var maxWidth = 100; context.font = "bold " + fontSize+"px Arial"; var text = "Hello World!"; while(context.measureText(text).width > maxWidth) { fontSize--; context.font = "bold " + fontSize+"px Arial"; } context.fillText(text, 50, 50, maxWidth);變換
rotate(angle)
context.rotate(Math.PI/4) context.fillText(text, 50, 50, maxWidth);
scale(scaleX, scaleY)
context.scale(1.2, 1.2); context.fillText(text, 50, 50, maxWidth); context.scale(0.5, 0.5); context.fillText(text, 50, 50, maxWidth);
translate(x, y)
假如我們要繪制一個對稱圖形,移動坐標(biāo)原點(diǎn)將會大大簡化對坐標(biāo)的計算。
使用transform(scaleX,skewX,skewY,scaleY,transX,transY)可以進(jìn)行矩陣變換,其實(shí)以上講的三個方法本質(zhì)上都在調(diào)用矩陣變換,從參數(shù)名中可以看出,它們分別表示X軸方向的縮放,Y軸方向的縮放,X軸方向的斜切,Y軸方向的斜切,X軸方向的偏移量,Y軸方向的偏移量。默認(rèn)值分別為1 0 0 1 0 0。
我們現(xiàn)在使用transform()重新定義一遍之前的三個方法:
rotate
function rotate (ctx, degree) { var unit = Math.PI/180; ctx.transform(Math.cos(degree*unit),Math.sin(degree*unit),-Math.sin(degree*unit),Math.cos(degree*unit),0,0) }
scale
function scale (ctx, scale) { ctx.transform(scale.x, 0, 0, scale.y, 0, 0); }
translate
function translate (ctx, translate) { ctx.transform(1, 0, 0, 1, translate.x, translate.y); }
我們現(xiàn)在繪制一段文本,先平移(50, 50),然后縮放2倍,最后旋轉(zhuǎn)30度。
context.fillText(text, 50, 50, maxWidth); translate(context, {x: 50, y: 50}); scale(context, {x: 2, y: 2}); rotate(context, 30); context.fillText(text, 50, 50, maxWidth);
每次執(zhí)行transform()都是基于上一次的結(jié)果,并不是初始狀態(tài),很多時候我們想執(zhí)行的是基于初始狀態(tài)旋轉(zhuǎn)、平移或縮放,而非上一次的狀態(tài),此時我們可以使用setTransfrom(scaleX,skewX,skewY,scaleY,transX,transY),此方法首先會重置變換矩陣,然后執(zhí)行transform()。
更加詳細(xì)的內(nèi)容可以參考html5 Canvas畫圖教程26:用transform來實(shí)現(xiàn)位移,縮放,旋轉(zhuǎn)等
使用drawImage(image, x1, y1, width1, height1, x2, y2, width2, height2)可以將圖像的指定部分按照指定的大小繪制到畫布指定的位置上。
參數(shù) | 含義 |
---|---|
image | 要繪制的圖像,可以是HTMLImageElement,也可以是canvas |
x1 | 源圖像的x坐標(biāo) |
y1 | 源圖像的y坐標(biāo) |
width1 | 源圖像的寬度 |
height1 | 源圖像的高度 |
x2 | 畫布的x坐標(biāo) |
y2 | 畫布的y坐標(biāo) |
width2 | 圖像在畫布上顯示的寬度 |
height2 | 圖像在畫布上顯示的高度 |
如果要給形狀或路徑加上陰影,我們要在繪制前設(shè)置context對象的以下屬性:
屬性 | 含義 |
---|---|
shadowColor | 陰影顏色 |
shadowOffsetX | x軸偏移量 |
shadowOffsetY | y軸偏移量 |
shadowBlur | 模糊的像素數(shù) |
context.shadowColor = "grey"; context.shadowOffsetX = "20"; context.shadowBlur = "5"; context.fillText(text, 50, 50, maxWidth);漸變
使用createLinearGradient(startX, startY, endX, endY)來創(chuàng)建線性漸變,這個方法確認(rèn)了漸變的起始和方向,然后我們通過addColorStop(position, color)來添加漸變的顏色,position是0到1的數(shù)字。一下筆者畫一個超級喜歡的條紋漸變:
var grad = context.createLinearGradient(50, 50, 200, 200) grad.addColorStop(0, "grey"); grad.addColorStop(0.3, "grey"); grad.addColorStop(0.3, "red"); grad.addColorStop(0.5, "red"); grad.addColorStop(0.5, "orange"); grad.addColorStop(0.7, "orange"); context.fillStyle = grad; context.fillRect(50, 50, 150, 150);
使用createRadialGradient(centerX1, centerY1, radius1, centerX2, centerY2, radius2)創(chuàng)建徑向漸變。
圖像重復(fù)使用createPattern(image, repeatType)可以繪制重復(fù)的圖像,用來填充或描邊,第一個參數(shù)是要重復(fù)的HTMLImageElement或canvas或video,第二個參數(shù)表示如何重復(fù)該圖像,可取repeat repeat-x repeat-y no-repeat
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/94741.html
摘要:是新加的標(biāo)簽,主要有和,的應(yīng)用是動畫和圖像,的應(yīng)用是游戲渲染。 HTML5 Canvas canvas是html5新加的標(biāo)簽,主要有2D和3D,2D的應(yīng)用是動畫和圖像,3D的應(yīng)用是游戲渲染。 1. 2D基礎(chǔ) 1.1繪制線 canvas window.onload = function(){ ...
摘要:游戲開發(fā)實(shí)戰(zhàn)主要講解使用來開發(fā)和設(shè)計各類常見游戲的思路和技巧,在介紹相關(guān)特性的同時,還通過游戲開發(fā)實(shí)例深入剖析了其內(nèi)在原理,讓讀者不僅知其然,而且知其所以然。HTML5 Canvas游戲開發(fā)實(shí)戰(zhàn)主要講解使用HTML5 Canvas來開發(fā)和設(shè)計各類常見游戲的思路和技巧,在介紹HTML5 Canvas相關(guān)特性的同時,還通過游戲開發(fā)實(shí)例深入剖析了其內(nèi)在原理,讓讀者不僅知其然,而且知其所以然。在本書...
摘要:前端知識點(diǎn)總結(jié)新特性新的語義標(biāo)簽增強(qiáng)型表單音頻和視頻繪圖繪圖地理定位拖動增強(qiáng)型表單新新的表單元素新特性數(shù)據(jù)列表本身不可見為提供輸入建議列表新特性進(jìn)度條左右晃動進(jìn)度條具有指定進(jìn)度值進(jìn)度條新特性刻度尺用于標(biāo)示一個值所值的范圍不 前端知識點(diǎn)總結(jié)——H5 1.html5新特性 (1)新的語義標(biāo)簽 (2)增強(qiáng)型表單* (3)音頻和視頻 (4)Canvas繪圖 (5)SVG繪圖 (6)地...
閱讀 1105·2021-11-16 11:45
閱讀 3124·2021-10-13 09:40
閱讀 714·2019-08-26 13:45
閱讀 1188·2019-08-26 13:32
閱讀 2167·2019-08-26 13:23
閱讀 911·2019-08-26 12:16
閱讀 2823·2019-08-26 11:37
閱讀 1748·2019-08-26 10:32