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()