canvas

183 阅读2分钟

介绍 最早由 Apple 引入 WebKit,用于 Mac OS X 的 Dashboard,随后被各个浏览器实现。如今,所有主流的浏览器都支持它。Canvas API 提供了一个通过 JavaScript 和 HTML 的 元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。Canvas 适合绘制大数据量图形元素的图表(如热力图、地理坐标系或平行坐标系上的大规模线图或散点图等),也适合实现某些视觉特效。它还能能够以 png、jpg 或 webp 格式保存图像。Canvas 提供了强大的 Web 绘图能力,所以我们要学会使用它。

效果如下:

CPT2211112159-785x407.gif

步骤 为了兼容旧浏览器,所以没有使用 ES6(块级作用域变量声明和 class 类)。

准备一个 canvas 元素。 获取 canvas 对象和上下文,初始化变量:窗口宽高、爱心数量、爱心数组。 var canvas = document.getElementById('drawHeart'); var ctx = canvas.getContext('2d'); var wW = window.innerWidth; var wH = window.innerHeight; var num = 100; var hearts = []; 定义一个获取随机颜色的方法,用来动态渲染屏幕文字颜色。 function getColor() { var val = Math.random() * 10; if (val > 0 && val <= 1) { return '#00f'; } else if (val > 1 && val <= 2) { return '#f00'; } else if (val > 2 && val <= 3) { return '#0f0'; } else if (val > 3 && val <= 4) { return '#368'; } else if (val > 4 && val <= 5) { return '#666'; } else if (val > 5 && val <= 6) { return '#333'; } else if (val > 6 && val <= 7) { return '#f50'; } else if (val > 7 && val <= 8) { return '#e96d5b'; } else if (val > 8 && val <= 9) { return '#5be9e9'; } else { return '#d41d50'; } } 定义一个获取随机文字的方法,用来动态渲染屏幕文字。 function getText() { var val = Math.random() * 10; if (val > 1 && val <= 3) { return 'always'; } else if (val > 3 && val <= 5) { return 'zzy'; } else if (val > 5 && val <= 8) { return 'taylor swift'; } else { return 'I Love You'; } } 定义一个构造函数,参数 type 标识用来判断实例为爱心图片还是文字类型。 function Heart(type) { this.type = type; // 初始化生成范围 this.x = Math.random() * wW; this.y = Math.random() * wH; this.opacity = Math.random() * .5 + .5; // 偏移量 this.vel = { x: (Math.random() - .5) * 5, y: (Math.random() - .5) * 5 } this.initialW = wW * .5; this.initialH = wH * .5; // 缩放比例 this.targetScale = Math.random() * .15 + .02; // 最小0.02 this.scale = Math.random() * this.targetScale; // 文字位置 this.fx = Math.random() * wW; this.fy = Math.random() * wH; this.fs = Math.random() * 10; this.text = getText(); this.fvel = { x: (Math.random() - .5) * 5, y: (Math.random() - .5) * 5, f: (Math.random() - .5) * 2 } } 定义爱心图片,图片 src 可以是 base64 类型或者本地图片文件和网络图片链接。 var heartImage = new Image(); heartImage.src = 'data:image/svg+xml;charset=utf-8,'; 在函数原型上定义重绘和更新方法。 Heart.prototype.draw = function() { ctx.save(); ctx.globalAlpha = this.opacity; ctx.drawImage(heartImage, this.x, this.y, this.width, this.height); // ctx.scale(this.scale + 1, this.scale + 1); if (!this.type) { // 设置文字属性 ctx.fillStyle = getColor(); ctx.font = 'italic ' + this.fs + 'px sans-serif'; // 填充字符串 ctx.fillText(this.text, this.fx, this.fy); } ctx.restore(); } Heart.prototype.update = function() { this.x += this.vel.x; this.y += this.vel.y; if (this.x - this.width > wW || this.x + this.width < 0) { // 重新初始化位置 this.scale = 0; this.x = Math.random() * wW; this.y = Math.random() * wH; } if (this.y - this.height > wH || this.y + this.height < 0) { // 重新初始化位置 this.scale = 0; this.x = Math.random() * wW; this.y = Math.random() * wH; } // 放大 this.scale += (this.targetScale - this.scale) * .1; this.height = this.scale * this.initialH; this.width = this.height * 1.4; // -----文字----- this.fx += this.fvel.x; this.fy += this.fvel.y; this.fs += this.fvel.f; if (this.fs > 50) { this.fs = 2; } if (this.fx - this.fs > wW || this.fx + this.fs < 0) { // 重新初始化位置 this.fx = Math.random() * wW; this.fy = Math.random() * wH; } if (this.fy - this.fs > wH || this.fy + this.fs < 0) { // 重新初始化位置 this.fx = Math.random() * wW; this.fy = Math.random() * wH; } } 定义渲染和初始化方法,添加 resize 事件,在窗口调整大小时自动适应。 function render() { ctx.clearRect(0, 0, wW, wH); for (var i = 0; i < hearts.length; i++) { hearts[i].draw(); hearts[i].update(); } setTimeout(render, 80); } function init() { canvas.width = wW; canvas.height = wH; for (var i = 0; i < num; i++) { hearts.push(new Heart(i % 5)); } setTimeout(render, 80); } window.addEventListener('resize', function() { wW = window.innerWidth; wH = window.innerHeight; }); init(); 马上掘金

参考资料 canvas实现满屏爱心