H5 canvas基礎與「生成名片」小程序

要建立一個canvas,其實只要在HTML中添加標籤:<canvas></canvas> 就好了。 如果考慮瀏覽器的兼容問題,只需在標籤中加上一行文字:javascript

<canvas>
	您的瀏覽器不支持canvas
</canvas>
複製代碼

便可達到「 友好提示用戶 」的效果。html

若是要「畫東西」,也就是所謂的「操縱canvas元素」,則必要藉助於DOM事件:java

//獲取canvas
var canvas=document.querySelector('canvas標籤中的id/class名');
//獲取「上下文對象「
var ctx=canvas.getContext("2d");
複製代碼

其中「上下文對象」你能夠理解爲是「繪圖的環境(參數)」,而「2d」表明「要繪製2d(平面)圖形」 —— 一樣的,「3d」表示「繪製3d(立體)圖形」。canvas

canvas坑一: 若要改變canvas「畫布」的大小,最好在canvas標籤的style屬性中或在JS中動態進行。若經過class/id-style中修改(執行),會形成「總體縮放」——包括後面說到的lineTo線條也是這樣。瀏覽器

//style
.canvas{
	border: 1px solid red;
	width: 200px;
	height: 200px;
}
//html
<canvas class="canvas">
	您的瀏覽器不支持canvas
</canvas>
//JS
var canvas=document.querySelector('.canvas');
var ctx=canvas.getContext("2d");
console.log(canvas.width,canvas.height);  //canvas中能夠直接操做canvas所用到屬性的各個CSS,這個後面還會提到
//下面三行先沒必要管
ctx.moveTo(0,0);
ctx.lineTo(200,200);
ctx.stroke()
複製代碼

left

JS操控canvas

上面說了,經過JS操做canvas元素前要先dom

  1. 獲得元素
  2. 獲取環境(參數)

下面的一些demo就省去這兩行代碼了。。。函數

首先,你要畫好比一條線/一個圖的話,假如canvas如今是你手中的一杆畫筆,那你就要先「提筆」 —— 從哪開始畫:字體

ctx.moveTo(0,0);   //移動到【畫布的】(0,0)座標處「落筆」
複製代碼

moveTo的兩個參數分別是:起始座標X、Y。 而後 如果畫直線,能夠調用lineTo - API:動畫

ctx.lineTo(100,100);   //從畫布的(0,0)處「畫」到(100,100)處
複製代碼

而後其實能夠繼續lineTo()...ui

ctx.lineTo(100,200);   //從畫布的(100,100)處「畫」到(100,200)處
複製代碼

這時,這些線條還只是在【內存】中,要其真正顯示到頁面上,則需調用stroke():

ctx.stroke();
複製代碼

ctx坑二: 若要再畫一條線,很多初學者可能會將以上「繪製」部分代碼再CV一遍,改變座標即「大功告成」,可是真是這樣的嗎? 經檢驗,第一條線要「深色」一些:這是由於整段代碼有兩個stroke() —— 即第一條線被「畫」了兩次。

其實若要畫多個圖形,只要先把moveTo、lineTo...所有完成,再調用一次 ctx.stroke(); 便可。 但這樣一來又有一個問題:如果就想讓兩條線顏色不同怎麼辦? canvas API提供了下面的函數:

ctx.beginPath();   //開啓一條「新的」內存路徑
複製代碼

只要把這個函數加到「第二條繪製線」的moveTo函數前便可。

canvas畫圖形

上面是畫線,那麼諸如圓、長方形...這些圖形怎麼畫?

圓形:ctx.arc(參數1,參2,參3,起始弧度,終止弧度,順時針/逆時針畫);

  • 參1:圓心座標X
  • 參2:圓心座標Y
  • 參3:半徑r
  • 最後一個參數:true表明「逆時針」,false爲「順時針」
ctx.arc(300,300,50,0,2*Math.PI,true);
ctx.stroke();
複製代碼

矩形:ctx.strokeRect(左上角X,左上角Y,寬,高); (由於是strokeRect這種stroke前綴的函數其實都是通過stroke()封裝過的,因此能夠直接顯示在屏幕上)

