搜尋
首頁web前端html教學講一講 Canvas 究竟是個啥

HTML5 的標準已經出來很久了,但是似乎其中的 Canvas 現在並沒有在太多的地方用到。一個很重要的原因是,Canvas 的標準還沒有完全確定,不適合大規模用於生產環境。但是,Canvas 的優點也是很明顯的,例如在繪製含有大量元素的圖表的時候,SVG 往往因為性能問題而無法勝任,例如我見過的一次技術分享會的抽獎環節,雖然效果比較炫,但因為每個頭像都是DOM,利用CSS3 控制的動畫,導致了效能非常低。此外,隨著硬體效能的提高,視訊截圖、影像處理等功能也逐漸可以在網頁上實現了,大多數網站用的是Flash,但是Flash 在Mac 電腦上效能不高,還需要學習一些額外的知識。 Canvas 則是直接使用 JavaScript 來進行繪圖,對 Mac 友好,所以不失為 Flash 的一個繼承者。

使用 Canvas

說了這麼多,Canvas 究竟是個啥?

英文中 Canvas 的意思是“畫布”,不過這裡說的 Canvas 是 HTML5 中新出的一個元素,開發者可以在上面繪製一系列圖形。 Canvas 在HTML 文件中的寫法很簡單:


其中 id 屬性是所有HTML 元素都可以用的,Canvas 自帶的屬性只有後面兩個(分別控制寬度、高度),沒有其它的了。至於相容性,CanIUse 上面寫了,基礎的功能目前用戶使用的 90% 的瀏覽器都支持,所以大部分情況下還是可以放心使用的。

講一講 Canvas 究竟是個啥

注意,一定要用 Canvas 隨附的 width 和 height 屬性,請勿使用 CSS 來控制,因為 CSS 控制會造成 Canvas 變形。可以試著與 PhptpShop 對比一下,後者是改變“圖像大小”,前者才是正確的改變“畫布大小”。例如下圖是三張圖片的橫向拼接:最左邊的黑框中是大小為50px * 50px 的原圖;中間是改變了圖像大小為100px * 100px 的效果,圖像變得模糊,但是對於圖像本身來說座標範圍並沒有變大;最右邊才是正確的100px * 100px 的Canvas。

講一講 Canvas 究竟是個啥

Canvas 絕大部分的繪圖方法都與  標籤無關,需要使用 JavaScript 來操作,這就是所謂的 Canvas API。

我們首先取得到這個元素:

var canvas = document.getElementById('canvas');

然後透過一個方法來取得可以呼叫一切 Canvas API 的入口:

var ctx = canvas.getContext('2d');

看到 2d 是不是很激動地聯想到有沒有 3d 呢?沒有 3d 的寫法,不過如果想要開啟 3D 世界的大門,則可以寫 canvas.getContext('webgl')。然而 WebGL 是基於 OpenGL ES 2.0 的一套標準,與本文是徹底的兩條路,因此這裡就不討論了。

Canvas 中的基本概念

坐標

與數學上常見的笛卡爾坐標係不太相同,Canvas 的坐標係是計算機中常見的坐標系,它長這樣:

講一講 Canvas 究竟是個啥

畫布的最左上角是(0,0),往右x 增大,往下y 增大,而且x 和y 都是整數(就算在計算過程中不是整數,在繪製的時候也會當作整數處理),單位是像素。

绘图

带大家怀旧一下。不知道有多少同学小时候玩过 logo 语言,在里面你可以控制一只小海龟在一块板子上行走、画画、提笔、落笔。Canvas 中也一样,你需要控制一只画笔的移动和绘制。然而 Canvas 更高级一些,你可以直接利用一些函数来画图,不用去控制那只画笔的位置。

Canvas 中的基本图形

通过上文定义的 ctx 变量可以干许多有意思的事情,我们先看看如何绘制一些基本图形。

线条

我们指定画笔移动到某一点,然后告诉画笔需要从当前这一点画到另一点。我们可以让画笔多次移动、绘制,最后统一输出到屏幕上。例子如下:

ctx.moveTo(10, 10);
ctx.lineTo(150, 50);
ctx.lineTo(10, 50);
ctx.moveTo(10, 20);
ctx.lineTo(40, 70);
ctx.stroke();

