日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > HTML >内容正文

HTML

HTML5 Canvas

發(fā)布時(shí)間:2025/3/15 HTML 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HTML5 Canvas 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

HTML5 Canvas

轉(zhuǎn)自:https://blog.csdn.net/u012468376/article/details/73350998

一、canvas簡(jiǎn)介

??  <canvas>?是?HTML5?新增的,一個(gè)可以使用腳本(通常為JavaScript)在其中繪制圖像的?HTML?元素。它可以用來(lái)制作照片集或者制作簡(jiǎn)單(也不是那么簡(jiǎn)單)的動(dòng)畫(huà),甚至可以進(jìn)行實(shí)時(shí)視頻處理和渲染。

?   它最初由蘋(píng)果內(nèi)部使用自己MacOS X WebKit推出,供應(yīng)用程序使用像儀表盤(pán)的構(gòu)件和?Safari?瀏覽器使用。 后來(lái),有人通過(guò)Gecko內(nèi)核的瀏覽器 (尤其是Mozilla和Firefox),Opera和Chrome和超文本網(wǎng)絡(luò)應(yīng)用技術(shù)工作組建議為下一代的網(wǎng)絡(luò)技術(shù)使用該元素。

??  Canvas是由HTML代碼配合高度和寬度屬性而定義出的可繪制區(qū)域。JavaScript代碼可以訪(fǎng)問(wèn)該區(qū)域,類(lèi)似于其他通用的二維API,通過(guò)一套完整的繪圖函數(shù)來(lái)動(dòng)態(tài)生成圖形。

?   Mozilla 程序從 Gecko 1.8 (Firefox 1.5)開(kāi)始支持?<canvas>, Internet Explorer 從IE9開(kāi)始<canvas>?。Chrome和Opera 9+ 也支持?<canvas>。

二、Canvas基本使用

2.1?<canvas>元素

<canvas id="tutorial" width="300" height="300"></canvas>
<canvas>看起來(lái)和<img>標(biāo)簽一樣,只是?<canvas>?只有兩個(gè)可選的屬性?width、heigth?屬性,而沒(méi)有?src、alt?屬性。

? 如果不給<canvas>設(shè)置widht、height屬性時(shí),則默認(rèn)?width為300、height為150,單位都是px。也可以使用css屬性來(lái)設(shè)置寬高,但是如寬高屬性和初始比例不一致,他會(huì)出現(xiàn)扭曲。所以,建議永遠(yuǎn)不要使用css屬性來(lái)設(shè)置<canvas>的寬高。

替換內(nèi)容

? 由于某些較老的瀏覽器(尤其是IE9之前的IE瀏覽器)或者瀏覽器不支持HTML元素<canvas>,在這些瀏覽器上你應(yīng)該總是能展示替代內(nèi)容。

? 支持<canvas>的瀏覽器會(huì)只渲染<canvas>標(biāo)簽,而忽略其中的替代內(nèi)容。不支持?<canvas>?的瀏覽器則 會(huì)直接渲染替代內(nèi)容。

文本替換:

<canvas>你的瀏覽器不支持canvas,請(qǐng)升級(jí)你的瀏覽器 </canvas>

用?<img>?替換::

<canvas><img src="./美女.jpg" alt=""> </canvas>

?

結(jié)束標(biāo)簽</canvas>不可省

與?<img>元素不同,<canvas>元素需要結(jié)束標(biāo)簽(</canvas>)。如果結(jié)束標(biāo)簽不存在,則文檔的其余部分會(huì)被認(rèn)為是替代內(nèi)容,將不會(huì)顯示出來(lái)。

2.2 渲染上下文(Thre Rending Context)

??<canvas>會(huì)創(chuàng)建一個(gè)固定大小的畫(huà)布,會(huì)公開(kāi)一個(gè)或多個(gè)?渲染上下文(畫(huà)筆),使用?渲染上下文來(lái)繪制和處理要展示的內(nèi)容。

? 我們重點(diǎn)研究 2D渲染上下文。 其他的上下文我們暫不研究,比如, WebGL使用了基于OpenGL ES的3D上下文 (“experimental-webgl”) 。

var canvas = document.getElementById('tutorial'); //獲得 2d 上下文對(duì)象 var ctx = canvas.getContext('2d');

?

2.3 檢測(cè)支持性

