canvas入門筆記

来源:https://www.cnblogs.com/unclefang/archive/2019/02/20/10408011.html
-Advertisement-
Play Games

使用canvas可以在html5製作出各種絢麗的圖表、動畫,是製作微信/H5小游戲的基礎。 canvas的數學計算公式 坐標系 在數學中坐標系是一個十字形的,原點在中間。而在canvas中原點在畫布的左上角。 常用的三角函數 三角函數是初中數學開始學習的知識,但我已經忘記的差不多了,因此這裡就多詳細 ...


使用canvas可以在html5製作出各種絢麗的圖表、動畫,是製作微信/H5小游戲的基礎。

canvas的數學計算公式

坐標系

在數學中坐標系是一個十字形的,原點在中間。而在canvas中原點在畫布的左上角。

常用的三角函數

三角函數是初中數學開始學習的知識,但我已經忘記的差不多了,因此這裡就多詳細整理一下。

  1. sin(α) = y/c

  2. cos(α) = x/c

  3. tan(α) = y/x

常用的反三角函數

  1. sin(α) = y/c => α = arcsin(y/c)

  2. cos(α) = x/c => α = arccos(c/c)

  3. tan(α) = y/x => α = arctan(y/x)

getContext()

getContext() 方法返回canvas上下文環境,可以在創建渲染上下文的時候設置多個屬性:

// 二維渲染
canvas.getContext("2d")

// 三維渲染(OpenGL ES 2.0)
canvas.getContext("webgl")

// 三維渲染(OpenGL ES 3.0)
canvas.getContext("webg2")

// 提供功能去替換指定 canvas 的ImageBitmap內容
canvas.getContext("bitmaprenderer")

通常情況下,我們使用 canvas.getContext("2d"), 即:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
console.log(ctx); // CanvasRenderingContext2D { ... }

圖形繪製API

移動筆觸

moveTo(x, y) 將筆觸移動到指定的坐標x以及y上。

路徑

beginPath()
新建一條路徑,生成之後,圖形繪製命令被指向到路徑上生成路徑。

closePath()
閉合路徑之後圖形繪製命令又重新指向到上下文中。

stroke()
通過線條來繪製圖形輪廓。

fill()
通過填充路徑的內容區域生成實心的圖形。調用fill時,會自動閉合路徑。

clip()
將當前正在構建的路徑轉換為當前的裁剪路徑。

lineTo(x, y) 繪製一條從當前位置到指定x以及y位置的直線。如果沒有 moveTo 那麼第一次 lineTo 的效果等於 moveTo。

線型

lineWidth = value 設置線條寬度。

lineCap = type 設置線條末端樣式。

lineJoin = type 設定線條與線條間接合處的樣式。

miterLimit = value 限制當兩條線相交時交接處最大長度;所謂交接處長度(斜接長度)是指線條交接處內角頂點到外角頂點的長度。

getLineDash() 返回一個包含當前虛線樣式,長度為非負偶數的數組。

setLineDash(segments) 設置當前虛線樣式。

lineDashOffset = value 設置虛線樣式的起始偏移量。

矩形

fillRect(x, y, width, height) 繪製一個填充的矩形

strokeRect(x, y, width, height) 繪製一個矩形的邊框

clearRect(x, y, width, height) 清除指定矩形區域,讓清除部分完全透明。

rect(x, y, width, height) 將一個矩形路徑增加到當前路徑上

實心圓

arc(x, y, radius, startAngle, endAngle, anticlockwise) 畫一個以(x,y)為圓心的以radius為半徑的圓弧(圓),從startAngle開始到endAngle結束,按照anticlockwise給定的方向(預設為順時針)來生成。

圓弧

arcTo(x1, y1, x2, y2, radius) 根據給定的控制點和半徑畫一段圓弧,再以直線連接兩個控制點。

註意:

  1. arc()函數中表示角的單位是弧度,不是角度。角度與弧度的js表達式: 弧度=(Math.PI/180)*角度

  2. arc()函數如果不閉合路徑並且不填充顏色,那麼將顯示為圓弧。

二次貝塞爾曲線及三次貝塞爾曲線

quadraticCurveTo(cp1x, cp1y, x, y) 繪製二次貝塞爾曲線,cp1x,cp1y為一個控制點,x,y為結束點。

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) 繪製三次貝塞爾曲線,cp1x,cp1y為控制點一,cp2x,cp2y為控制點二,x,y為結束點。

顏色

設置填充顏色

// 這些 fillStyle 的值均為 '橙色'
ctx.fillStyle = "orange";
ctx.fillStyle = "#FFA500";
ctx.fillStyle = "rgb(255,165,0)";
ctx.fillStyle = "rgba(255,165,0,1)";