上面的代码中,lineTo 是产生线条用的函数,执行完之后画笔就移到了线条的终点。需要注意的是,线条此时并没有显示在屏幕上,必须调用 stroke 才会显示。这样设计是有道理的,因为向屏幕上输出内容需要耗费大量的资源,我们完全可以先攒够一波 lineTo,最后用 stroke 放一个大的。

路径

绘制路径非常简单,只需要先告诉 ctx 一声“我要开始画路径了”,然后通过各种方法(例如 lineTo)绘制路径。如果需要画一个封闭路径,那就最后告诉 ctx一声:“我画完了,你把它封闭起来吧。”当然,不要忘记利用 stroke 输出到屏幕上。

一个简单的例子:

ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(150, 50);
ctx.lineTo(10, 50);
ctx.closePath();
ctx.stroke();

如果我不想只描绘路径线条,而是想填充整个路径呢?可以将最后一行的 stroke 改成 fill,这样就跟使用了画图中的油漆桶一样,封闭路径里面的内容就都被填充上颜色了:

ctx.fill();

弧 / 圆形

绘制弧的函数参数比较多:

ctx.arc(圆心 x 坐标, 圆心 y 坐标, 半径, 起始角度, 终止角度, 是否为逆时针);

注意,在 Canvas 的坐标系中,角的一边是以圆心为中心的水平向右的直线。角度单位均为弧度。例如下图,确定了圆心、起始角度(图中标明的锐角)和终止角度(图中标明的钝角),方向为逆时针,于是就有了这么一个弧。如果方向为顺时针,那么就会是一个跟它互补的、非常非常大的弧……

講一講 Canvas 究竟是個啥

所以如果转了 2π 圈之后,弧就成了圆形,因此也可以使用绘制弧的方式来绘制圆形:

ctx.beginPath();
ctx.arc(圆心 x 坐标, 圆心 y 坐标, 半径, 0, Math.PI * 2, true);
ctx.closePath();

最后一个参数随便填(当然也可以不填),因为不管是顺时针还是逆时针,转了 2π 圈之后都是一个圆。

矩形

如果只是想绘制一个横平竖直的矩形,可以使用下面的两个方法:

// 只描边
ctx.strokeRect(左上角 x 坐标, 左上角 y 坐标, 宽度, 高度);
// 只填充
ctx.fillRect(左上角 x 坐标, 左上角 y 坐标, 宽度, 高度);

线条样式 / 填充样式

之前绘制的所有图形都是黑色的,但是 Canvas 肯定不止这么一种颜色(不然标准的制定者会被喷的很惨)。事实上,Canvas 可以单独设置线条样式和填充样式,分别使用的是 strokeStyle 和 fillStyle。可能的值有三种:纯色、渐变、图像。既然线条样式与填充样式的使用方法相同,那么下面统一以填充样式为例。如果想设置线条样式,直接将所有的 fillStyle 改成 strokeStyle 即可,里面的参数都不变。

/* 纯色填充 */
// 普通的颜色
ctx.fillStyle = '#0000ff';
// 带有透明度的颜色
ctx.fillStyle = 'rgba(64, 0, 127, 0.5)';

/* 渐变填充 */
// 设置渐变的尺寸(参数分别为起始点的 x 和 y、终止点的 x 和 y)
var gradient = ctx.createLinearGradient(0, 0, 170, 0);
// 设置过渡色,第一个参数是渐变的位置,第二个参数是颜色
gradient.addColorStop(0, 'magenta');
gradient.addColorStop(0.5, 'blue');
gradient.addColorStop(1.0, 'red');
// 设置填充样式
ctx.fillStyle = gradient;

/* 图片填充 */
// 创建图片
var image = new Image;
image.src = '/path/to/image.png';
// 创建图片笔触,可以指定图片的平铺方式,这里是横向平铺
var pattern = ctx.createPattern(image, 'repeat-x');
// 设置笔触填充
ctx.fillStyle = pattern;

关于渐变,除了代码中提到的线性渐变以外,还有 createRadialGradient,也就是径向渐变。

设置完填充样式之后,就可以使用 fill 来填充啦!如果设置的是线条样式,那么就可以使用 stroke 来描边。

当然,对于线条样式,还有个额外的方法叫 lineWidth 可以用来控制线条的宽度。

文字