其實,矩形還有兩種畫法:

  • 經過lineTo畫四條線,最後一條的終點座標和第一條的起點座標相同
  • 經過lineTo畫三條線,最後經過「閉合函數」:ctx.closePath() 將圖形路徑閉合

曾經看到好多「圖片+JS雪花掉落效果」,其實這個用canvas也能夠實現:

var circles = [];
setInterval(function() {
  // 擦出畫布
  animCtx.clearRect(0, 0, animCtx.canvas.width, animCtx.canvas.height);   //animCtx是canvas元素上下文對象
  // 繪製下落的圓形
  for(var i=0; i<=10; i++) {
    if(!circles[i]) {   //保證每片「雪花」垂直下落
      circles[i] = {};
      circles[i].radius = Math.floor(Math.random() * 5) + 1;
      circles[i].y = - circles[i].radius - Math.floor(Math.random() * 10);
      circles[i].x = i * 60 + Math.floor(Math.random() * 10) - 5;
      circles[i].vy = Math.floor(Math.random() * 5) + 1;
    }
    animCtx.beginPath();
    animCtx.arc(circles[i].x, circles[i].y, circles[i].radius, 0, Math.PI * 2);
    animCtx.fillStyle = "rgba(255, 255, 255, 0.5)";
    animCtx.fill();
    circles[i].y = circles[i].y + circles[i].vy;
    if(circles[i].y > animCtx.canvas.height + circles[i].radius * 2) {
      circles[i] = undefined;
    }
  }
}, 100);
複製代碼

JS填充canvas與canvas描邊

上面的圖形畫着是挺爽的,就是顏色未免太單一了一些: 咱們能夠經過 ctx.fill() 填充函數填充整個圖形(內部)爲「黑色」(默認顏色)(視覺上看「自動閉合了路徑」)emmmmmmm,這樣所有都變成黑色了,不過我能夠在前面用 ctx.fillStyle="顏色值" 來改變整個圖形的顏色。

如果要只改變圖形邊框的顏色呢?其實上面說的一個函數自己就有「描邊」的功能:ctx.stroke() 。 你固然能夠理解爲「只有爲圖形邊框添加了顏色,才能顯示出來」,毫無疑問,它默認也是黑色的。不過咱們也能夠用API:ctx.strokeStyle="顏色值" 來改變圖形邊框的顏色。 咱們還能夠經過 ctx.lineWidth=數字值; 來改變邊框的寬度。

canvas中容許「邊框設置」和「填充設置」同時出現。

JS圖形變換(平移、旋轉、縮放)

如上面「畫線」所說:

ctx.moveTo(0,0);
ctx.lineTo(100,100);
ctx.stroke();
複製代碼

平移:ctx.translate(X方向,Y方向); 你們能夠試下分別將translate函數放在moveTo前、lineTo前、最後,分別有什麼效果!

旋轉:ctx.rotate(旋轉角度); —— 以弧度爲單位:

//旋轉45°
ctx.rotate(Math.PI / 4);
複製代碼

縮放:ctx.scale(X軸縮放,Y軸縮放);

//X軸不縮放,Y軸變爲原來的1/2
ctx.scale(1,0.5);
複製代碼

圖形變換的效果也會「自上而下疊加」!

若是以爲疊加效果並非想要的,能夠將某個變換片斷代碼放到 ctx.save() 【保存環境函數】和 ctx.restore() 【恢復環境函數】(恢復到save()函數以前的環境)的「包裹」中。

canvas文字

var str="hello world";
複製代碼

咱們怎麼把展現到canvas畫布中呢?

ctx.fillText(str,0,100);   //參數:文字,X座標,Y座標
//或
ctx.strokeText(str,0,200);   //如有顏色,則上面的爲填充,這裏爲描邊(字體呈鏤空效果)
複製代碼

填充:

tc

能不能改變他的樣式? (開頭說了一句「canvas裏能直接改變元素CSS樣式值」不知道你們還記得不記得)