設置輪廓顏色

ctx.strokeStyle = "orange";

設置透明度值

ctx.globalAlpha = 0.2;

漸變

createLinearGradient(xStart,yStart,xEnd,yEnd).addColorStop(offset,color) 線性漸變

createRadialGradient(xStart,yStart,radiusStart,xEnd,yEnd,radiusEnd).addColorStop(offset,color) 徑向漸變

xstart:漸變開始點x坐標

ystart:漸變開始點y坐標

xEnd:漸變結束點x坐標

yEnd:漸變結束點y坐標

radiusStart:發散開始圓的半徑

radiusEnd:發散結束圓的半徑

offset:設定的顏色離漸變結束點的偏移量(0~1)

color:繪製時要使用的顏色

陰影

shadowOffsetX = float

shadowOffsetX 和 shadowOffsetY 用來設定陰影在 X 和 Y 軸的延伸距離,它們是不受變換矩陣所影響的。負值表示陰影會往上或左延伸,正值則表示會往下或右延伸,它們預設都為 0。

shadowOffsetY = float

shadowOffsetX 和 shadowOffsetY 用來設定陰影在 X 和 Y 軸的延伸距離,它們是不受變換矩陣所影響的。負值表示陰影會往上或左延伸,正值則表示會往下或右延伸,它們預設都為 0。

shadowBlur = float

shadowBlur 用於設定陰影的模糊程度,其數值並不跟像素數量掛鉤,也不受變換矩陣的影響,預設為 0。

shadowColor = color

shadowColor 是標準的 CSS 顏色值,用於設定陰影顏色效果,預設是全透明的黑色。

填充規則

// 參數: nonzero | evenodd
ctx.fill("evenodd")

“nonzero”是非零環繞原則,也是預設值,“evenodd”為奇偶原則。

通常在填充相交或嵌套路徑時使用。

文本

fillText(text, x, y [, maxWidth])
在指定的(x,y)位置填充指定的文本,繪製的最大寬度是可選的.

strokeText(text, x, y [, maxWidth])
在指定的(x,y)位置繪製文本邊框,繪製的最大寬度是可選的.

文本樣式

font = value
當前我們用來繪製文本的樣式. 這個字元串使用和 CSS font 屬性相同的語法. 預設的字體是 10px sans-serif。

textAlign = value
文本對齊選項. 可選的值包括:start, end, left, right or center. 預設值是 start。

textBaseline = value
基線對齊選項. 可選的值包括:top, hanging, middle, alphabetic, ideographic, bottom。預設值是 alphabetic。

direction = value
文本方向。可能的值包括:ltr, rtl, inherit。預設值是 inherit。

預測量文本寬度

var text = ctx.measureText("foo");
text.width; // 16;

圖片操作

嵌入圖片的操作

// 1. new image()
var img = new Image();   // 創建img元素
img.onload = function(){
  // 執行drawImage語句
}
img.src = 'myImage.png'; // 設置圖片源地址

// 2. data: url
img.src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';

drawImage(image, x, y, width, height,x2, y2, width2, height2)
其中 image 是 image 或者 canvas 對象;x 和 y 是其在目標 canvas 里的起始坐標;width 和 height,這兩個參數用來控制 當向canvas畫入時應該縮放的大小;x2/y2/width2/height2定義切片的目標顯示位置和大小。

Path2D對象

Path2D對象可以把svg等內容畫在canvas上。

new Path2D();     // 空的Path對象
new Path2D(path); // 克隆Path對象
new Path2D(d);    // 從SVG建立Path對象
var p = new Path2D("M10 10 h 80 v 80 h -80 Z"); // 使用svg路徑

圖案樣式

var img = new Image();
img.src = 'someimage.png';
var ptrn = ctx.createPattern(img,'repeat');

註意:

與 drawImage 有點不同,你需要確認 image 對象已經裝載完畢,否則圖案可能效果不對的。

狀態的保存和恢復

save()restore()
save 和 restore 方法是用來保存和恢復 canvas 狀態的,都沒有參數。Canvas 的狀態就是當前畫面應用的所有樣式和變形的一個快照。

移動原點和canvas位置

translate(x, y)
translate 方法接受兩個參數。x 是左右偏移量,y 是上下偏移量,如右圖所示。

旋轉

rotate(angle)
這個方法只接受一個參數:旋轉的角度(angle),它是順時針方向的,以弧度為單位的值。

縮放

scale(x, y)
scale 方法接受兩個參數。x,y 分別是橫軸和縱軸的縮放因數,它們都必須是正值。值比 1.0 小表示縮小,比 1.0