要想在画布上画文字,首先需要知道所使用的字体和字号:

ctx.font = '30px Verdana';

然后就可以通过 strokeText 或者 fillText 来对字体描边或者填充字体。

ctx.strokeText("Hello Coding!", 23, 33);
ctx.fillText("Hello Coding!", 23, 66);

图片

在 Canvas 中绘制图片有三种方法:

// 指定绘制位置
ctx.drawImage(image, x, y);
// 指定绘制位置和图像宽高
ctx.drawImage(image, x, y, width, height);
// 指定剪裁区域、绘制位置和图像宽高
ctx.drawImage(image, sx, sy, swidth, sheight, x, y, width, height);

参数的含义依次如下:

image:   要使用的 Image、Canvas 或 Video
sx:      可选,开始剪切的 x 坐标
sy:      可选,开始剪切的 y 坐标
swidth:  可选,被剪切图像的宽度
sheight: 可选,被剪切图像的高度
x:       在画布上放置图像的 x 坐标
y:       在画布上放置图像的 y 坐标
width:   可选,要使用的图像的宽度
height:  可选,要使用的图像的高度

画布设置

细心的同学可能会发现,刚才有些属性是直接对 ctx 变量做设置,例如 ctx.lineWidth,只要设置了它,那么后续画出来的线条全都是这么个宽度。

其实,Canvas 的设置项还有许多,例如我们可以直接移动画布、旋转画布、设置全局的绘制透明度等等。这些设置还可以随时保存和恢复。

要注意的一点是,所有已经画在画布上的东西,是已经定死了的,不管之后再次进行任何设置都不会再改变。这个很像 Windows 下的画图程序。

废话不多说,直接上代码:

// 移动画布,其实就是移动坐标系
ctx.translate(往右移动的量, 往下移动的量);
// 旋转画布,旋转中心为坐标系原点
ctx.rotate(顺时针旋转的角度);
// 以坐标系原点为中心缩放画布
ctx.scale(横向放大倍数, 纵向放大倍数);
// 设置绘制透明度,如果 fillStyle 等属性设置了透明度则会叠加
ctx.globalAlpha(零到一的小数);
// 设置全局组合操作
ctx.globalCompositeOperation = 'lighter';
// 保存当前设置
ctx.save();
// 恢复上次保存的设置
ctx.restore();

移动、旋转、缩放其实就是在控制绘图的坐标系,如果你在调用这三个方法的时候,脑子里时刻有一个带刻度的坐标系,效果会非常好。

事實上,Canvas 的座標變換遵循電腦圖形學的知識:變換矩陣。簡單來說,一個座標可以看成是一個矩陣,座標所對應的矩陣乘上變換矩陣就可以實現對座標的變換。為了提升計算的效率,可以先計算出幾種變換複合之後的變換矩陣,然後直接透過 transform 函數對目前座標系進行變換,或透過 setTransform 函數將座標系重設為初始狀態後再進行變換。至於變換矩陣的內容,對於本文來說就有些超綱了。

全域組合操作有點像PhotoShop 裡面的“混合選項”,具體的實現方式還沒有完全確定,目前常見瀏覽器都統一了的實現方式有:source-over、source-atop、destination-over、destination- out、lighter、xor。具體的行為可以看 Mozilla 官方文檔,但是由於標準還未完全確定,因此其它瀏覽器不保證所有的行為都跟 Mozilla 的標準一致。一般來說,比較常見的是 source-over 和 lighter 兩種,這兩種的標準在瀏覽器界也算是無可爭議的。

至於保存和恢復設定就有點好玩了,首先需要了解一個叫做「棧」的東西。

棧是一個一維數組,規定只能從一個方向操作。棧一開始是空的,我們可以從這個方嚮往數組 push 元素,也只能從這個方向把最後一個元素(棧頂元素)pop 出來,除此以外沒有任何多餘的操作。當然,pop 的次數不能多於 push 的次數,因為 pop 到堆疊底部的時候棧裡就已經沒有元素了,此時再 pop 是沒有意義的。棧的用處有很多,例如括號匹配、表達式求值、深度優先搜索,甚至絕大部分語言的函數呼叫都要用到棧。