var canvas = document.getElementById('tutorial');if (canvas.getContext){var ctx = canvas.getContext('2d');// drawing code here } else {// canvas-unsupported code here }

?

2.4 代碼模板

<html> <head><title>Canvas tutorial</title><style type="text/css">canvas {border: 1px solid black;}</style> </head> <canvas id="tutorial" width="300" height="300"></canvas> </body> <script type="text/javascript">function draw(){var canvas = document.getElementById('tutorial');if(!canvas.getContext) return;var ctx = canvas.getContext("2d");//開(kāi)始代碼 }draw(); </script> </html>

?

2.5 一個(gè)簡(jiǎn)單的例子

繪制兩個(gè)長(zhǎng)方形:

<html> <head><title>Canvas tutorial</title><style type="text/css">canvas {border: 1px solid black;}</style> </head> <canvas id="tutorial" width="300" height="300"></canvas> </body> <script type="text/javascript">function draw(){var canvas = document.getElementById('tutorial');if(!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.fillStyle = "rgb(200,0,0)";//繪制矩形 ctx.fillRect (10, 10, 55, 50);ctx.fillStyle = "rgba(0, 0, 200, 0.5)";ctx.fillRect (30, 30, 55, 50);}draw(); </script> </html>

?

三、繪制形狀

3.1 柵格(grid)和坐標(biāo)空間

? 如下圖所示,canvas元素默認(rèn)被網(wǎng)格所覆蓋。通常來(lái)說(shuō)網(wǎng)格中的一個(gè)單元相當(dāng)于canvas元素中的一像素。柵格的起點(diǎn)為左上角(坐標(biāo)為(0,0))。所有元素的位置都相對(duì)于原點(diǎn)來(lái)定位。所以圖中藍(lán)色方形左上角的坐標(biāo)為距離左邊(X軸)x像素,距離上邊(Y軸)y像素(坐標(biāo)為(x,y))。

? 后面我們會(huì)涉及到坐標(biāo)原點(diǎn)的平移、網(wǎng)格的旋轉(zhuǎn)以及縮放等。

3.2 繪制矩形

??<canvas>?只支持一種原生的 圖形繪制:矩形。所有其他圖形都至少需要生成一種路徑(path)。不過(guò),我們擁有眾多路徑生成的方法讓復(fù)雜圖形的繪制成為了可能。

canvast 提供了三種方法繪制矩形:

  • fillRect(x, y, width, height)

    繪制一個(gè)填充的矩形

  • strockRect(x, y, width, height)

    繪制一個(gè)矩形的邊框

  • clearRect(x, y, widh, height)

    清除指定的矩形區(qū)域,然后這塊區(qū)域會(huì)變的完全透明。

  • 說(shuō)明:

    ? 這3個(gè)方法具有相同的參數(shù)。

    ??x, y:指的是矩形的左上角的坐標(biāo)。(相對(duì)于canvas的坐標(biāo)原點(diǎn))

    ??width, height:指的是繪制的矩形的寬和高。

    function draw(){var canvas = document.getElementById('tutorial');if(!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.fillRect(10, 10, 100, 50); //繪制矩形,填充的默認(rèn)顏色為黑色ctx.strokeRect(10, 70, 100, 50); //繪制矩形邊框 } draw();

    ?

    ctx.clearRect(15, 15, 50, 25);

    四、繪制路徑(path)

    ? 圖形的基本元素是路徑。

    ? 路徑是通過(guò)不同顏色和寬度的線(xiàn)段或曲線(xiàn)相連形成的不同形狀的點(diǎn)的集合。

    ? 一個(gè)路徑,甚至一個(gè)子路徑,都是閉合的。

    使用路徑繪制圖形需要一些額外的步驟:

  • 創(chuàng)建路徑起始點(diǎn)
  • 調(diào)用繪制方法去繪制出路徑
  • 把路徑封閉
  • 一旦路徑生成,通過(guò)描邊或填充路徑區(qū)域來(lái)渲染圖形。
  • 下面是需要用到的方法:

  • beginPath()

    新建一條路徑,路徑一旦創(chuàng)建成功,圖形繪制命令被指向到路徑上生成路徑

  • moveTo(x, y)

    把畫(huà)筆移動(dòng)到指定的坐標(biāo)(x, y)。相當(dāng)于設(shè)置路徑的起始點(diǎn)坐標(biāo)。

  • closePath()

    閉合路徑之后,圖形繪制命令又重新指向到上下文中

  • stroke()

    通過(guò)線(xiàn)條來(lái)繪制圖形輪廓

  • fill()

    通過(guò)填充路徑的內(nèi)容區(qū)域生成實(shí)心的圖形

  • 4.1 繪制線(xiàn)段

    function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.beginPath(); //新建一條pathctx.moveTo(50, 50); //把畫(huà)筆移動(dòng)到指定的坐標(biāo)ctx.lineTo(200, 50); //繪制一條從當(dāng)前位置到指定坐標(biāo)(200, 50)的直線(xiàn).//閉合路徑。會(huì)拉一條從當(dāng)前點(diǎn)到path起始點(diǎn)的直線(xiàn)。如果當(dāng)前點(diǎn)與起始點(diǎn)重合,則什么都不做 ctx.closePath();ctx.stroke(); //繪制路徑。 } draw();

    ?

    ?

    4.2 繪制三角形邊框

    function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.beginPath();ctx.moveTo(50, 50);ctx.lineTo(200, 50);ctx.lineTo(200, 200);ctx.closePath(); //雖然我們只繪制了兩條線(xiàn)段,但是closePath會(huì)closePath,仍然是一個(gè)3角形ctx.stroke(); //描邊。stroke不會(huì)自動(dòng)closePath() } draw();

    ?

    ?

    4.3 填充三角形

    function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.beginPath();ctx.moveTo(50, 50);ctx.lineTo(200, 50);ctx.lineTo(200, 200);ctx.fill(); //填充閉合區(qū)域。如果path沒(méi)有閉合,則fill()會(huì)自動(dòng)閉合路徑。 } draw();

    ?

    ?

    4.4 繪制圓弧

    有兩個(gè)方法可以繪制圓弧:

  • arc(x, y, r, startAngle, endAngle, anticlockwise):

    以(x, y)為圓心,以r為半徑,從?startAngle弧度開(kāi)始到endAngle弧度結(jié)束。anticlosewise是布爾值,true表示逆時(shí)針,false表示順時(shí)針。(默認(rèn)是順時(shí)針)

    注意:

  • 這里的度數(shù)都是弧度。
  • 0弧度是指的x軸正方形
  • radians=(Math.PI/180)*degrees //角度轉(zhuǎn)換成弧度
    • 1
  • arcTo(x1, y1, x2, y2, radius):

    根據(jù)給定的控制點(diǎn)和半徑畫(huà)一段圓弧,最后再以直線(xiàn)連接兩個(gè)控制點(diǎn)。

  • 圓弧案例1:

    function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.beginPath();ctx.arc(50, 50, 40, 0, Math.PI / 2, false);ctx.stroke(); } draw();

    ?

    ?

    圓弧案例2:

    function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.beginPath();ctx.arc(50, 50, 40, 0, Math.PI / 2, false);ctx.stroke();ctx.beginPath();ctx.arc(150, 50, 40, 0, -Math.PI / 2, true);ctx.closePath();ctx.stroke();ctx.beginPath();ctx.arc(50, 150, 40, -Math.PI / 2, Math.PI / 2, false);ctx.fill();ctx.beginPath();ctx.arc(150, 150, 40, 0, Math.PI, false);ctx.fill();} draw();

    ?

    ?

    圓弧案例3:

    function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.beginPath();ctx.moveTo(50, 50);//參數(shù)1、2:控制點(diǎn)1坐標(biāo) 參數(shù)3、4:控制點(diǎn)2坐標(biāo) 參數(shù)4:圓弧半徑ctx.arcTo(200, 50, 200, 200, 100);ctx.lineTo(200, 200)ctx.stroke();ctx.beginPath();ctx.rect(50, 50, 10, 10);ctx.rect(200, 50, 10, 10)ctx.rect(200, 200, 10, 10)ctx.fill() } draw();

    ?

    ?

    arcTo方法的說(shuō)明:

    ? 這個(gè)方法可以這樣理解。繪制的弧形是由兩條切線(xiàn)所決定。

    ? 第 1 條切線(xiàn):起始點(diǎn)和控制點(diǎn)1決定的直線(xiàn)。

    ? 第 2 條切線(xiàn):控制點(diǎn)1 和控制點(diǎn)2決定的直線(xiàn)。

    ??其實(shí)繪制的圓弧就是與這兩條直線(xiàn)相切的圓弧。

    4.5 繪制貝塞爾曲線(xiàn)

    4.5.1 什么是貝塞爾曲線(xiàn)

    ? 貝塞爾曲線(xiàn)(Bézier curve),又稱(chēng)貝茲曲線(xiàn)或貝濟(jì)埃曲線(xiàn),是應(yīng)用于二維圖形應(yīng)用程序的數(shù)學(xué)曲線(xiàn)。

    ? 一般的矢量圖形軟件通過(guò)它來(lái)精確畫(huà)出曲線(xiàn),貝茲曲線(xiàn)由線(xiàn)段與節(jié)點(diǎn)組成,節(jié)點(diǎn)是可拖動(dòng)的支點(diǎn),線(xiàn)段像可伸縮的皮筋,我們?cè)诶L圖工具上看到的鋼筆工具就是來(lái)做這種矢量曲線(xiàn)的。

    ? 貝塞爾曲線(xiàn)是計(jì)算機(jī)圖形學(xué)中相當(dāng)重要的參數(shù)曲線(xiàn),在一些比較成熟的位圖軟件中也有貝塞爾曲線(xiàn)工具如PhotoShop等。在Flash4中還沒(méi)有完整的曲線(xiàn)工具,而在Flash5里面已經(jīng)提供出貝塞爾曲線(xiàn)工具。

    ? 貝塞爾曲線(xiàn)于1962,由法國(guó)工程師皮埃爾·貝塞爾(Pierre Bézier)所廣泛發(fā)表,他運(yùn)用貝塞爾曲線(xiàn)來(lái)為汽車(chē)的主體進(jìn)行設(shè)計(jì)。貝塞爾曲線(xiàn)最初由Paul de Casteljau于1959年運(yùn)用de Casteljau演算法開(kāi)發(fā),以穩(wěn)定數(shù)值的方法求出貝茲曲線(xiàn)。

    一次貝塞爾曲線(xiàn)(線(xiàn)性貝塞爾曲線(xiàn))

    ? 一次貝塞爾曲線(xiàn)其實(shí)是一條直線(xiàn)。

    二次貝塞爾曲線(xiàn)

    三次貝塞爾曲線(xiàn)

    4.5.2 繪制貝塞爾曲線(xiàn)

    繪制二次貝塞爾曲線(xiàn)

    quadraticCurveTo(cp1x, cp1y, x, y):

    說(shuō)明:

    ? 參數(shù)1和2:控制點(diǎn)坐標(biāo)

    ? 參數(shù)3和4:結(jié)束點(diǎn)坐標(biāo)

    function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.beginPath();ctx.moveTo(10, 200); //起始點(diǎn)var cp1x = 40, cp1y = 100; //控制點(diǎn)var x = 200, y = 200; // 結(jié)束點(diǎn)//繪制二次貝塞爾曲線(xiàn) ctx.quadraticCurveTo(cp1x, cp1y, x, y);ctx.stroke();ctx.beginPath();ctx.rect(10, 200, 10, 10);ctx.rect(cp1x, cp1y, 10, 10);ctx.rect(x, y, 10, 10);ctx.fill();} draw();

    ?

    ?

    繪制三次貝塞爾曲線(xiàn)

    bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y):

    說(shuō)明:

    ? 參數(shù)1和2:控制點(diǎn)1的坐標(biāo)

    ? 參數(shù)3和4:控制點(diǎn)2的坐標(biāo)

    ? 參數(shù)5和6:結(jié)束點(diǎn)的坐標(biāo)

    function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.beginPath();ctx.moveTo(40, 200); //起始點(diǎn)var cp1x = 20, cp1y = 100; //控制點(diǎn)1var cp2x = 100, cp2y = 120; //控制點(diǎn)2var x = 200, y = 200; // 結(jié)束點(diǎn)//繪制二次貝塞爾曲線(xiàn) ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);ctx.stroke();ctx.beginPath();ctx.rect(40, 200, 10, 10);ctx.rect(cp1x, cp1y, 10, 10);ctx.rect(cp2x, cp2y, 10, 10);ctx.rect(x, y, 10, 10);ctx.fill();} draw();

    ?

    ?

    五、添加樣式和顏色

    ? 在前面的繪制矩形章節(jié)中,只用到了默認(rèn)的線(xiàn)條和顏色。

    ? 如果想要給圖形上色,有兩個(gè)重要的屬性可以做到。

  • fillStyle = color

    設(shè)置圖形的填充顏色

  • strokeStyle = color

    設(shè)置圖形輪廓的顏色

  • 備注:

    1. `color` 可以是表示 `css` 顏色值的字符串、漸變對(duì)象或者圖案對(duì)象。 2. 默認(rèn)情況下,線(xiàn)條和填充顏色都是黑色。 3. 一旦您設(shè)置了 `strokeStyle` 或者 `fillStyle` 的值,那么這個(gè)新值就會(huì)成為新繪制的圖形的默認(rèn)值。如果你要給每個(gè)圖形上不同的顏色,你需要重新設(shè)置 `fillStyle` 或 `strokeStyle` 的值。

    ?

    fillStyle

    function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");for (var i = 0; i < 6; i++){for (var j = 0; j < 6; j++){ctx.fillStyle = 'rgb(' + Math.floor(255 - 42.5 * i) + ',' +Math.floor(255 - 42.5 * j) + ',0)';ctx.fillRect(j * 50, i * 50, 50, 50);}} } draw();

    ?

    strokeStyle

    <script type="text/javascript">function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");for (var i = 0; i < 6; i++){for (var j = 0; j < 6; j++){ctx.strokeStyle = `rgb(${randomInt(0, 255)},${randomInt(0, 255)},${randomInt(0, 255)})`;ctx.strokeRect(j * 50, i * 50, 40, 40);}}}draw();/*** 返回隨機(jī)的 [from, to] 之間的整數(shù)(包括from,也包括to)*/function randomInt(from, to){return parseInt(Math.random() * (to - from + 1) + from);}</script>

    ?

    ?

    Transparency(透明度)

    globalAlpha = transparencyValue

    ? 這個(gè)屬性影響到 canvas 里所有圖形的透明度,有效的值范圍是 0.0 (完全透明)到 1.0(完全不透明),默認(rèn)是 1.0。

    ??globalAlpha?屬性在需要繪制大量擁有相同透明度的圖形時(shí)候相當(dāng)高效。不過(guò),我認(rèn)為使用rgba()設(shè)置透明度更加好一些。

    line style

    1.?lineWidth = value

    線(xiàn)寬。只能是正值。默認(rèn)是1.0。

    起始點(diǎn)和終點(diǎn)的連線(xiàn)為中心,上下各占線(xiàn)寬的一半

    “`javascript?
    ctx.beginPath();?
    ctx.moveTo(10, 10);?
    ctx.lineTo(100, 10);?
    ctx.lineWidth = 10;?
    ctx.stroke();

    ctx.beginPath();?
    ctx.moveTo(110, 10);?
    ctx.lineTo(160, 10)?
    ctx.lineWidth = 20;?
    ctx.stroke()?
    “`

    2.?lineCap = type

    線(xiàn)條末端樣式。

    共有3個(gè)值:

  • butt:線(xiàn)段末端以方形結(jié)束
  • round:線(xiàn)段末端以圓形結(jié)束
  • square:線(xiàn)段末端以方形結(jié)束,但是增加了一個(gè)寬度和線(xiàn)段相同,高度是線(xiàn)段厚度一半的矩形區(qū)域。

    var lineCaps = ["butt", "round", "square"];for (var i = 0; i < 3; i++){ctx.beginPath();ctx.moveTo(20 + 30 * i, 30);ctx.lineTo(20 + 30 * i, 100);ctx.lineWidth = 20;ctx.lineCap = lineCaps[i];ctx.stroke(); }ctx.beginPath(); ctx.moveTo(0, 30); ctx.lineTo(300, 30);ctx.moveTo(0, 100); ctx.lineTo(300, 100)ctx.strokeStyle = "red"; ctx.lineWidth = 1; ctx.stroke();

    ?

  • 3.?lineJoin = type

    同一個(gè)path內(nèi),設(shè)定線(xiàn)條與線(xiàn)條間接合處的樣式。

    共有3個(gè)值round,?bevel?和?miter:

  • round

    通過(guò)填充一個(gè)額外的,圓心在相連部分末端的扇形,繪制拐角的形狀。 圓角的半徑是線(xiàn)段的寬度。

  • bevel

    在相連部分的末端填充一個(gè)額外的以三角形為底的區(qū)域, 每個(gè)部分都有各自獨(dú)立的矩形拐角。

  • miter(默認(rèn))

    通過(guò)延伸相連部分的外邊緣,使其相交于一點(diǎn),形成一個(gè)額外的菱形區(qū)域。

  • function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");var lineJoin = ['round', 'bevel', 'miter'];ctx.lineWidth = 20;for (var i = 0; i < lineJoin.length; i++){ctx.lineJoin = lineJoin[i];ctx.beginPath();ctx.moveTo(50, 50 + i * 50);ctx.lineTo(100, 100 + i * 50);ctx.lineTo(150, 50 + i * 50);ctx.lineTo(200, 100 + i * 50);ctx.lineTo(250, 50 + i * 50);ctx.stroke();}} draw();

    ?

    ?

    4. 虛線(xiàn)

    用?setLineDash?方法和?lineDashOffset?屬性來(lái)制定虛線(xiàn)樣式.?setLineDash?方法接受一個(gè)數(shù)組,來(lái)指定線(xiàn)段與間隙的交替;lineDashOffset屬性設(shè)置起始偏移量.

    function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.setLineDash([20, 5]); // [實(shí)線(xiàn)長(zhǎng)度, 間隙長(zhǎng)度]ctx.lineDashOffset = -0;ctx.strokeRect(50, 50, 210, 210); } draw();

    ?

    ?

    備注:

    ??getLineDash():返回一個(gè)包含當(dāng)前虛線(xiàn)樣式,長(zhǎng)度為非負(fù)偶數(shù)的數(shù)組。

    六、繪制文本

    繪制文本的兩個(gè)方法

    canvas 提供了兩種方法來(lái)渲染文本:

  • fillText(text, x, y [, maxWidth])

    在指定的(x,y)位置填充指定的文本,繪制的最大寬度是可選的.

  • strokeText(text, x, y [, maxWidth])

    在指定的(x,y)位置繪制文本邊框,繪制的最大寬度是可選的.

  • var ctx; function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;ctx = canvas.getContext("2d");ctx.font = "100px sans-serif"ctx.fillText("天若有情", 10, 100);ctx.strokeText("天若有情", 10, 200) } draw();

    ?

    給文本添加樣式

  • font = value

    當(dāng)前我們用來(lái)繪制文本的樣式。這個(gè)字符串使用和?CSS font屬性相同的語(yǔ)法. 默認(rèn)的字體是?10px sans-serif。

  • textAlign = value

    文本對(duì)齊選項(xiàng). 可選的值包括:start,?end,?left,?right?or?center. 默認(rèn)值是?start。

  • textBaseline = value

    基線(xiàn)對(duì)齊選項(xiàng),可選的值包括:top,?hanging,?middle,?alphabetic,?ideographic,?bottom。默認(rèn)值是?alphabetic。

  • direction = value

    文本方向。可能的值包括:ltr,?rtl,?inherit。默認(rèn)值是?inherit。

  • 七、繪制圖片

    ? 我們也可以在canvas上直接繪制圖片。

    7.1 由零開(kāi)始創(chuàng)建圖片

    創(chuàng)建<img>元素

    var img = new Image(); // 創(chuàng)建一個(gè)<img>元素 img.src = 'myImage.png'; // 設(shè)置圖片源地址

    ?

    腳本執(zhí)行后圖片開(kāi)始裝載

    繪制img

    //參數(shù)1:要繪制的img 參數(shù)2、3:繪制的img在canvas中的坐標(biāo) ctx.drawImage(img,0,0);

    ?

    注意:

    ? 考慮到圖片是從網(wǎng)絡(luò)加載,如果?drawImage?的時(shí)候圖片還沒(méi)有完全加載完成,則什么都不做,個(gè)別瀏覽器會(huì)拋異常。所以我們應(yīng)該保證在?img?繪制完成之后再?drawImage。

    var img = new Image(); // 創(chuàng)建img元素 img.onload = function(){ctx.drawImage(img, 0, 0) } img.src = 'myImage.png'; // 設(shè)置圖片源地址

    ?

    7.2 繪制?img?標(biāo)簽元素中的圖片

    ??img?可以?new?也可以來(lái)源于我們頁(yè)面的?<img>標(biāo)簽

    <img src="./美女.jpg" alt="" width="300"><br> <canvas id="tutorial" width="600" height="400"></canvas> <script type="text/javascript">function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");var img = document.querySelector("img");ctx.drawImage(img, 0, 0);}document.querySelector("img").onclick = function (){draw();}</script>

    ?

    ?

    第一張圖片就是頁(yè)面中的<img>標(biāo)簽

    7.3 縮放圖片

    drawImage()?也可以再添加兩個(gè)參數(shù):

    ??drawImage(image, x, y, width, height)

    ? 這個(gè)方法多了2個(gè)參數(shù):width?和?height,這兩個(gè)參數(shù)用來(lái)控制 當(dāng)像canvas畫(huà)入時(shí)應(yīng)該縮放的大小。

    ctx.drawImage(img, 0, 0, 400, 200)

    ?

    7.4 切片(slice)

    drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

    ? 第一個(gè)參數(shù)和其它的是相同的,都是一個(gè)圖像或者另一個(gè) canvas 的引用。

    其他8個(gè)參數(shù):

    ? 前4個(gè)是定義圖像源的切片位置和大小,

    ? 后4個(gè)則是定義切片的目標(biāo)顯示位置和大小。

    八、狀態(tài)的保存和恢復(fù)

    Saving and restoring state是繪制復(fù)雜圖形時(shí)必不可少的操作。

    save()和restore()

    ??save?和?restore?方法是用來(lái)保存和恢復(fù)?canvas?狀態(tài)的,都沒(méi)有參數(shù)。

    ??Canvas?的狀態(tài)就是當(dāng)前畫(huà)面應(yīng)用的所有樣式和變形的一個(gè)快照。

  • 關(guān)于?save()

    Canvas狀態(tài)存儲(chǔ)在棧中,每當(dāng)save()方法被調(diào)用后,當(dāng)前的狀態(tài)就被推送到棧中保存。一個(gè)繪畫(huà)狀態(tài)包括:

    • 當(dāng)前應(yīng)用的變形(即移動(dòng),旋轉(zhuǎn)和縮放)

    • strokeStyle,?fillStyle,?globalAlpha,?lineWidth,?lineCap,?lineJoin,?miterLimit,?shadowOffsetX,?shadowOffsetY,?shadowBlur,?shadowColor,?globalCompositeOperation 的值

    • 當(dāng)前的裁切路徑(clipping path)

    ?

    可以調(diào)用任意多次?save方法。(類(lèi)似數(shù)組的push())

  • 關(guān)于restore()

    每一次調(diào)用?restore?方法,上一個(gè)保存的狀態(tài)就從棧中彈出,所有設(shè)定都恢復(fù)。(類(lèi)似數(shù)組的pop())

  • var ctx; function draw(){var canvas = document.getElementById('tutorial');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.fillRect(0, 0, 150, 150); // 使用默認(rèn)設(shè)置繪制一個(gè)矩形ctx.save(); // 保存默認(rèn)狀態(tài) ctx.fillStyle = 'red' // 在原有配置基礎(chǔ)上對(duì)顏色做改變ctx.fillRect(15, 15, 120, 120); // 使用新的設(shè)置繪制一個(gè)矩形 ctx.save(); // 保存當(dāng)前狀態(tài)ctx.fillStyle = '#FFF' // 再次改變顏色配置ctx.fillRect(30, 30, 90, 90); // 使用新的配置繪制一個(gè)矩形 ctx.restore(); // 重新加載之前的顏色狀態(tài)ctx.fillRect(45, 45, 60, 60); // 使用上一次的配置繪制一個(gè)矩形 ctx.restore(); // 加載默認(rèn)顏色配置ctx.fillRect(60, 60, 30, 30); // 使用加載的配置繪制一個(gè)矩形 } draw();

    ?

    ?

    九、變形

    9.1 translate

    translate(x, y)

    ? 用來(lái)移動(dòng)?canvas?的原點(diǎn)到指定的位置

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

    在做變形之前先保存狀態(tài)是一個(gè)良好的習(xí)慣。大多數(shù)情況下,調(diào)用?restore?方法比手動(dòng)恢復(fù)原先的狀態(tài)要簡(jiǎn)單得多。又如果你是在一個(gè)循環(huán)中做位移但沒(méi)有保存和恢復(fù)canvas?的狀態(tài),很可能到最后會(huì)發(fā)現(xiàn)怎么有些東西不見(jiàn)了,那是因?yàn)樗芸赡芤呀?jīng)超出?canvas?范圍以外了。

    ? 注意:translate移動(dòng)的是canvas的坐標(biāo)原點(diǎn)。(坐標(biāo)變換)

    ??

    var ctx; function draw(){var canvas = document.getElementById('tutorial1');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.save(); //保存坐原點(diǎn)平移之前的狀態(tài)ctx.translate(100, 100);ctx.strokeRect(0, 0, 100, 100)ctx.restore(); //恢復(fù)到最初狀態(tài)ctx.translate(220, 220);ctx.fillRect(0, 0, 100, 100) } draw();

    ?

    ?

    9.2 rotate

    rotate(angle)

    ? 旋轉(zhuǎn)坐標(biāo)軸。

    ? 這個(gè)方法只接受一個(gè)參數(shù):旋轉(zhuǎn)的角度(angle),它是順時(shí)針?lè)较虻?#xff0c;以弧度為單位的值。

    ? 旋轉(zhuǎn)的中心是坐標(biāo)原點(diǎn)。

    var ctx; function draw(){var canvas = document.getElementById('tutorial1');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.fillStyle = "red";ctx.save();ctx.translate(100, 100);ctx.rotate(Math.PI / 180 * 45);ctx.fillStyle = "blue";ctx.fillRect(0, 0, 100, 100);ctx.restore();ctx.save();ctx.translate(0, 0);ctx.fillRect(0, 0, 50, 50)ctx.restore(); } draw();

    ?

    ?

    9.3 scale

    scale(x, y)

    ? 我們用它來(lái)增減圖形在?canvas?中的像素?cái)?shù)目,對(duì)形狀,位圖進(jìn)行縮小或者放大。

    ??scale方法接受兩個(gè)參數(shù)。x,y分別是橫軸和縱軸的縮放因子,它們都必須是正值。值比 1.0 小表示縮 小,比 1.0 大則表示放大,值為 1.0 時(shí)什么效果都沒(méi)有。

    ? 默認(rèn)情況下,canvas?的 1 單位就是 1 個(gè)像素。舉例說(shuō),如果我們?cè)O(shè)置縮放因子是 0.5,1 個(gè)單位就變成對(duì)應(yīng) 0.5 個(gè)像素,這樣繪制出來(lái)的形狀就會(huì)是原先的一半。同理,設(shè)置為 2.0 時(shí),1 個(gè)單位就對(duì)應(yīng)變成了 2 像素,繪制的結(jié)果就是圖形放大了 2 倍。

    9.4 transform(變形矩陣)

    transform(a, b, c, d, e, f)

    a (m11)

    ? Horizontal scaling.

    b (m12)

    ? Horizontal skewing.

    c (m21)

    ? Vertical skewing.

    d (m22)

    ? Vertical scaling.

    e (dx)

    ? Horizontal moving.

    f (dy)

    ? Vertical moving.

    var ctx; function draw(){var canvas = document.getElementById('tutorial1');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.transform(1, 1, 0, 1, 0, 0);ctx.fillRect(0, 0, 100, 100); } draw();

    ?

    ?

    十、合成

    ? 在前面的所有例子中、,我們總是將一個(gè)圖形畫(huà)在另一個(gè)之上,對(duì)于其他更多的情況,僅僅這樣是遠(yuǎn)遠(yuǎn)不夠的。比如,對(duì)合成的圖形來(lái)說(shuō),繪制順序會(huì)有限制。不過(guò),我們可以利用?globalCompositeOperation?屬性來(lái)改變這種狀況。

    globalCompositeOperation = typevar ctx;function draw(){var canvas = document.getElementById('tutorial1');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.fillStyle = "blue";ctx.fillRect(0, 0, 200, 200);ctx.globalCompositeOperation = "source-over"; //全局合成操作ctx.fillStyle = "red";ctx.fillRect(100, 100, 200, 200);}draw();

    ?

    注:下面的展示中,藍(lán)色是原有的,紅色是新的。

    type `是下面 13 種字符串值之一:

    1.?source-over(default)

    這是默認(rèn)設(shè)置,新圖像會(huì)覆蓋在原有圖像。

    2.?source-in

    僅僅會(huì)出現(xiàn)新圖像與原來(lái)圖像重疊的部分,其他區(qū)域都變成透明的。(包括其他的老圖像區(qū)域也會(huì)透明)

    3.?source-out

    僅僅顯示新圖像與老圖像沒(méi)有重疊的部分,其余部分全部透明。(老圖像也不顯示)

    4.?source-atop

    新圖像僅僅顯示與老圖像重疊區(qū)域。老圖像仍然可以顯示。

    5.?destination-over

    新圖像會(huì)在老圖像的下面。

    6.?destination-in

    僅僅新老圖像重疊部分的老圖像被顯示,其他區(qū)域全部透明。

    7.?destination-out

    僅僅老圖像與新圖像沒(méi)有重疊的部分。 注意顯示的是老圖像的部分區(qū)域。

    8.?destination-atop

    老圖像僅僅僅僅顯示重疊部分,新圖像會(huì)顯示在老圖像的下面。

    9.?lighter

    新老圖像都顯示,但是重疊區(qū)域的顏色做加處理

    10.?darken

    保留重疊部分最黑的像素。(每個(gè)顏色位進(jìn)行比較,得到最小的)

    blue: #0000ff

    red: #ff0000

    所以重疊部分的顏色:#000000

    11.?lighten

    保證重疊部分最量的像素。(每個(gè)顏色位進(jìn)行比較,得到最大的)

    blue: #0000ff

    red: #ff0000

    所以重疊部分的顏色:#ff00ff

    12.?xor

    重疊部分會(huì)變成透明

    13.?copy

    只有新圖像會(huì)被保留,其余的全部被清除(邊透明)

    十一、裁剪路徑

    clip()

    ? 把已經(jīng)創(chuàng)建的路徑轉(zhuǎn)換成裁剪路徑。

    ? 裁剪路徑的作用是遮罩。只顯示裁剪路徑內(nèi)的區(qū)域,裁剪路徑外的區(qū)域會(huì)被隱藏。

    ? 注意:clip()只能遮罩在這個(gè)方法調(diào)用之后繪制的圖像,如果是clip()方法調(diào)用之前繪制的圖像,則無(wú)法實(shí)現(xiàn)遮罩。

    var ctx; function draw(){var canvas = document.getElementById('tutorial1');if (!canvas.getContext) return;var ctx = canvas.getContext("2d");ctx.beginPath();ctx.arc(20,20, 100, 0, Math.PI * 2);ctx.clip();ctx.fillStyle = "pink";ctx.fillRect(20, 20, 100,100); } draw();

    ?

    ?

    十二、動(dòng)畫(huà)

    動(dòng)畫(huà)的基本步驟

  • 清空canvas

    再繪制每一幀動(dòng)畫(huà)之前,需要清空所有。清空所有最簡(jiǎn)單的做法就是clearRect()方法

  • 保存canvas狀態(tài)

    如果在繪制的過(guò)程中會(huì)更改canvas的狀態(tài)(顏色、移動(dòng)了坐標(biāo)原點(diǎn)等),又在繪制每一幀時(shí)都是原始狀態(tài)的話(huà),則最好保存下canvas的狀態(tài)

  • 繪制動(dòng)畫(huà)圖形

    這一步才是真正的繪制動(dòng)畫(huà)幀

  • 恢復(fù)canvas狀態(tài)

    如果你前面保存了canvas狀態(tài),則應(yīng)該在繪制完成一幀之后恢復(fù)canvas狀態(tài)。

  • 控制動(dòng)畫(huà)

    我們可用通過(guò)canvas的方法或者自定義的方法把圖像會(huì)知道到canvas上。正常情況,我們能看到繪制的結(jié)果是在腳本執(zhí)行結(jié)束之后。例如,我們不可能在一個(gè)?for?循環(huán)內(nèi)部完成動(dòng)畫(huà)。

    也就是,為了執(zhí)行動(dòng)畫(huà),我們需要一些可以定時(shí)執(zhí)行重繪的方法。

    一般用到下面三個(gè)方法:

  • setInterval()
  • setTimeout()
  • requestAnimationFrame()
  • 案例1:太陽(yáng)系

    let sun; let earth; let moon; let ctx; function init(){sun = new Image();earth = new Image();moon = new Image();sun.src = "sun.png";earth.src = "earth.png";moon.src = "moon.png";let canvas = document.querySelector("#solar");ctx = canvas.getContext("2d");sun.onload = function (){draw()}} init(); function draw(){ctx.clearRect(0, 0, 300, 300); //清空所有的內(nèi)容/*繪制 太陽(yáng)*/ctx.drawImage(sun, 0, 0, 300, 300);ctx.save();ctx.translate(150, 150);//繪制earth軌道 ctx.beginPath();ctx.strokeStyle = "rgba(255,255,0,0.5)";ctx.arc(0, 0, 100, 0, 2 * Math.PI)ctx.stroke()let time = new Date();//繪制地球ctx.rotate(2 * Math.PI / 60 * time.getSeconds() + 2 * Math.PI / 60000 * time.getMilliseconds())ctx.translate(100, 0);ctx.drawImage(earth, -12, -12)//繪制月球軌道 ctx.beginPath();ctx.strokeStyle = "rgba(255,255,255,.3)";ctx.arc(0, 0, 40, 0, 2 * Math.PI);ctx.stroke();//繪制月球ctx.rotate(2 * Math.PI / 6 * time.getSeconds() + 2 * Math.PI / 6000 * time.getMilliseconds());ctx.translate(40, 0);ctx.drawImage(moon, -3.5, -3.5);ctx.restore();requestAnimationFrame(draw); }

    ?

    ?

    案例2:模擬時(shí)鐘

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><style>body {padding: 0;margin: 0;background-color: rgba(0, 0, 0, 0.1)}canvas {display: block;margin: 200px auto;}</style> </head> <body> <canvas id="solar" width="300" height="300"></canvas> <script>init();function init(){let canvas = document.querySelector("#solar");let ctx = canvas.getContext("2d");draw(ctx);}function draw(ctx){requestAnimationFrame(function step(){drawDial(ctx); //繪制表盤(pán) drawAllHands(ctx); //繪制時(shí)分秒針 requestAnimationFrame(step);});}/*繪制時(shí)分秒針*/function drawAllHands(ctx){let time = new Date();let s = time.getSeconds();let m = time.getMinutes();let h = time.getHours();let pi = Math.PI;let secondAngle = pi / 180 * 6 * s; //計(jì)算出來(lái)s針的弧度 let minuteAngle = pi / 180 * 6 * m + secondAngle / 60; //計(jì)算出來(lái)分針的弧度 let hourAngle = pi / 180 * 30 * h + minuteAngle / 12; //計(jì)算出來(lái)時(shí)針的弧度 drawHand(hourAngle, 60, 6, "red", ctx); //繪制時(shí)針 drawHand(minuteAngle, 106, 4, "green", ctx); //繪制分針 drawHand(secondAngle, 129, 2, "blue", ctx); //繪制秒針 }/*繪制時(shí)針、或分針、或秒針* 參數(shù)1:要繪制的針的角度* 參數(shù)2:要繪制的針的長(zhǎng)度* 參數(shù)3:要繪制的針的寬度* 參數(shù)4:要繪制的針的顏色* 參數(shù)4:ctx* */function drawHand(angle, len, width, color, ctx){ctx.save();ctx.translate(150, 150); //把坐標(biāo)軸的遠(yuǎn)點(diǎn)平移到原來(lái)的中心 ctx.rotate(-Math.PI / 2 + angle); //旋轉(zhuǎn)坐標(biāo)軸。 x軸就是針的角度 ctx.beginPath();ctx.moveTo(-4, 0);ctx.lineTo(len, 0); // 沿著x軸繪制針 ctx.lineWidth = width;ctx.strokeStyle = color;ctx.lineCap = "round";ctx.stroke();ctx.closePath();ctx.restore();}/*繪制表盤(pán)*/function drawDial(ctx){let pi = Math.PI;ctx.clearRect(0, 0, 300, 300); //清除所有內(nèi)容 ctx.save();ctx.translate(150, 150); //一定坐標(biāo)原點(diǎn)到原來(lái)的中心 ctx.beginPath();ctx.arc(0, 0, 148, 0, 2 * pi); //繪制圓周 ctx.stroke();ctx.closePath();for (let i = 0; i < 60; i++){//繪制刻度。 ctx.save();ctx.rotate(-pi / 2 + i * pi / 30); //旋轉(zhuǎn)坐標(biāo)軸。坐標(biāo)軸x的正方形從 向上開(kāi)始算起 ctx.beginPath();ctx.moveTo(110, 0);ctx.lineTo(140, 0);ctx.lineWidth = i % 5 ? 2 : 4;ctx.strokeStyle = i % 5 ? "blue" : "red";ctx.stroke();ctx.closePath();ctx.restore();}ctx.restore();} </script> </body> </html>

    ?

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/Michelle20180227/p/9293395.html

    總結(jié)

    以上是生活随笔為你收集整理的HTML5 Canvas的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。