arc(x, y, r, start, stop)
moveTo(x, y) 定義線條開始座標lineTo(x, y) 定義線條結束座標css
fill()
stroke()
<canvas id="canvas" width="700" height="600"> 瀏覽器不支持canvas! </canvas>
<canvas>
元素let canvas = document.getElementById("canvas");
context
對象let ctx = canvas.getContext("2d");
// 座標(x, y)、半徑、開始角度、結束角度、順時針(逆時針) ctx.arc(70, 80, 30, 0, Math.PI * 2, false);
//生成點 for (let i = 0; i < dotsNum; i ++) { x = Math.random() * canvas.width; y = Math.random() * canvas.height; r = Math.random() * 4; // 隨機生成 <4 的半徑值 ctx.beginPath(); ctx.arc(x, y, r, 0, 2 * Math.PI); ctx.fillStyle = "rgba(0,0,0,.8)"; ctx.fill(); ctx.closePath(); }
肯定兩個點的座標 + lineTo 、moveTo
for (let i = 0; i < 2; i++) { ctx.beginPath() // 設置原點位置爲(100,100),半徑爲10 ctx.arc(100 + i * 150, 100 + i * 250, 10, 0, Math.PI * 2, false) // 兩個點進行畫線 ctx.moveTo(100, 100) ctx.lineTo(100 + i * 150, 100 + i * 250) // 設置線的寬度,單位是像素 ctx.lineWidth = 2 ctx.stroke() // 實心圓 - 填充顏色,默認是黑色 // 實心圓 - 畫實心圓 ctx.fill() ctx.closePath() }
當點不少、元素不少的時候再進行畫線操做會很繁瑣,對於多元素的狀況,建立實例對象,把變量存儲在實例對象上。web
var Dots = function () { // 畫布 this.canvas; this.ctx; // 畫點 this.x; this.y; this.r; };
Dots.prototype = { // 初始化點的方法 init: function (canvas) { this.canvas = canvas; this.ctx = this.canvas.getContext('2d'); this.x = Math.random() * this.canvas.width; this.y = Math.random() * this.canvas.height; this.r = Math.random() * 4; // 隨機生成 <4 的半徑值 this.ctx.beginPath(); this.ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI); this.ctx.fillStyle = "black"; this.ctx.fill(); this.ctx.closePath(); } };
// 繪製連線 for (var i = 0; i < dotsNum; i ++) { for (var j = i + 1; j < dotsNum; j ++) { var tx = dotsArr[i].x - dotsArr[j].x, ty = dotsArr[i].y - dotsArr[j].y, // 三角形斜邊長 s = Math.sqrt(Math.pow(tx, 2) + Math.pow(ty, 2)); if (s < dotsDistance) { ctx.beginPath(); ctx.moveTo(dotsArr[i].x, dotsArr[i].y); ctx.lineTo(dotsArr[j].x, dotsArr[j].y); ctx.strokeStyle = 'rgba(0,0,0,'+(dotsDistance-s)/dotsDistance+')'; ctx.strokeWidth = 1; ctx.stroke(); ctx.closePath(); } } }
點與點之間連線canvas
優化點:
限定點與點的連線距離(優化:根據點之間的距離添加連線顏色透明度)瀏覽器
Canvas 畫布的工做原理和顯示器工做原理同樣,都是經過不斷的刷新繪製。瀏覽器的刷新是實時的,而 Canvas 的刷新是手動觸發的,若是咱們只想在 Canvas 上實現靜態的效果,就沒必不斷刷新。dom
requestAnimationFrame
是瀏覽器用於定時循環操做的一個接口,相似於setTimeout,主要用途是按幀
對網頁進行重繪。requestAnimationFrame
不是本身指定回調函數運行的時間,而是跟着瀏覽器內建的刷新頻率來執行回調。函數
瀏覽器能夠優化並行的動畫動做,更合理的從新排列動做序列,並把可以合併的動做放在一個渲染週期內完成,從而呈現出更流暢的動畫效果,一旦頁面不處於瀏覽器的當前標籤,就會自動中止刷新。優化
持續調用 requestAnimFrame清除動畫調用 cancelAnimationFrame動畫
var canvas = document.querySelector('canvas'); var context = canvas.getContext('2d'); // 畫布渲染 var render = function () { // 清除畫布 context.clearRect(0, 0, canvas.width, canvas.height); // 繪製(在canvas畫布上繪製圖形的代碼) draw(); // 繼續渲染 requestAnimationFrame(render); }; render();
上面的draw()
就是在 canvas 畫布上繪製圖形的代碼,可是若是僅僅有上面代碼還不夠,若是是同一個位置不斷刷新,咱們看到的仍是靜止不動的效果,因此還須要一個運動變量。this
var canvas = document.querySelector('canvas'); var context = canvas.getContext('2d'); // 座標變量 var x = 0; // 繪製方法 var draw = function () { ball.x = x; }; // 畫布渲染 var render = function () { // 清除畫布 context.clearRect(0, 0, canvas.width, canvas.height); // 位置變化 x++; // 繪製 draw(); // 繼續渲染 requestAnimationFrame(render); }; render();
動的是點,畫的是線prototype
let Dots = function () { // 畫布 this.canvas; this.ctx; // 畫點 this.x; this.y; this.r; // 移動 // 隨機肯定點的移動速度與方向 速度值在 [-2, 2) 之間 提升數值可加快速度 //(Math.random() 隨機返回[0,1)的數) this.sx = Math.random() * 4 - 2; this.sy = Math.random() * 4 - 2; };
update()
// 更新點位置 update: function () { this.x = this.x + this.sx; this.y = this.y + this.sy; // 點超出 canvas 範圍時從新初始化 if (this.x < 0 || this.x > this.canvas.width) { this.init(this.canvas); } if (this.y < 0 || this.y > this.canvas.height) { this.init(this.canvas); } this.ctx.beginPath(); this.ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI); this.ctx.fillStyle = "rgba(0,0,0,.6)"; this.ctx.fill(); this.ctx.closePath(); }
兼容 requestAnimationFrame
let requestAnimFrame = requestAnimationFrame || webkitRequestAnimationFrame || oRequestAnimationFrame || msRequestAnimationFrame; requestAnimFrame(animateUpdate); // 兼容不一樣瀏覽器的 requestAnimationFrame
或者使用 setTimeout 向下兼容:
// requestAnimationFrame的向下兼容處理 if (!window.requestAnimationFrame) { window.requestAnimationFrame = function(fn) { setTimeout(fn, 17); }; }
因爲點的位置不斷變換,所以須要將畫線的操做放在動畫內執行,點的位置 update 一次就執行一次連線。
function animateUpdate() { ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空canvas中原有的內容 for (let i = 0; i < dotsNum; i ++) { dotsArr[i].update(); } // 繪製連線 for (let i = 0; i < dotsNum; i ++) { for (let j = i + 1; j < dotsNum; j ++) { let tx = dotsArr[i].x - dotsArr[j].x, ty = dotsArr[i].y - dotsArr[j].y, // 三角形斜邊長 s = Math.sqrt(Math.pow(tx, 2) + Math.pow(ty, 2)); if (s < dotsDistance) { ctx.beginPath(); ctx.moveTo(dotsArr[i].x, dotsArr[i].y); ctx.lineTo(dotsArr[j].x, dotsArr[j].y); ctx.strokeStyle = 'rgba(0,0,0,'+(dotsDistance-s)/dotsDistance+')'; ctx.strokeWidth = 1; ctx.stroke(); ctx.closePath(); } } } // 繼續渲染 requestAnimFrame(animateUpdate); }
星空效果、下雨效果等
不要在style裏指定 Canvas 的寬度,Canvas 畫布的尺寸的大小和顯示的大小是有很大的區別的,在 canvas 裏面設置的是纔是 Canvas 自己的大小。
若是不給<canvas>
設置 width、height 屬性時,則默認 width 爲 300、height 爲 150, 單位都是 px。也能夠使用 css 屬性來設置寬高,可是如寬高屬性和初始比例不一致,他會出現扭曲。因此, 建議永遠不要使用css屬性來設置<canvas>
的寬高。
畫新元素前記得要 beginPath()