1、什么是Canvas
- canvas 是 HTML5 提供的一個用於展示繪圖效果的標簽
canvas 提供了一個空白的圖形區域,可以使用特定的JavaScript API來繪畫圖形(canvas 2D或WebGL) 首先由 Apple 引入的,用於OS X的儀表盤 和 Safari 瀏覽器
1.1 關於Canvas的一些說明
- canvas 是一個矩形區域的畫布,可以用JavaScript在上面繪畫。控制其每一個像素。
- canvas 標簽使用 JavaScript 在網頁上繪制圖像,本身不具備繪圖功能。
- canvas 擁有多種繪制路徑、矩形、圓形、字符以及添加圖像的方法。
- canvas的標准:
1.2 canvas主要應用的領域(了解)
- 1、游戲:canvas在基於Web的圖像顯示方面比Flash更加立體、更加精巧,canvas游戲在流暢度和跨平台方面更牛。
-
3、banner廣告:Flash曾經輝煌的時代,智能手機還未曾出現。現在以及未來的智能機時代,HTML5技術能夠在banner廣告上發揮巨大作用,用Canvas實現動態的廣告效果再合適不過。
-
4、未來
- 模擬器:無論從視覺效果還是核心功能方面來說,模擬器產品可以完全由JavaScript來實現。
- 遠程計算機控制:Canvas可以讓開發者更好地實現基於Web的數據傳輸,構建一個完美的可視化控制界面。
- 圖形編輯器:Photoshop圖形編輯器將能夠100%基於Web實現。
1.3 課程目標
- 學會使用基本的 canvas api, 使用 canvas 可以完成簡單的繪圖
- 實現數據的可視化
2、Canvas標簽介紹
<canvas width="600" height="400"></canvas>
- 作用:展示繪圖的內容,但不能進行繪圖
2.1 canvas的兼容性
<canvas width="600" height="400"> IE9及其以上版本的瀏覽器,才支持canvas標簽 提示:您的瀏覽器不支持canvas,請升級瀏覽器 </canvas>
2.2 設置寬高注意點
- 1 可以使用 html屬性/DOM屬性
width
和height
來設置 - 2 不要:使用CSS樣式來設置寬高
使用 屬性設置寬高,實際上相當於增加了 canvas畫布的像素 默認寬高: 300*150,表示:水平方向有300個像素,垂直方向有150個像素 使用屬性設置寬高,是增加或減少了canvas畫布的像素; 而使用css樣式,不會增加像素點,只是將每個像素點擴大了!
2.3 繪圖
- 使用JavaScript中提供的繪圖API來繪制
- 每個canvas都有一套繪圖的API(工具)
2.3.1 繪圖的基本步驟
- 1 找到canvas畫布
- 2 通過canvas拿到繪圖上下文(一系列的API集合)
- 3 使用API繪制需要的圖形
// 1 找到canvas
var cv = document.getElementById("canvasId"); // 2 拿到canvas繪圖上下文 var ctx = cv.getContext("2d"); // 3 使用上下文中的API繪制圖形 ctx.moveTo(100, 100); // 將畫筆移動到 100,100 的位置 ctx.lineTo(200, 100); // 從 100,100 到 200,100 畫一條線段 ctx.stroke(); // 描邊
- 注意點:
getContext("2d"), 參數`2d`是指獲取到繪制平面圖形的上下文; 如果想繪制立體圖形,需要傳入參數:"webgl" 2d上下文類型:CanvasRenderingContext2D 獲得 webgl 上下文:(了解) var cCv = document.createElement("canvas"); console.log(cCv.getContext("webgl")); 查看瀏覽器是否支持 webgl:http://doesmybrowsersupportwebgl.com/ webgl示例:http://pablotheflamingo.com/
3、canvas的基本使用
3.1 canvas中的坐標系
- canvas坐標系,從最左上角0,0開始。x向右增大, y向下增大
- 聯想:CSS中的盒模型
3.2 繪制直線的常用API
- 步驟:先繪制路徑再描邊(在畫布中展示)
3.2.1 moveTo -設置繪制起點
- 語法:ctx.moveTo(x, y);
- 解釋:設置上下文繪制路徑的起點。相當於移動畫筆到某個位置
- 參數:x,y 都是相對於 canvas盒子的坐標。
- 注意:繪制線段前必須先設置起點,不然繪制無效。
3.2.2 lineTo -繪制直線
- 語法:ctx.lineTo(x, y);
- 解釋:從x,y的位置繪制一條直線到起點或者上一個線頭點。
- 參數:x,y 線頭點坐標。
3.2.3 stroke -描邊
- 語法:ctx.stroke();
- 解釋:根據路徑繪制線。路徑只是草稿,真正繪制線必須執行stroke
練習
- 練習1:繪制虛線
var startPosX = 100, step = 10, targetX = 500; while(startPosX + step <= targetX) { ctx.moveTo(startPosX, 100); ctx.lineTo(startPosX += step, 100); startPosX += step; } ctx.stroke();
- 練習2: 繪制傾斜虛線
var startX = 0, startY = 0, stepX = 5, stepY = cv.height / cv.width * stepX; while(true) { if(startX >= 600 || startY >= 400) { break; } ctx.moveTo(startX, startY); ctx.lineTo(startX += stepX, startY += stepY); startX += stepX; startY += stepY; }
- 練習3: 繪制正方形、三角形和梯形
3.3 fill -填充
- 語法:ctx.fill();
- 解釋:填充,是將閉合的路徑的內容填充具體的顏色, 默認黑色。
如果所有的描點沒有構成封閉結構,也會自動構成一個封閉圖形
- 練習:
3.3.1 非零環繞原則
- 注意:交叉路徑的填充問題,“非零環繞原則”,順逆時針穿插次數決定是否填充。
以下是非0環繞原則的原理:(了解即可,非常少會用到復雜的路徑) “非零環繞規則”是這么來判斷有自我交叉情況的路徑的:對於路徑中的任意給定區域, 從該區域內部畫一條足夠長的線段,使此線段的終點完全落在路徑范圍之外。 接下來,將計數器初始化為0, 然后,每當這條線段與路徑上的直線或曲線相交時, 就改變計數器的值。如果是與路徑的順時針部分相交,則加1, 如果是與路徑的逆時針部分相交,則減1。若計數器的最終值不是0,那么此區域就在路徑里面, 在調用fill()方法時,瀏覽器就會對其進行填充。 如果最終值是0,那么此區域就不在路徑內部,瀏覽器也就不會對其進行填充了
3.4 路徑開始和閉合
- 開始路徑:ctx.beginPath();
- 閉合路徑:ctx.closePath();
- 解釋:如果復雜路徑繪制,必須使用路徑開始和結束。閉合路徑會自動把最后的線頭和開始的線頭連在一起。
- beginPath: 核心的作用是將 不同繪制的形態進行隔離, 每次執行此方法,表示重新繪制一個路徑,跟之前的繪制的墨跡可以進行分開樣式設置和管理。
3.4.1 beginPath -開始路徑
- canvas 是基於狀態的繪圖
- beginPath 是開啟了一個的繪圖狀態
- 狀態:包含當前與當前繪制相關的屬性,如:顏色、線寬等
- 新的狀態會“繼承”原先的狀態
3.5 線寬
- 語法:ctx.lineWidth
- 解釋:設置或返回當前的線條寬度,沿着起始坐標往上下兩邊擴展
3.6 繪制線的其他屬性(了解)
-
lineCap 設置或返回線條的結束端點(線頭、線冒)樣式
- butt : 默認。向線條的每個末端添加平直的邊緣。
- round : 向線條的每個末端添加圓形線帽。
- square: 向線條的每個末端添加正方形線帽。
-
lineJoin 設置或返回兩條線相交時,所創建的拐角類型
- bevel: 創建斜角。
- round: 創建圓角。
- miter: 默認。創建尖角
-
miterLimit 設置或返回最大斜接長度
- 斜接長度指的是在兩條線交匯處內角和外角之間的距離。
- 一般用默認值:10就可以了。除非需要特別長的尖角時,使用此屬性。
3.7 繪制虛線(了解)
- 設置: setLineDash(數組)
- 讀取: getLineDash(數組)
- 偏移: lineDashOffset = 值
3.7.1 一些說明
- lineDashOffset 用於設置開始繪制虛線的偏移量. 數字的正負表示左右偏移.
- getLineDash() 與 setLineDash() 方法使用數組描述實線與虛線的長度.
3.8 描邊和填充的樣式說明
- fillStyle : 設置或返回用於填充繪畫的顏色
- strokeStyle: 設置或返回用於描邊的顏色
以上兩個值都可以接受:顏色名、16進制數據、rgb值,甚至rgba. 一般先進行設置樣式然后進行繪制。
例如: ctx.strokeStyle = "red"; ctx.strokeStyle = "#ccc"; ctx.strokeStyle = "rgb(255,0,0)"; ctx.strokeStyle = "rgba(255,0,0,6)";
3.8 繪制線的練習
- 練習1: 繪制坐標網格
- 練習2: 繪制坐標系
- 練習3: 繪制折線圖
4、使用面向對象封裝繪制直線
function Line(config) { this._init(config); } Line.prototype = { constructor: Line, _init: function(config) { this.ctx = config.context; this.x0 = config.points[0]; this.y0 = config.points[1]; this.x = config.points[2]; this.y = config.points[3]; this.strokeStyle = config.strokeStyle; this.lineWidth = config.lineWidth; }, stroke: function() { this.ctx.moveTo(this.x0, this.y0); this.ctx.lineTo(this.x, this.y); // 判斷有沒有值 if(this.strokeStyle) { this.ctx.strokeStyle = this.strokeStyle; } if(this.lineWidth) { this.ctx.lineWidth = this.lineWidth; } this.ctx.stroke(); } }; var line1 = new Line({ context: ctx, points: [100, 100, 500, 100], strokeStyle: "green", lineWidth: 10 }); line1.stroke();