每次我們調用 save 函數,實際上是將當前的全域設定push 到了一個專門棧上,每次調用 restore 函數的時候將最後一次保存的內容pop 出來並用它覆蓋當前的全局設置,這樣頂棧就是最近一次保存的內容了。保存和恢復在某些情況下很好用,例如我需要畫一個歪著的圖形,然後繼續畫正著的圖形,這樣就可以先調用 save,然後調用 rotate,畫完圖形之後再restore 回來,繼續畫其它的圖形。

其實Canvas 還有許多方法,例如 toDataURL 直接將目前畫布上的內容轉換為十六進位的 data-url,getImageData 直接將影像轉換為RGBA 陣列以供影像處理演算法使用,putImageData 將RGBA 陣列轉換為圖片顯示在畫布上等等。如果配上 JavaScript 的計時更新(最好用 requestAnimationFrame 而不是 setInterval),則可以產生動畫效果。網路上還有許多 Canvas 的函式庫,可以讓程式設計師更簡單地基於 Canvas 編寫屬於自己的特效或功能。在這兒我想說一句話:大家的腦洞有多大,Canvas 的能力就有多強~


陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
了解HTML,CSS和JavaScript:初學者指南了解HTML,CSS和JavaScript:初學者指南Apr 12, 2025 am 12:02 AM

WebDevelovermentReliesonHtml,CSS和JavaScript:1)HTMLStructuresContent,2)CSSStyleSIT和3)JavaScriptAddSstractivity,形成thebasisofmodernWebemodernWebExexperiences。

HTML的角色:構建Web內容HTML的角色:構建Web內容Apr 11, 2025 am 12:12 AM

HTML的作用是通過標籤和屬性定義網頁的結構和內容。 1.HTML通過到、等標籤組織內容,使其易於閱讀和理解。 2.使用語義化標籤如、等增強可訪問性和SEO。 3.優化HTML代碼可以提高網頁加載速度和用戶體驗。

HTML和代碼:仔細觀察術語HTML和代碼:仔細觀察術語Apr 10, 2025 am 09:28 AM

htmlisaspecifictypefodyfocusedonstructuringwebcontent,而“代碼” badlyLyCludEslanguagesLikeLikejavascriptandPytyPythonForFunctionality.1)htmldefineswebpagertuctureduseTags.2)“代碼”代碼“ code” code code code codeSpassSesseseseseseseseAwiderRangeLangeLangeforLageforLogageforLogicIctInterract

HTML,CSS和JavaScript:Web開發人員的基本工具HTML,CSS和JavaScript:Web開發人員的基本工具Apr 09, 2025 am 12:12 AM

HTML、CSS和JavaScript是Web開發的三大支柱。 1.HTML定義網頁結構,使用標籤如、等。 2.CSS控製網頁樣式,使用選擇器和屬性如color、font-size等。 3.JavaScript實現動態效果和交互,通過事件監聽和DOM操作。

HTML,CSS和JavaScript的角色:核心職責HTML,CSS和JavaScript的角色:核心職責Apr 08, 2025 pm 07:05 PM

HTML定義網頁結構,CSS負責樣式和佈局,JavaScript賦予動態交互。三者在網頁開發中各司其職,共同構建豐富多彩的網站。

HTML容易為初學者學習嗎?HTML容易為初學者學習嗎?Apr 07, 2025 am 12:11 AM

HTML適合初學者學習,因為它簡單易學且能快速看到成果。 1)HTML的學習曲線平緩,易於上手。 2)只需掌握基本標籤即可開始創建網頁。 3)靈活性高,可與CSS和JavaScript結合使用。 4)豐富的學習資源和現代工具支持學習過程。

HTML中起始標籤的示例是什麼?HTML中起始標籤的示例是什麼?Apr 06, 2025 am 12:04 AM

AnexampleOfAstartingTaginHtmlis,beginSaparagraph.startingTagSareEssentialInhtmlastheyInitiateEllements,defiteTheeTheErtypes,andarecrucialforsstructuringwebpages wepages webpages andConstructingthedom。

如何利用CSS的Flexbox佈局實現菜單中虛線分割效果的居中對齊?如何利用CSS的Flexbox佈局實現菜單中虛線分割效果的居中對齊?Apr 05, 2025 pm 01:24 PM

如何設計菜單中的虛線分割效果?在設計菜單時,菜名和價格的左右對齊通常不難實現,但中間的虛線或點如何...

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境