ctx.font="50px sans-serif";   //改變字體大小
複製代碼

而且加上strokeText函數:

ys
也能夠改變文字的位置,如:

ctx.textAlign="center";   //文字居中(水平)
複製代碼
ctx.textBaseline="middle";   //文字垂直居中
複製代碼

既然能控制大小和位置,確定也能獲取一些自身信息:

let width=ctx.measureText(str).width;   //獲取文本寬度
複製代碼

這樣,咱們就能作一些有意義的事,好比文本X/Y座標是多少時設置Align才能讓水平居中、好比根據一個元素的width(文字字數)控制另外一個元素的位置。。。這些都在末尾demo中有用到。

很遺憾的是,canvas並不支持獲取文本的「高度」

在canvas中展現圖片

canvas做爲一個「特殊的結構」,其圖片的展現方式確定也不一樣尋常:

//加載圖片對象
let img=new Image();
//設置src屬性
img.src="xxx.xx";
//展現
ctx.drawImage(img,0,0);   //ctx.drawImage(img對象,左上角X座標,左上角Y座標);
複製代碼

而後咱們「自信滿滿地」打開圖片,發現...沒有東西!!!

這是由於Image()的加載須要必定時間,而咱們直接插入了src:切記!必定要在load中完成img的「展現」。(和H5的File()加載展現同樣的道理)

img.onload=function(){
	ctx.drawImage(img,0,0);
}
複製代碼

這樣完成是完成了,但圖片樣式是固定的,很差看啊。 不要緊,咱們有「第二種展現方法」,能夠將其進行縮放:

ctx.drawImage(img對象,左上角X座標,左上角Y座標,寬,高);
複製代碼

而後咱們又發現縮放後圖片中圖標是挺好看的,但文字太模糊了,難受的一批,因而咱們想:怎麼把圖標單獨顯示出來呢? 不要緊,咱們還有「第三種展現方法」:

ctx.drawImage(img對象,截取起點X座標,截取起點Y座標,截取終點X座標,截取終點Y座標,繪製位置X座標,繪製位置Y座標,寬,高);
複製代碼

其實「圖片」的展現還有一種方式 —— 圖形畫刷 ,它能夠將圖片爲背景填充展現到canvas區域:

var pattern=ctx.createPattern(img對象,"模式");
ctx.fillStyle=pattern;
複製代碼

其中,「模式」和CSS中【背景圖片】的展現也很相似:

  • no-repeat
  • repeat
  • repeat-x
  • repeat-y

canvas陰影設置

  • X軸偏移:ctx.shadowOffsetX=數字值; (數字值相對於圖形)
  • Y軸偏移:ctx.shadowOffsetY=數字值; (數字值相對與圖形)
  • 陰影顏色:ctx.shadowColor='顏色值如:rgba(0,0,0,0.2)';
  • 模糊半徑:ctx.shadowBlur=數字值;

陰影會做用於其下全部設置的canvas上(文本、圖形、圖片...)

離屏canvas

這個在大加載量、頻繁JS動畫 and DOM重繪量巨大的場景下應用極廣。它基於這樣的原理:把涉及大量DOM重繪、頻繁加載的元素(好比小球運動場景下的背景格的樣式改變)單獨拿出來放在某位置地方(display:none;)本身加載,在觸發操做後,經過:

真實canvas元素上下文對象.drawImage(離屏canvas元素, 起始位置X, 起始位置Y, 真實canvas元素寬, 真實canvas元素高,起始位置X, 起始位置Y, 離屏canvas元素寬,離屏canvas元素高);
複製代碼

將元素的「樣子」刻畫到主要顯示的canvas上!

要記得「適當地」擦乾畫布:canvas元素上下文對象.clearRect()


canvas名片生成程序代碼

代碼較多,已打包到百度網盤,可直接免費下載:

連接 提取碼
pan.baidu.com/s/1EIJp0MNA… xqwk

canvas生成的圖形能夠做爲圖片保存


本文首發於@csdn:yunxiaomeng.blog.csdn.net/article/det…

相關文章
相關標籤/搜索