什么软件能绘画canvas(用canvas让美女沉浸在音符的海洋里)

今天跟大家聊点轻松的话题——《用canvas让美女沉浸在音符的海洋里》,效果如下所示:

什么软件能绘画canvas(用canvas让美女沉浸在音符的海洋里)(1)

一、前期准备

为了能够实现这个效果,要进行如下准备:

  1. 一张梦寐以求的美女图片;
  2. 能够简单使用canvas;
  3. 准备一些音乐符号;
  4. 准备编辑器,由于该内容很偏向于实战,边敲边看效果更佳。
二、具体实现

美女图片仅仅是作为背景使用,所以就不过多的讲述了,直接设置一下background属性即可,下面主要讲述一下音符动画的实现。

2.1 音符符号

音符符号都可以用文字表示出来,没必要一个个自己去画,自己收集了一些,如下表格所示:【哎、当时自己不知道,还想着怎么画呢,最后经过一波神奇的百度才知道原来直接写文字就行,展示毫无障碍】

音符符号

含义

八分音符

二个八分音符

十六分音符

降记号

升记号

音乐符号g谱号

音乐自然标志

竖琴

……

2.2 封装绘制文字的类

既然音符符号可以用文字表示,那复杂的事情就变得简单了,直接封装一个绘制文字的类,话不多说开整。

// index.js class Draw { // 传入一个canvas的DOM节点 constructor(canvasDom) { this._canvasDom = canvasDom; this.ctx = this._canvasDom.getContext('2d'); this.width = this._canvasDom.width; this.height = this._canvasDom.height; } // 清空画布,毕竟要让音符动起来,不清空画布那还了得 clearCanvas() { this.ctx.clearRect(0, 0, this.width, this.height); } // 根据传入的参数绘制文字 drawText(textObj) { const { x, y, rotateRad, font, content, fillStyle = '#000000', textAlign = 'start', textBaseline = 'middle' } = textObj; this.ctx.save(); this.ctx.translate(x, y); this.ctx.rotate(rotateRad); this.ctx.fillStyle = fillStyle; this.ctx.textAlign = textAlign; this.ctx.textBaseline = textBaseline; this.ctx.font = font; this.ctx.fillText(content, 0, 0); this.ctx.restore(); } }

2.3 创建文字条件

在封装文字类的时候已经发现其接收一个对象,然后根据对象来进行绘制,那我们接下来就是要根据需求创建一个这样的对象,怎么创建呢?如下所示:

// index.js /** * @param {string} content 绘制的内容 * @param {object} canvasObj canvas相关的内容 * param {object} conditionsObj 生成文字配置所需要的条件 */ function createTextObj(content, canvasObj, conditionsObj) { const {width, height} = canvasObj; const { fontMin = 20, fontMax = 40, direction = 3, // 0:从左到右;1:从右到左;2:从上到下;3:从下到上 baseStep = 0.5 } = conditionsObj; let textX = 0; let textY = 0; // 注意:这个位置预制了direction条件,因为咱们的音符要动起来,所以设置一下从哪个方向进行浮动 // 预制的初始坐标肯定不能被我们看到,所以需要根据方向决定初始坐标 switch(direction) { case 0: { textX = (-0.1 - 0.1 * Math.random()) * width; textY = Math.random() * height; break; } case 1: { textX = (1.1 0.1 * Math.random()) * width; textY = Math.random() * height; break; } case 2: { textX = Math.random() * width; textY = (-0.1 - 0.1 * Math.random()) * height; break; } case 3: { textX = Math.random() * width; textY = (1.1 0.1 * Math.random()) * height; break; } } // 都是一个方位也不好看呀,所以要旋转一下 const rotateRad = Math.PI * Math.random(); const font = Math.random() * (fontMax - fontMin) fontMin 'px serif'; // 设置一下直线运动和旋转运动的步长 const step = Math.random() baseStep; const rotateStep = Math.random() * Math.PI / 100; const fillStyle = 'rgba(' Math.random() * 255 ',' Math.random() * 255 ',' Math.random() * 255 ',' (0.5 0.5 * Math.random()) ')'; return { x: textX, y: textY, rotateRad, font, fillStyle, content, step, rotateStep, direction }; }

2.4 更新文字配置

既然音符会动起来,则咱们就要逐帧进行更新,那更新函数就不能避免了,更新函数如下所示:

// index.js /** * @param {object} canvasObj canvas相关的内容 * @param {Array} textObjArr 文字配置对象的数组 * param {object} conditionsObj 生成文字配置所需要的条件 */ function updateTextObjArr(canvasObj, textObjArr, conditionsObj) { const {width, height} = canvasObj; textObjArr.forEach((textObj, index) => { const {step, rotateStep, x, y, direction} = textObj; // 根据运动方向做对应的更新 // 当音符符号运动出可视区域后直接在生成一个新的音符,毕竟要保证整个音符的数量 switch(direction) { case 0: { if (x > width 10) { textObjArr[index] = createTextObj(getRandomValFromArr(TEXT_CONTENT_ARR), canvasObj, conditionsObj); } else { textObj.x = step; } break; } case 1: { if (x < -10) { textObjArr[index] = createTextObj(getRandomValFromArr(TEXT_CONTENT_ARR), canvasObj, conditionsObj); } else { textObj.x -= step; } break; } case 2: { if (y > height 10) { textObjArr[index] = createTextObj(getRandomValFromArr(TEXT_CONTENT_ARR), canvasObj, conditionsObj); } else { textObj.y = step; } break; } case 3: { if (y < -10) { textObjArr[index] = createTextObj(getRandomValFromArr(TEXT_CONTENT_ARR), canvasObj, conditionsObj); } else { textObj.y -= step; } break; } } textObj.rotateRad = rotateStep; }); return textObjArr; }

2.5 动起来

万事俱备,只欠东风,下面就是我们调动这些函数让整个内容动起来的关键时刻

<!DOCTYPE html> <html> <head> <title>音乐字符</title> <style> canvas { width: 500px; height: 300px; background: url('https://gimg2.baidu.com/image_search/src=http://www.1230530.com/public/uploads/images/20211017/2538_20211017231117c46c5.jpg&refer=http://www.1230530.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1649658529&t=2b38137ce9cb301fc27a869e40b58629'); background-size: 100% 100%; } </style> </head> <body> <canvas width="500" height="300" id="canvasId"></canvas> <script src="./index.js"></script> <script> // 从数组中随机获取一个值 function getRandomValFromArr(arr) { return arr[Math.floor(Math.random() * arr.length)]; } // 创建一系列的文字对象 function createTextObjArr(count, canvasObj, conditionsObj) { const textObjArr = []; for (let i = 0; i < count; i ) { textObjArr.push(createTextObj(getRandomValFromArr(TEXT_CONTENT_ARR), canvasObj, conditionsObj)); } return textObjArr; } // 初始音符 const TEXT_CONTENT_ARR = ['♪', '♫', '♬', '♭', '♯', '', '♮', '']; // canvas节点 const canvasDom = document.getElementById('canvasId'); // 获取绘制文字的实例 const drawInstance = new Draw(canvasDom); const canvasObj = { width: drawInstance.width, height: drawInstance.height }; // 生成30个随机音符符号 const count = 30; const conditionsObj = { direction: 2 }; const textObjArr = createTextObjArr(count, canvasObj, conditionsObj) // 动画动起来 function animate() { drawInstance.clearCanvas(); textObjArr.forEach(textObj => drawInstance.drawText(textObj)); window.requestAnimationFrame(animate); updateTextObjArr(canvasObj, textObjArr, conditionsObj); } animate(); </script> </body> </html>

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页