變形

transform(m11, m12, m21, m22, dx, dy)

m11:水平方向的縮放

m12:水平方向的傾斜偏移

m21:豎直方向的傾斜偏移

m22:豎直方向的縮放

dx:水平方向的移動

dy:豎直方向的移動

// 將當前的變形矩陣重置為單位矩陣
setTransform(m11, m12, m21, m22, dx, dy) 

// 重置當前變形為單位矩陣
resetTransform()

組合

globalCompositeOperation = type
這個屬性設定了在畫新圖形時採用的遮蓋策略,其值是一個標識遮蓋方式的字元串。

  1. source-over
    這是預設設置,併在現有畫布上下文之上繪製新圖形。

  2. source-in
    新圖形只在新圖形和目標畫布重疊的地方繪製。其他的都是透明的。

  3. source-out
    在不與現有畫布內容重疊的地方繪製新圖形

  4. source-atop
    新圖形只在與現有畫布內容重疊的地方繪製。

  5. destination-over
    在現有的畫布內容後面繪製新的圖形。

  6. destination-in
    現有的畫布內容保持在新圖形和現有畫布內容重疊的位置。其他的都是透明的。

  7. destination-out
    現有內容保持在新圖形不重疊的地方。

  8. destination-atop
    現有的畫布只保留與新圖形重疊的部分,新的圖形是在畫布內容後面繪製的。

  9. lighter
    兩個重疊圖形的顏色是通過顏色值相加來確定的。

  10. copy
    只顯示新圖形。

  11. xor
    圖像中,那些重疊和正常繪製之外的其他地方是透明的。

  12. multiply
    將頂層像素與底層相應像素相乘,結果是一幅更黑暗的圖片。

  13. screen
    像素被倒轉,相乘,再倒轉,結果是一幅更明亮的圖片。

  14. overlay
    multiply和screen的結合,原本暗的地方更暗,原本亮的地方更亮。

  15. darken
    保留兩個圖層中最暗的像素。

  16. lighten
    保留兩個圖層中最亮的像素。

  17. color-dodge
    將底層除以頂層的反置。

  18. color-burn
    將反置的底層除以頂層,然後將結果反過來。

  19. hard-light
    屏幕相乘(A combination of multiply and screen)類似於疊加,但上下圖層互換了。

  20. soft-light
    用頂層減去底層或者相反來得到一個正值。

  21. difference
    一個柔和版本的強光(hard-light)。純黑或純白不會導致純黑或純白。

  22. exclusion
    和difference相似,但對比度較低。

  23. hue
    保留了底層的亮度(luma)和色度(chroma),同時採用了頂層的色調(hue)。

  24. saturation
    保留底層的亮度(luma)和色調(hue),同時採用頂層的色度(chroma)。

  25. color
    保留了底層的亮度(luma),同時採用了頂層的色調(hue)和色度(chroma)。

  26. luminosity
    保持底層的色調(hue)和色度(chroma),同時採用頂層的亮度(luma)。

動畫

canvas動畫通過重繪出每一幀畫面,達到連續的動畫效果,重繪是相當費時的,而且性能很依賴於電腦的速度。

動畫的基本步驟

  1. 清空 canvas

除非接下來要畫的內容會完全充滿 canvas (例如背景圖),否則你需要清空所有。最簡單的做法就是用 clearRect 方法。

  1. 保存 canvas 狀態

如果你要改變一些會改變 canvas 狀態的設置(樣式,變形之類的),又要在每畫一幀之時都是原始狀態的話,你需要先保存一下。

  1. 繪製動畫圖形(animated shapes)

這一步才是重繪動畫幀。

  1. 恢復 canvas 狀態

如果已經保存了 canvas 的狀態,可以先恢復它,然後重繪下一幀。

更新畫布

window.setInterval(function, delay)
當設定好間隔時間後,function會定期執行。

window.setTimeout(function, delay)
在設定好的時間之後執行函數

window.requestAnimationFrame(callback)
告訴瀏覽器你希望執行一個動畫,併在重繪之前,請求瀏覽器執行一個特定的函數來更新動畫。

ImageData對象

ImageData對象中存儲著canvas對象真實的像素數據,它包含以下幾個只讀屬性:

width
圖片寬度,單位是像素

height
圖片高度,單位是像素

data
Uint8ClampedArray類型的一維數組,包含著RGBA格式的整型數據,範圍在0至255之間(包括255)。

性能優化

offscreenCanvas 離屏畫布

當有許多相似圖形或重覆圖像時使用,比如說需要同一個圖像的不同尺寸

