前言
html5Canvas的知識點,是程式設計師開發者必備技能,在實際工作中也常常會涉及到。
最近熬夜總結html5Canvas相關的知識點,大家一起看一下吧:
1.html5Canvas基礎知識
- Canvas,它是畫布
- Canvas元素用於在網頁上繪製2D圖形和影像
Canvas使用的場景有:1,動畫;2,H5遊戲;3,圖表。
效果動畫,載入Loading:
H5遊戲效果:
對於Canvas需要掌握:
- 使用Canvas畫直線,矩形,圓形以及設定它們的樣式。
- Canvas中的圖形變換,漸變,文字和圖片。
- Canvas的畫素獲取,陰影和曲線繪製以及區域的剪輯。
- Canvas動畫,互動和離屏技術。
使用Canvas畫基本圖形
- Canvas的座標體系
- 使用Canvas畫直線,矩形,圓形
- 為圓形設定樣式
Canvas座標體系
- canvas預設大小,300*150
- 通過HTML,css,JavaScript設定width和height的區別
- HTML和JavaScript設定的畫布大小
- css設定的是畫布縮放後的大小
- 座標系原點及方向(原點在左上角,向右為x方向,向下為y方向)
畫直線,矩形和原型
- 畫直線:
ctx.moveTo(x1,y1),ctx.lineTo(x2,y2)
- 畫圓形:
ctx.arc(x,y,radius,0,Math.PI*2,true)
- 畫矩形:可以通過直線來畫,也可以直接用(
ctx.strokeRect(x1,y1,x2,y2
)
beginPath和closePath
- beginPath和closePath並不是成對出現的
- beginPath的作用是開始一條新路徑
- closePath的作用是使當前路徑閉合
描邊和填充樣式
- strokeStyle用來設定畫筆樣式,也就是直線,曲線,邊框的樣式
- fillStyle用來設定 填充樣式
- lineWidth用來設定線條的粗細
Canvas中的圖形變換,漸變,文字和圖片
- Canvas中的影像變換
- Canvas中的漸變
- Canvas中的文字
- Canvas中的圖片
Canvas中的圖形變換
圖形變換都是針對座標系來說的:
- 平移:
ctx.translate(x,y)
- 旋轉:
ctx.rotate(rad)
- 縮放:
ctx.scale(x,y)
save和restore
用來儲存和恢復上下文的環境ctx,一般成對出現
ctx.save()
,儲存當前上下文環境。ctx.restore()
,恢復到上一次的上下文環境
Canvas中的漸變
- 線性漸變:
ctx.createLinearGradient(xStart,yStart,xEnd,yEnd)
(xStart,yStart)
是線段的起點,(xEnd,yEnd)
是線段終點。起點到終點之間的顏色呈漸變。
gradient.addColorStop
可以來控制漸變的顏色- 漸變可以理解為一種顏色
- 徑向漸變:
ctx.createRadialGradient(xStart,yStart, radiusStart,xEnd,yEnd,radiusEnd);
(xStart,yStart)
是第一個圓的原心,radiusStart
是第一個圓的半徑,(xEnd,yEnd)
是第二個圓的原心,radiusEnd
是第二個圓的半徑
第一圓到第二個圓之間的顏色呈現漸變。
Canvas中的文字
描邊文字:ctx.strokeText(text,x,y)
填充文字:ctx.fillText(text,x,y);
設定字型樣式:ctx.font
- 例如:
ctx.font="bold 100px sans-serif"
- 設定水平對齊方式:
ctx.textAlign
- left,start,左對齊,center居中對齊,end,right,右對齊
設定垂直對齊方式:ctx.textBaseline
- top,頂對齊,middle,居中,bottom,底部對齊
- 計算文字寬度:
ctx.measuerText(text).width
須在設定字型樣式之後計算
Canvas圖片
繪製圖片3種方法
ctx.drawImage(image,x,y)
,該方法把圖片繪製在(x,y)
處ctx.drawImage(image,x,y,w,h)
,該方法把圖片繪製在(x,y)
處,並縮放為寬w,高hctx.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)
,該方法把圖片中(sx,sy)
處的寬sw,高sh的區域,繪製到(dx,dy)
處,並縮放為寬dw
,高dh
在image載入完成之後繪製:
示例:
var img = new Image();
img.src = 'logo.png';
img.onload = function() {
ctx.drawImage(img,0,0,40,40,0,0,80,80);
}
Canvas繪製
- Canvas的圖形繪製和畫素獲取
- Canvas陰影繪製
- Canvas剪輯區域
- Canvas曲線繪製
Canvas圖形畫刷
ctx.createPattern
可以建立一個畫刷模式,進而可以設定到fillStyle裡,進行畫刷的填充。
- 函式原型:
ctx.createPattern(image,type)
type取值:
no-repeat
不平鋪repeat-x
橫方向平repeat-y
縱方向平鋪repeat
全方向平鋪
Canvas畫素操作
- 獲取畫素
var imageData = ctx.getImageData(x,y,w,h)
返回的是一維陣列:[r1,g1,b1,a1,r2,g2,b2,a2...]
- 設定畫素
ctx.putImageData(imageData,x,y)
把imageData放在(x,y)處
- 設定畫素
ctx.putImageData(imageData, x, y, dirtyX, dirtyY, dirtyW, dirtyH)
只顯示(dirtyX,dirtyY)處的寬dirtyW,dirtyH的區域
Canvas陰影繪製
ctx.shadowOffsetX:
陰影x方向的偏移距離ctx.shadowOffsetY:
陰影y方向的偏移距離ctx.shadowColor:
陰影的顏色ctx.shadowBlur:
陰影的模糊半徑
效果圖:
Canvas剪輯區域
- 設定一個路徑;
- 呼叫ctx.clip();
- 再繪製圖形。
Canvas繪製曲線
狐線:
context.arc(x,y,radius, starAngle,endAngle, anticlockwise)
圓心(x,y) 半徑radius
從starAngle到endAngle
anticlockwise代表是否逆時針方向
生成工具
Canvas Quadratic Curve Example
http://blogs.sitepointstatic....
http://blogs.sitepointstatic....
二次樣條曲線:
context.quadraticCurveTo(qcpx,qcpy, qx,qy)
貝塞爾曲線:
context.bezierCurveTo(cp1x,cp1y, cp2x, cp2y, x,y)
- Canvas動畫,Canvas離屏技術
ctx.clearRect(x,y, width,height)
清除(x,y)
點起, 寬width,高height的區域,用於重新繪製
離屏技術是什麼:通過在離屏Canvas中繪製元素,再複製到顯示Canvas中,從而大幅提高效能的一種技術。
使用離屏技術:
- 靜態場景繪製特別耗資源,動態場景繪製簡單。為了不每次更新動態場景的時候,都去繪製靜態場景。
- 一般把靜態場景繪製在離屏canvas上,更新動態場景的時候,把靜態場景copy過來,而不是重新繪製。
離屏技術:
一個Canvas中的圖形繪製到另一個Canvas方法:
ctx.drawImage(canvas,x,y),該方法把canvas繪製在(x,y)處
ctx.drawImage(canvas,x,y, w,h),該方法把canvas繪製在(x,y)處,並縮放為寬w,高h
ctx.drawImage(canvas, sx, sy, sw, sh, dx, dy, dw, dh),該方法把canvas中(sx, sy)處的寬sw,高sh的區域,繪製到(dx,dy)處,並縮放為寬dw, 高dh
對canvas外掛的相關了解
什麼是Canvas外掛,掌握Chart.js外掛,瞭解Chartist.js和HighCharts.js外掛
(圖表)Chart.js外掛:https://www.chartjs.org/
Chartist.js外掛是一個簡單的響應式圖表外掛:支援SVG格式(http://gionkunz.github.io/cha...)
HighCharts.js外掛:方便快捷的HTML5互動性圖示庫:https://www.highcharts.com/
Chartist.js外掛與HighCharts.js外掛
- Chartist.js配置簡單,css和JavaScript分離,響應式圖表,支援不同的瀏覽器尺寸和解析度。
- HighCharts.js,相容當今所有的瀏覽器,包含iPhone,IE,火狐等。
響應式佈局,它的使用者體驗友好,響應式網站可以根據不同終端,不同尺寸和不同應用環境,自動調整介面佈局,展示內容,提供非常好的視覺效果。響應式佈局就是一個網站能夠相容多個終端
2. 構建Canvas元素
示例:
<style>
#canva {
border: 1px solid red;
}
</style>
<div>
<canvas id="canva" width="200" height="200"></canvas>
// 繪製寬高200的canvas
</div>
- 使用JavaScript實現繪圖的流程
在開始繪圖時,先要獲取Canvas元素的物件,在獲取一個繪圖的上下文。
獲取Canvas物件 ,使用document物件的getElementById()方法獲取。
var canvas = document.getElementById("canvas")
可以使用通過標籤名稱來獲取物件的getElementsByTagName方法
- 建立二維的繪圖上下文物件
使用getContext()方法來獲取
var context = canvas.getContext("2d")
- 在Canvas上繪製文字
context.font="98px 黑體"; // 文字樣式
context.fillStyle="red"; // 文字顏色
context.textAlign = "center"; // 文字對齊方式
// 繪製文字
context.fillText("達達前端",100, 123, 234);
繪製影像:
使用drawImage()方法可以將影像新增到Canvas畫布中,繪製一幅影像,需要有三個過載的方法:
使用:
drawImage(image, x, y)
// 在畫布上定點陣圖像
// 方法在畫布上繪製影像、畫布或視訊。
// 方法也能夠繪製影像的某些部分,以及/或者增加或減少影像的尺寸。
drawImage(image, x, y, width, height)
// 在畫布上定點陣圖像,並規定影像的寬度和高度
drawImage(image, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight)
// 剪下影像,並在畫布上定位被剪下的部分
引數:
引數 | 描述 |
---|---|
image | 規定要使用的影像,畫布或視訊 |
sourceX | 開始剪下的x座標位置 |
sourceY | 開始剪下的y座標位置 |
sourceWidth | 被剪下影像的寬度 |
sourceHeight | 被剪下影像的高度 |
destX | 在畫布上放置影像的 x 座標位置 |
destY | 在畫布上放置影像的 y 座標位置 |
destWidth | 要使用的影像的寬度 |
destHeight | 要使用的影像的高度 |
插入影像:
function Draw() {
// 獲取canvas物件
var canvas = document.getElementById("canvas");
// 獲取2d上下文繪圖物件
var context = canvas.getContext("2d");
// 使用Image()建構函式建立影像物件
var newImg = new Image();
// 指定影像的檔案地址
newImg.src = "../images/dadaqianduan.jpg";
newImg.onload = function () {
// 左上角開始繪製影像
context.drawImage(newImg, 0, 0);
context.drawImage(newImg, 250, 100, 150, 200);
context.drawImage(newImg, 90, 80, 100, 100, 0, 0, 120, 120);
}
}
在Canvas中繪製文字“達達前端”:
// canvas 寬高200
<canvas id="canvas" width="200" height="200"></canvas>
<style type="text/css">
canvas {
border: 2px solid #ccc;
}
</style>
<script>
// 獲取canvas
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
// 設定字型
context.font="98px 黑體";
// 填充
context.fillStyle="#036";
// 文字水平位置
context.textAlign="center";
// 執行繪製
context.fillText("達達前端",100, 120, 200);
</script>
3.繪製矩形
兩個方法:
- strokeRect() - 矩形邊框
- fillRect() - 填充矩形區域
- strokeStyle - 設定線條的顏色
- lineWidth - 設定線條寬度,預設寬度為1,單位是畫素
- fillStyle - 設定區域或文字的填充顏色
繪製矩形邊框,使用strokeStyle方法:
// 繪製矩形邊框
strokeRect(x,y, width, height);
填充矩形區域,使用fillRect()方法:
// 填充矩形區域
fillRect(x,y,width,height);
繪製矩形
// 繪製矩形
function drawRect() {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
// 描邊
context.strokeStyle = "#000";
// 線條寬度
context.lineWidth = 1;
// 矩形邊框
context.strokeRect(50,50, 150, 100);
// 填充
context.fillStyle="#f90";
// 矩形
context.fillRect(50,50,150,100);
}
window.addEventListener("load",DrawRect,true);
使用clearRect方法,可以擦除指定的矩形區域:
// 擦除指定的矩形區域
context.clearRect(x,y,width,height)
4.體驗canvas繪圖
在實際開發中,畫布是預設300*150的大小。
示例:
// 為畫布設定邊框
canvas {
border: 1px solid #ccc;
}
// 準備畫布,預設是300*150
// 設定畫布的大小
<canvas width="1200" height="800"></canvas>
// 準備繪製工具
<script>
// 獲取元素
var myCanvas = document.querySelector('canvas');
// 獲取上下文,繪製工具箱
var ctx = myCanvas.getContext('2d');
// 移動畫筆
ctx.moveTo(100,100);
// 繪製直線,軌跡
ctx.lineTo(200,100);
// 描邊
ctx.stroke()
建立Canvas元素
向 HTML5 頁面新增 canvas 元素
// 規定元素的 id、寬度和高度
<canvas id="myCanvas" width="200" height="100"></canvas>
圖形繪製
需要理解些概念:
- 路徑的概念
路徑的繪製
- 描邊
stroke()
- 填充
fill()
- 描邊
閉合路徑
- 手動閉合
- 程式閉合
closePath()
- 開啟新的路徑
beginPath()
設定樣式
畫筆的狀態
- lineWidth 線寬,預設
1px
- lineCap 線末端型別:
(butt預設)、round、square
- lineJoin 相交線的拐點
miter(預設)、round、bevel
- strokeStyle 線的顏色
- fillStyle 填充顏色
setLineDash()
設定虛線getLineDash()
獲取虛線寬度集合lineDashOffset
設定虛線偏移量(負值向右偏移)
- lineWidth 線寬,預設
矩形繪製
rect(x,y,w,h)
沒有獨立路徑strokeRect(x,y,w,h)
有獨立路徑,不影響別的繪製fillRect(x,y,w,h)
有獨立路徑,不影響別的繪製clearRect(x,y,w,h)
擦除矩形區域
圓弧繪製
- 弧度概念
arc()
- x 圓心橫座標
- y 圓心縱座標
- r 半徑
startAngle
開始角度endAngle
結束角度anticlockwise
是否逆時針方向繪製(預設false表示順時針;true表示逆時針)
繪製文字
ctx.font
= '微軟雅黑' 設定字型strokeText()
fillText(text,x,y,maxWidth)
- text 要繪製的文字
- x,y 文字繪製的座標(文字左下角)
- maxWidth 設定文字最大寬度,可選引數
ctx.textAlign
文字水平對齊方式,相對繪製座標來說的- left
- center
- right
- start 預設
- end
ctx.direction
屬性css(rtl ltr) start和end
於此相關- 如果是
ltr,start和left
表現一致 - 如果是
rtl,start和right
表現一致
- 如果是
ctx.textBaseline
設定基線(垂直對齊方式 )- top 文字的基線處於文字的正上方,並且有一段距離
- middle 文字的基線處於文字的正中間
- bottom 文字的基線處於文字的證下方,並且有一段距離
- hanging 文字的基線處於文字的正上方,並且和文字粘合
- alphabetic 預設值,基線處於文字的下方,並且穿過文字
- ideographic 和bottom相似,但是不一樣
measureText()
獲取文字寬度obj.width
繪製圖片
drawImage()
三個引數
drawImage(img,x,y)
- img 圖片物件、canvas物件、video物件
- x,y 圖片繪製的左上角
五個引數
drawImage(img,x,y,w,h)
- img 圖片物件、canvas物件、video物件
- x,y 圖片繪製的左上角
- w,h 圖片繪製尺寸設定(圖片縮放,不是擷取)
九個引數
drawImage(img,x,y,w,h,x1,y1,w1,h1)
- img 圖片物件、canvas物件、video物件
- x,y,w,h 圖片中的一個矩形區域
- x1,y1,w1,h1 畫布中的一個矩形區域
座標變換
平移 移動畫布的原點
translate(x,y)
參數列示移動目標點的座標
縮放
scale(x,y)
參數列示寬高的縮放比例
旋轉
rotate(angle)
參數列示旋轉角度
5.使用路徑
- lineTo()
- rect()
- arc()
- fill()
- stroke()
建立繪圖路徑
使用方法:beginPath()和closePath()
,分別表示開始一個新的路徑和關閉當前的路徑
- 使用beginPath()方法建立一個新的路徑
- moveTo(x,y),開始繪圖時的座標
- lineTo(x,y),繪製直線到目標座標
- arc(x,y, radius, startAngle,endAngle, counterclockwise)
- x,y描述弧的圓形的圓心座標
- radius圓形的半徑
- startAngle描述弧的開始點的角度
- endAngle描述弧的結束點的角度
- counterclockwise,true值,表示逆時針方向,否則反之
rect(x,y, width, height)
:xy,起點座標,矩形的寬高,繪製矩形路徑
closePath方法關閉當前路徑
繪製圖形樣式
stokeStyle
屬性設定矩形邊框的顏色lineWidth
屬性設定邊框的寬度fillStyle
屬性設定填充的顏色
繪製網格,網格大小
var grid = 10;
// 畫多少條x軸方向的線,橫向的條數,畫布的高度
var canvasHeight = myCanvas.height
var canvasWidth = myCanvas.width
// 畫布寬高
ctx.canvas.width
ctx.canvas.height
// 網格大小
var gridSize = 10;
var canvasHeight = ctx.canvas.height;
var xLineTotal = canvasHeight / gridSize
// 匯流排條
var xLineTotal = Math.floor(canvasHeight / gridSize);
for (var i=0; i<=xLineTotal; i++) {
ctx.beginPath();
ctx.moveTo(0, i*gridSize-0.5);
ctx.lineTo(canvasWidth, i*gridSize-0.5);
ctx.strokeStyle='#eee';
ctx.stroke();
}
// 畫多少條y軸方向的線
var yLineTotal = canvasWidth / gridSize
var yLineTotal = Math.floor(canvasWidth / gridSize);
for (var i=0; i <= yLineTotal; i++) {
ctx.beginPath();
ctx.moveTo(i*gridSize-0.5,0);
ctx.lineTo(i*gridSize-0.5,canvasHeight);
ctx.strokeStyle='#eee';
ctx.stroke();
}
繪製座標系,確定圓點,確定離畫布旁邊的距離,確定座標軸的長度,確定箭頭的大小,繪製箭頭填充。
// 繪製座標系
var space = 20;
var arrowSize = 10;
// 畫布寬高
var canvasWidth = ctx.canvas.width;
var canvasHeight = ctx.canvas.height;
// 座標系
var x0 = space;
var y0 = canvasHeight - space;
// 繪製x軸
ctx.moveTo(x0,y0);
ctx.lineTo(canvasWidth-space, y0);
ctx.stroke();
// 箭頭
ctx.lineTo(canvasWidth-space-arrowSize, y0 + arrowSize/2);
ctx.lineTo(canvasWidth-space-arrowSize, y0 - arrowSize/2);
ctx.lineTo(canvasWidth-space, y0);
ctx.fill();
ctx.stroke();
// 繪製y軸
ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.lineTo(space, space);
ctx.stroke();
// 箭頭
ctx.lineTo(space+space-arrowSize/2, space + arrowSize);
ctx.lineTo(space-space-arrowSize/2, space - arrowSize);
ctx.lineTo(space, space);
ctx.fill();
ctx.stroke();
// 繪製點
var coordinate = {
x: 146,
y: 356
}
// 點尺寸
var dottedSize = 6;
ctx.moveTo(coordinate.x - dottedSize/2, coordinate.y - dottedSize/2);
ctx.lineTo(coordinate.x + dottedSize/2, coordinate.y - dottedSize/2);
ctx.lineTo(coordinate.x + dottedSize/2, coordinate.y + dottedSize/2);
ctx.lineTo(coordinate.x - dottedSize/2, coordinate.y + dottedSize/2);
ctx.closePath();
ctx.fill();
arc方法和rect方法
arc建立一個圓形,rect建立一個矩形,最後呼叫stroke()方法和fill()方法
// 圓形
context.arc(100,100,30,0,Math.PI*2,true);
使用beginPath()方法可以新建立一個子路徑,closePath()方法用來閉合路徑的。
繪製兩條直線
function DrawLine() {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
// 建立繪製過程
context.beginPath();
context.moveTo(50,50);
context.lineTo(120,120);
context.lineTo(120,60);
context.closePath();
context.strokeStyle="#000";
// 執行繪製
context.stroke();
}
- beginPath() 方法開始一條路徑,或者重置當前的路徑
- closePath() 方法建立從當前點到開始點的路徑
如果不用beginPath()
方法,繪製圖形時不再建立子路徑,第一次的圖形在執行過程中會被繪製填充兩次。
圖形組合
屬性 globalCompositeOperation
設定如何在畫布上組合顏色
12中組合型別:
值 | 說明 |
---|---|
copy | 只繪製新圖形,刪除其他所有內容 |
darker | 在圖形重疊的地方,顏色由兩個顏色值相減後決定 |
destination-atop | 已有的內容只在它和新的圖形重疊的地方保留,新圖形繪製在內容後 |
destination-in | 在新圖形和已有畫布重疊的地方,已有內容都保留,所有其他內容成為透明 |
destination-out | 在新圖形和已有內容不重疊的地方,已有內容保留所有其他內容成為透明 |
destination-over | 新圖形繪製於已有內容的後面 |
lighter | 在圖形重疊的地方,顏色由兩種顏色值的疊加值來決定 |
source-atop | 只在新圖形和已有內容重疊的地方才繪製新圖形 |
source-in | 在新圖形和已有內容重疊的地方,新圖形才會被繪製,所有其他內容成為透明 |
source-out | 只在和已有圖形不重疊的地方繪製新圖形 |
source-over | 新圖形繪製於已有圖形的頂部 |
xor | 在重置和正常繪製的其他地方,圖形都成為透明 |
繪製曲線
// 圓形,曲線
arc(x, y, radius, startAngle, endAngle, counterclockwise);
x,y
表示弧的圓形的圓心座標radius
表示弧的圓形的半徑startAngle
表示圓弧的開始點的角度endAngle
表示圓弧的結束點的角度counterclockwise
若true表示逆時針,false反之順時針
<style>
// 畫布背景顏色
#canvas {
background: #000;
}
</style>
// 畫布寬度400
<canvas id="canvas" width="400" height="400">
<script>
var canvas = document.getElementById('canvas');
var context= canvas.getContext('2d')
// 開始
context.beginPath();
// 繪製圓形
context.arc(100, 100, 50, 0, Math.PI*2, true);
// 關閉
context.closePath();
// 填充顏色
context.fillStyle = 'rgb(255,255,255)';
context.fill();
</script>
如果使用css
設定寬高,畫布會按照300*150
的比例進行縮放,將300*150
的頁面顯示在400*400
的容器中。
// 設定畫布寬度
var cx = canvas.width = 400;
var cy = canvas.height = 400;
使用js動態設定寬高。
建議使用HTML中的width和height,或者js動態設定寬高
建立一個canvas標籤,第一步:
// 獲取這個canvas的上下文物件
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
方法:
fill()
填充路徑stroke()
描邊arc()
建立圓弧rect()
建立矩形fillRect()
繪製矩形路徑區域strokeRect()
繪製矩形路徑描邊clearRect()
在給定的矩形內清除指定的畫素beginPath()
起始一條路徑,或重置當前路徑moveTo()
把路徑移動到畫布中的指定點,不建立線條lineTo()
新增一個新點,在畫布中建立從該點到最後指定點的線條clip()
從原始畫布剪下任意形狀和尺寸的區域arcTo()
建立兩切線之間的弧/曲線quadraticCurveTo()
建立二次方貝塞爾曲線bezierCurveTo()
建立三次方貝塞爾曲線isPointInPath()
如果指定的點位於當前路徑中,則返回 true,否則返回 false
輔助線繪製弧線:arcTo()
方法
語法:
// 輔助線繪製弧線
arcTo(x1, y1, x2, y2, radius)
arcTo()方法繪製一條弧線
程式碼:
// 繪製一條弧線
function draw() {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
// 開始繪製
context.beginPath();
// 移動點
context.moveTo(80, 120);
// 繪製線條
context.lineTo(150, 60);
context.lineTo(180, 130);
// 描邊
context.strokeStyle="rgba(0,0,0,0.4)";
context.lineWidth=2;
context.stroke();
context.beginPath();
context.moveTo(80,120);
context.arcTo(150,60,180,130,50);
context.strolkeStyle="rgba(255,135,0,1)";
context.stroke();
}
繪製二次樣條曲線
quadraticCurveTo()
方法:
quadraticCurveTo(cpX, cpY, x, y);
// cpX, cpY描述了控制點的座標,x, y描述了曲線的終點座標
繪製貝濟埃曲線
bezierCurveTo()
方法:它是應用於二維圖形應用程式的數學曲線。
bezierCurveTo(cp1X, cp1Y, cp2X, cp2Y, x, y);
// cp1X, cp1Y 表示第一個控制點的座標
// cp2X, cp2Y 表示第二個控制點的座標
// x, y表示曲線的終點座標
繪製曲線:
function draw() {
// 繪製曲線
var canvas = document..getElementById('canvas');
var context = canvas.getContext('2d');
// 開始繪製
context.beginPath();
// 移動
context.moveTo(100,180);
// 連線
context.lineTo(110,80);
context.moveTo(260,100);
context.lineTo(300,200);
// 描邊
context.strokeStyle="rgba(0,0,0,0.4)";
// 設定寬度
context.lineWidth=3;
context.stroke();
context.beginPath();
context.moveTo(100,180);
// 繪製貝濟埃曲線
context.bezierCurveTo(110,80,260,100,300,200);
// 設定寬度
context.lineWidth = 3;
context.strokeStyle="rgba(255,135,0,1)";
context.stroke();
}
四分之一圓
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
// 畫布寬度200
var canX = canvas.width = 200
var canY = canvas.height = 200;
// 開始繪製
context.beginPath();
// 四分之一圓
context.arc(100, 100, 50, 0, Math.PI*0.5, false);
context.strokeStyle="white"
context.stroke();
context.beginPath();
context.lineTo(200, 200);
context.lineTo(200, 100);
context.lineTo(100,50);
context.strokeStyle = '#fff';
context.stroke();
lineCap
設定或返回線條的結束斷點樣式lineJoin
設定或返回兩條線相交時,產生拐角型別lineWidth
設定或返回當前的線條寬度miterLimit
設定或返回最大斜接長度
fillRect()
繪製一個實心矩形strokeRect()
繪製一個空心矩形
設定陰影,shadowBlur
-context.shadowBlur
= 20
createLinearGradient()
建立線性漸變createPattern()
在指定的方向上重複指定的元素createRadialGradient()
建立放射狀/環形的漸變addColorStop()
規定漸變物件中的顏色和停止位置
gradient.addColorStop(stop,color)
scale()
縮放當前繪圖變大或變小rotate()
旋轉當前繪圖translate()
重新對映畫布的(0,0)位置
6.使用影像
使用三種方法插入影像
function draw() {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
// image例項
var newImg = new Image();
newImg.src='../images/dada.jpg' // 指定影像的檔案地址
newImg.onload = function(){
// 繪圖
context.drawImage(newImg, 0, 0);
context.drawImage(newImg, 250,100, 150,200);
context.drawImage(newImg, 90,80,100,100,0,0,120,120);
}
}
在插入影像之前,需要考慮影像載入的時間,如果影像沒載入完成就已經執行drawImage()方法,就不會顯示任何圖片。
7.繪製漸變
提供了兩種漸變的建立的方法:
// 建立線性漸變
createLinearGradient()方法
// 建立徑向漸變
createRadialGradient()方法
設定漸變顏色和過渡方式
語法如下:
- offset是一個範圍在0.0到1.0之間的浮點值
表示漸變的開始點和結束點之間的一部分
- offset的0為開始點,1為結束點
addColorStop(offset, color);
繪製線性漸變的矩形
function draw() {
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d')
// 建立漸變物件,線性漸變
var grd = context.createLinearGradient(0,0,300,0)
// 設定漸變顏色
grd.addColorStop(0, '#xxx'); // 設定顏色
grd.addColorStop(1, '#xxx'); // 設定顏色
// 將填充樣式設定為線性漸變物件
context.fillStyle = grd;
context.fillRect(0,0,300,80);
}
繪製徑向漸變的矩形
function draw() {
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d')
// 徑向漸變
var grd = context.createRadialGradient(50,50,0,100,100,90);
// 設定漸變顏色以及方式
grd.addColorStop(0,'#xxx');
grd.addColorStop(1,'#xxx');
context.fillStyle = grd;
context.beginPath();
// 圓形
context.arc(100,100,90,0,Math.PI*2,true);
context.fill();
}
描邊屬性
線帽屬性:lineCap
,表示指定線條的末端如何繪製
值:lineCap: butt, round, square
,當線條具有一定的寬度才能表現出來。
butt
// 定義了線段沒有線帽
round
// 定義了線段的末端為一個半圓形的線帽
square
// 定義了線段的末端為一個矩形的線帽
線條的連線屬性lineJoin
,用於兩條線條到的連線方式:
miter
兩條線段的外邊緣一直延伸到它們相交,屬性miterLimit是用來描述如何繪製兩條線段的交點,是表示延伸長度和線條長度的比值。
預設為10,只有miter
使用時有效
lineJoin = [value];
round
// 兩條線段的外邊緣應該和一個填充的弧結合
bevel
// 兩條線段的外邊緣應該和一個填充的三角形相交
8.模式
語法如下:
createPattern(image, repetitionStyle)
repeat
表示影像在各個方向上迴圈平鋪repeat-x
表示影像在橫向上迴圈平鋪repeat-y
表示影像在縱向上迴圈平鋪no-repeat
表示影像只使用一次
function draw() {
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d')
var img = new Image();
// 使用Image()建構函式建立影像物件
img.src='../images/xxx'
// 指定影像的檔案地址
img.onload = function() {
// 繪圖模式
var ptrn = context.createPattern(img, 'repeat');
// 填充樣式
context.fillStyle = ptrn;
// 填充矩形
context.fillReat(0,0,500,200);
}
}
移動變化:
// 移動
translate(dx,dy);
// 繪製
function draw() {
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d')
// 設定移動偏移量
context.translate(200, 200);
// 繪製一個圓形
ArcFace(context);
}
// 繪製一個圓形
function ArcFace(context) {
// 繪製一個圓形邊框
context.beginPath();
// 繪製圓形
context.arc(0,0,90,0,Math.PI*2,true);
// 線寬
context.lineWidth=5;
// 描邊
context.strokeStyle='#f90';
context.stroke();
// 繪製
context.beginPath();
context.moveTo(-30, -30);
context.lineTo(-30, -20);
context.moveTo(30, -30);
context.lineTo(30, -20);
context.moveTo(-20, 30);
// 曲線
context.bezierCurveTo(-20, 44, 20, 30, 30, 20);
context.strokeStyle='#000';
context.lineWidth=10;
context.lineCap = 'round';
// 笑臉?
context.stroke();
}
縮放變換,語法如下:
scale(sx, sy);
// sx為水平方向上的縮放因子,sy為垂直方向上的縮放因子
// 示例
function draw() {
var canvas = document.getElementById('canvas')
var context = canvas.getContent('2d')
// 移動
context.translate(200,200);
// 縮放
context.scale(0.5,0.5);
ArcFace(context);
}
旋轉變換:
rotate(angle)
// 旋轉例子
function draw() {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d')
context.translate(200,200);
// 旋轉
context.rotate(Math.PI/6);
context.scale(0.5, 0.5)
ArcFace(context)
}
矩形變形,語法如下:
transform(m1x,m1y,m2x,m2y,dx,dy); // 移動,縮放,旋轉
1. 移動translate (dx, dy)
2. 縮放scale (sx,sy)
3. 旋轉rotate (A)
9.使用文字
繪製文字的方法:
fillText(text, x, y, maxwidth)
strokeText(texxt, x, y, maxwidth)
text
表示要繪製的文字- 引數x表示繪製文字的起點橫座標
- 引數y表示繪製文字的起點縱座標
- 引數
maxwidth
表示顯示文字的最大寬度
文字屬性表:
屬性 | 說明 |
---|---|
font | 陣列字型樣式 |
textAlign | start,end,left,right,center |
textBaseline | top,hanging,middle,alphabetic,ideographic,bottom |
繪製文字
// 繪製文字示例
function draw() {
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d')
// 填充顏色
context.fillStyle = '#000';
context.font = 'bold 12px impact';
// 繪製文字
context..fillText('達達前端,魔王哪吒', 10, 10);
context.strokeStyle = '#000';
context.font = 'bold italic 12px impact';
// 繪製文字
context.strokeText('jeskson', 10, 10);
}
繪製獲取文字寬度的measureText()
方法:
measureText(text)
測量文字的寬度:
function draw() {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
context.fillStyle='#000';
context.font='bold 10px impact';
// 測量文字的寬度
var tm = context.measureText(txt);
context.fillText(txt,10,10);
context.fillText(tm.width, tm.width+10, 50);
context.strokeStyle = '#000';
context.font = 'bold italic 10px impact';
// 測量文字的寬度
tm = context.measureText(txt);
context.strokeText(txt,10,10);
context.strokeText(tm.width, tm.width+10, 100);
}
陰影效果
陰影屬性表:
屬性 | 說明 |
---|---|
shadowColor | 使用半透明顏色 |
shadowOffsetX | 陰影的橫向位移量 |
shadowOffsetY | 陰影的縱向位移量 |
shadowBlur | 高斯模糊 |
狀態儲存和恢復
- 狀態儲存方法
save()
- 狀態恢復方法
restore()
,恢復最後一次儲存的狀態
狀態的儲存和恢復是通過資料棧進行的
10.操作畫素
- 影像資料物件
ImageData
- 獲取影像資料的方法
getImageData()
,用於從Canvas
上下文中獲取影像資料。getImageData(sx, sy, sw, sh);
- 繪製影像資料的方法
putImageData()
getImageData(imagedata,dx,dy[,..])
- 建立影像資料的方法
createImageData()
繪製海報
<template>
<view class="backgroundColor">
// 畫布
<canvas class="isCan" canvas-id="dadaPoster" :style="{ width: cansWh.cansWidth + 'px', height: cansWh.cansHeight + 'px' }"></canvas>
// 效果圖
<image class="showImg" mode="aspectFit" v-if="tempImgShow" @longpress="longpress" :src="tempImg"></image>
// 按鈕
<view v-if="tempImgShow" class="fixedBox flex flex-direction">
<view class="boxTop text-white">長按圖片傳送給朋友</view>
<view class="boxDown">
<button class="flexBtn" hover-class="btnHover" @click="closeCans">關閉</button>
</view>
</view>
</view>
</template>
data() {
return {
tempImgShow: false,
tempImg: '',
cansWh: { // 畫布寬高
cansWidth: 800,
cansHeight: 900,
},
qrcode: { // 舉例二維碼
top: 0.85,
left: 0.035,
width: 0.23,
qrHeight: null,
},
...
productImg: { // 產品圖
top: 0.1,
left: 0.03,
width: 1,
height: 0.5,
},
};
},
// 繪製圖
drawImg(method,param){
return new Promise((resolve, reject)=>{
if(param.url.indexOf('http') === 0){
uni.downloadFile({
url: param.url,
success(res) {
param.url = res.tempFilePath
method(param).then(res=>{
resolve(res)
}).catch(err=>{
reject(err)
})
},
fail(error) {
console.log(error)
}
})
}else{
method(param).then(res=>{
resolve(res)
}).catch(err=>{
reject(err)
})
}
})
}
// 繪製圓形
drawCircle(param) {
var that = this,x = param.x,y = param.y,r = param.r,url = param.url;
return new Promise((resolve, reject) => {
x = Math.ceil(that.cansWh.cansWidth * x);
y = Math.ceil(that.cansWh.cansHeight * y);
r = r > 1 ? r : Math.ceil(that.cansWh.cansWidth * r);
that.ctx.save();
var d = 2 * r;
var cx = x + r;
var cy = y + r;
that.ctx.arc(cx, cy, r, 0, 2 * Math.PI);
that.ctx.clip();
that.ctx.drawImage(url, x, y, d, d);
that.ctx.restore();
that.ctx.draw(true, res=>{
resolve();
});
});
}
// 繪製圖
drawPic(item) {
return new Promise((resolve, reject) => {
let x, y, w, h, r;
y = item.sTop <= 1 ? this.cansWh.cansHeight * item.sTop : item.sTop;
w = item.sWidth <= 1 ? this.cansWh.cansWidth * item.sWidth : item.sWidth;
h = item.sHeight <= 1 ? this.cansWh.cansHeight * item.sHeight : item.sHeight;
if (item.sLeft == 'center') {
x = item.sWidth <= 1 ? this.cansWh.cansWidth * (0.5 - item.sWidth / 2) : this.cansWh.cansWidth * 0.5 - item.sWidth /
2;
} else {
x = this.cansWh.cansWidth * item.sLeft;
}
if (item.r) {
r = item.r;
this.ctx.save();
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
this.ctx.beginPath();
this.ctx.moveTo(x + r, y);
this.ctx.arcTo(x + w, y, x + w, y + h, r);
this.ctx.arcTo(x + w, y + h, x, y + h, r);
this.ctx.arcTo(x, y + h, x, y, r);
this.ctx.arcTo(x, y, x + w, y, r);
this.ctx.closePath();
this.ctx.clip();
this.ctx.drawImage(item.url, x, y, w, h);
this.ctx.restore(); // 返回上一狀態
} else {
this.ctx.drawImage(item.url, x, y, w, h);
}
this.ctx.draw(true, res=>{
resolve();
});
});
}
// 儲存
saveCans() {
let tempRatio = 1;
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: this.cansWh.cansWidth * tempRatio,
height: this.cansWh.cansHeight * tempRatio,
destWidth: this.cansWh.cansWidth * tempRatio * 2,
destHeight: this.cansWh.cansHeight * tempRatio * 2,
canvasId: 'dadaPoster',
success: (res) => {
this.tempImg = res.tempFilePath;
setTimeout(() => {
this.tempImgShow = true;
}, 100);
uni.hideLoading();
},
fail: (res) => {
console.log(res);
uni.hideLoading();
}
},
);
}
小結
canvas標籤的使用
// canvas標籤的使用
<canvas width="100" height="100"></canvas>
// 獲取canvas
var canvas = document.getElementById('target')
if(canvas.getContext) {
var ctx = canvas.getContext('2d');
}else {
alert('該瀏覽器版本過低,請更換')
}
// 矩形
fillRect( x , y , width , height) // 填充
strokeRect( x , y , width , height) // 空心
clearRect( x, y , width , height ) // 清除透明
var grd = ctx.createLinearGradient( x1 ,y1 ,x2 ,y2); //線性漸變
var grd = ctx.createRadialGradient(x1 ,y1 ,r1 ,x2 ,y2 ,r2);//徑向漸變
曲線
- 二次貝塞爾曲線
quadraticCurveTo( cp1x, cp1y , x ,y )
(cp1x,cp1y) 控制點 (x,y)結束點
- 三次貝塞爾曲線
bezierCurveTo( cp1x, cp1y ,cp2x , cp2y ,x , y )
(cp1x,cp1y)控制點1 (cp2x,cp2y) 控制點2 (x,y)結束點
HTML5繪圖製作海報
<body>
<img src="img/bg.png" id="img1" style="display: block" width="1200" height="800" />
<img src="img/dada.png" id="img2" style="display: block" width="100" height="100" />
<img id="img3" />
<button onclick="draw()" id="btn">點選下載</button>
<script>
function draw() {
var img1 = document.getElementById("img1"),
var img2 = document.getElementById("img2"),
var img3 = document.getElementById("img3");
var img1.width = 1200;
var img1.height = 800;
var img2.width = 100;
var img2.height = 100;
var canvas = document.createElement("canvas"),
context = canvas.getContext("2d");
// 繪製寬度
canvas.width = img1.width;
// 繪製高度
canvas.height = img1.height;
/**
* context.drawImage(image,x,y,w,h)
* var img=new Image(); img.src="url(...)";
* x:繪製影像的x座標
* y:繪製影像的y座標
* w:繪製影像的寬度
* h:繪製影像的高度
*/
context.drawImage(img1, 0, 0, img1.width, img1.height);
// 將 img2 加入畫布
context.drawImage(img2, 100, 100, img2.width, img2.height);
// 文字填充顏色
context.fillStyle = '#333';
// 文字字型
context.font = 'bold 45px 黑體';
// 設定文字
var name_text = '達達前端,魔王哪吒';
// 獲取文字的寬度
var name_width = context.measureText(name_text).width;
// 獲取除去文字後的一半的寬度
var x = (canvas.width - name_width) / 2;
/**
* context.font:設定字型樣式
* context.textAlign:水平對齊方式
* context.textBaseline:垂直對齊方式
* context.measureText(text):計算字型長度(px)
*/
context.fillText(name_text, x, 450);
context.fillStyle = '#333'; // 文字填充顏色
context.font = '25px bold 黑體';
var con_1 = 'dadaqianduan';
var con_2 = '達達';
/**
* text:要繪製的文字
* x:文字起點的x座標軸
* y:文字起點的y座標軸
*/
context.fillText(con_1, x, 400);
var con_width_2 = context.measureText(con_2).width;
context.fillText(con_2, canvas.width - x - con_width_2, 400);
context.stroke();
// 將畫布內容匯出
var src = canvas.toDataURL();
img3.src = src;
const a = document.createElement("a");
a.href = src;
a.download = '自定義.png';
a.click();
}
</script>
</body>
html5繪圖操作(html2canvas)
script引入檔案
html2canvas(content, { //content是將要截圖的div元素
scale: 2,
logging: false, //在console中輸出資訊
useCORS: true //允許跨域
//proxy: string, //代理地址
//timeout: number //超時時間
}).then(function(canvas) {
let dataUrl = canvas.toDataURL()
console.log(dataUrl)
})
crossOrigin
屬性設定成Anonymous
就可以跨域? - 並不可以的哦!
- 後臺解決跨域問題
- 轉成
base64
格式(後端,前端,建議前端)
html5移動端生成海報
大致效果:
<script>
var code_model = '<div id="qrcode" style="position: fixed; opacity: 0;"></div>', // 放置二維碼
canvas_model = '<canvas width="1200" height="800" style="position: fixed;opacity:0;" id="myCanvas"></canvas>', // 放置canvas
poster_model = '<div class="poster_container"><div class="poster"><img src="" alt="" class="poster_img"><p class="save_poster">長按儲存圖片至手機相簿</p><p style="margin-top: 0.5rem" class="aaaa"></p></div></div>';
//poster_model為效果圖
$("body").append(code_model, canvas_model, poster_model);
$.ajax({
url: "/photo/dada",
data: {
id: id
},
success: function (res) {
$.hideLoading();
if (res.e = "1111") {
if (!res.data.is_buy) {
location.href = res.data.jump_url;
return false;
}
$(".poster").show();
var data_base = res.data.poster_info;
new QRCode('qrcode', {
text: data_base.url,
width: 100,
height: 100,
colorDark: '#000000',
colorLight: '#ffffff',
correctLevel: QRCode.CorrectLevel.H
});
var c = document.getElementById("myCanvas"),
cxt = c.getContext("2d");
var img = new Image(), imgUrl, personName = data_base.name;
//跨域問題
img.crossOrigin = 'anonymous';
img.src = data_base.image;
img.onload = function () {
//圖片載入為非同步載入
cxt.drawImage(img, 0, 0);
cxt.save();
cxt.beginPath();
cxt.arc(100, 200, 33, 0, 2 * Math.PI, true);
cxt.strokeStyle = '#fff';
cxt.stroke();
cxt.clip();
var img_head = new Image();
img_head.crossOrigin = 'anonymous';
var avatar_height = data_base.avatar_height, avatar_width = data_base.avatar_width;
img_head.src = data_base.avatar;
img_head.onload = function () {
cxt.drawImage(img_head, 0, 0, avatar_height, avatar_width, 54, 520, 80, 80);
cxt.restore();
var img_code = new Image();
img_code.crossOrigin = 'anonymous';
cxt.lineWidth = "4";
cxt.strokeStyle = '#FFF';
cxt.rect(80, 80, 400, 400);
cxt.stroke();
setTimeout(function () {
img_code.src = $("#qrcode").find("img").attr("src");
img_code.onload = function () {
cxt.drawImage(img_code, 0, 0, 100, 100, 450, 450, 80, 80);
cxt.font = '21px 黑體';
cxt.fillStyle = "#000";
cxt.fillText(personName, 250, 520);
imgUrl = c.toDataURL("image/png", 1);
$(".poster_img").attr("src", imgUrl);
$(".poster_container").show();
};
}, 0);
};
};
} else {
$.toast(res.m, "text");
}
}
});
</script>
微信小程式所使用的繪圖api
CanvasContext
`canvas` 元件的繪圖上下文
CanvasContext
是舊版的介面, 新版 Canvas 2D
介面與 Web
一致。
string|CanvasGradient fillStyle
- 填充顏色string|CanvasGradient strokeStyle
- 邊框顏色number shadowOffsetX
- 陰影相對於形狀在水平方向的偏移number shadowOffsetY
- 陰影相對於形狀在豎直方向的偏移number shadowColor
- 陰影的顏色number shadowBlur
- 陰影的模糊級別number lineWidth
- 線條的寬度string lineCap
- 線條的端點樣式string lineJoin
- 線條的交點樣式
lineJoin
值 | 說明 |
---|---|
bevel | 斜角 |
round | 圓角 |
miter | 尖角 |
number miterLimit
- 最大斜接長度number lineDashOffset
- 虛線偏移量,初始值為0
幾個相關的畫圖api 點這裡
<view class="photoCan">
<canvas style="width: 375px; height: 612px; position:fixed; top:9999px; left:0; z-index:223;" canvas-id="mycanvas"></canvas>
<image src="{{imagePath}}" mode="widthFix"></image>
</view>
const app = getApp()
const setText = (context, fs, color, x, y, c) => {
context.setFontSize(fs);
context.setFillStyle(color);
context.setTextAlign('left');
context.fillText(c, x, y);
context.restore();
};
Page({
data: {
imagePath:''
},
onLoad(){
var that=this;
wx.downloadFile({
url: 'https://xxxx.com/image',
success: function (res) {
that.setData({
path: res.tempFilePath
})
}
})
var ctx = wx.createCanvasContext('mycanvas');
var c_avatar = '../image/timg2.jpg';
var wechat = '../image/wechat.png';
var path = that.data.path;
ctx.fillStyle = "#ffe200";
ctx.fillRect(0, 0, 375, 612);
setText(ctx, 16, '#xxx', 90, 45, '達達);
// 繪製畫報背景圖
ctx.drawImage(path, 30, 95, 400, 500);
//頭像
ctx.arc(45, 45, 25, 0, 2 * Math.PI)
ctx.strokeStyle = "#fff";
ctx.clip();
ctx.drawImage(c_avatar, 20, 20, 50, 50);
// 繪製生成畫報
ctx.draw(true, setTimeout(function () {
// 儲存
wx.canvasToTempFilePath({
canvasId: 'mycanvas',
success: function (res) {
console.log(res)
var tempFilePath = res.tempFilePath;
that.setData({
imagePath: tempFilePath
});
},
fail: function (res) {
console.log(res);
}
})
}, 1000));
}
})
點關注,不迷路
好了各位,以上就是這篇文章的全部內容,能看到這裡的人都是人才。我後面會不斷更新網路技術相關的文章,如果覺得文章對你有用,歡迎給個“贊”,也歡迎分享,感謝大家 !!