myEntity.offscreenCanvas = document.createElement("canvas");
myEntity.offscreenCanvas.width = myEntity.width;
myEntity.offscreenCanvas.height = myEntity.height;
myEntity.offscreenContext = myEntity.offscreenCanvas.getContext("2d");

myEntity.render(myEntity.offscreenContext);

用整數坐標代替浮點數坐標

ctx.drawImage(myImage, 0.3, 0.5); // no

使用Math.floor()對所有坐標取整

let x = Math.floor(0.3);
let y = Math.floor(0.5);
ctx.drawImage(myImage, x, y);

使用多層畫布去畫一個複雜的場景

用多個畫布元素去創建不同層次。

用CSS設置大的背景圖

可以用div把canvas包裹起來,然後用css設置div的背景圖片。

用CSS transforms特性縮放畫布

CSS transforms 特性由於調用GPU,因此更快捷。不要將小畫布放大,而是去將大畫布縮小。

關閉透明度

如果不需要透明度,可以在聲明渲染的時候先關閉它。

var ctx = canvas.getContext('2d', { alpha: false });

其他的一些優化小技巧

  1. 將畫布的函數調用集合到一起(例如,畫一條折線,而不要畫多條分開的直線)

  2. 避免不必要的畫布狀態改變

  3. 渲染畫布中的不同點,而非整個新狀態

  4. 儘可能避免 shadowBlur特性

  5. 儘可能避免text rendering

  6. 使用不同的辦法去清除畫布(clearRect() vs. fillRect() vs. 調整canvas大小)

  7. 有動畫,請使用window.requestAnimationFrame() 而非window.setInterval()

  8. 請謹慎使用大型物理庫


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 相信我,這不是一篇吐槽文章。。。。 基礎控制項 Android的控制項和控制項樣式非常特別,它是一種內聯特別高的設計模式,換句話說,它是非常爛的設計。。。。 但在這種特別的關係里還是有一定的規律的,下麵我們一起來看看控制項的使用方式。 首先我們定義一個ImageButton,如下: 如上代碼所示,我們定義了 ...
  • 1. 什麼是記憶體管理 程式在運行的過程中通常通過以下行為,來增加程式的的記憶體占用 創建一個OC對象 定義一個變數 調用一個函數或者方法 而一個移動設備的記憶體是有限的,每個軟體所能占用的記憶體也是有限的 當程式所占用的記憶體較多時,系統就會發出記憶體警告,這時就得回收一些不需要再使用的記憶體空間。比如回收一些 ...
  • 1、charAt() 獲取字元串指定位置的字元 用法:strObj是字元串對象,index是指定的位置,(位置從0開始數) 2、 indexOf() 方法可返回某個指定的字元串值在字元串中首次出現的位置 用法:stringObject是字元串對象,searchvalue是指定的字元串值,fromin ...
  • Web前端JQuery面試題(一) 一:選擇器 基本選擇器 1. 什麼是 ,`element .class `, ? 答: 根據給定的 匹配一個元素,用於搜索,通過 的屬性給定值。 案例:查找 為`da3`的元素 根據給定的元素名匹配所有元素 案例,查找 元素: 根據給定的類匹配元素 匹配所有元素 ...
  • Arcade表達式是輕量級的腳本語言,我們可以通過全局變數$feature獲取要素屬性。比如說,要為城市添加標簽,利用CITY_NAME列,我們可以編寫語句:$feature.CITY_NAME。Arcade語句可以利用表達式來執行數學運算,邏輯運算。 首先來看下,這次需要展現的要素圖層是: 我們用 ...
  • TCP/IP是互聯網相關的各類協議族的總稱,HTTP屬於它內部的一個子集。 一、TCP/TP的分層管理 1. 應用層 應用層決定了向用戶提供應用服務時通信的活動。TCP/IP 協議族內預存了各類通用的應用服務,比如,FTP(File Transfer Protocol,文件傳輸協議)和 DNS(Do ...
  • 1.傳遞 基本數據類型中,傳遞的是值 引用數據類型中,傳遞的是在堆中的地址 基本數據類型中,傳遞的是值 引用數據類型中,傳遞的是在堆中的地址 基本數據類型:改變複製的值,不影響原值 引用數據類型:改變複製的值,會影響原值(淺複製) 引用數據類型:改變複製的值,不影響原值(深複製) for迴圈拷貝數組 ...
  • 本文由雲+社區發表 作者:Dan Abramov 接觸 "React Hooks" 一定時間的你,也許會碰到一個神奇的問題: "用起來沒你想的簡單" 。 Ryan Florence 在 "他的推文" 裡面說到: 不少朋友跟我提起,setInterval 和 hooks 一起用的時候,有種蛋蛋的憂傷。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...