JS之Math.sin与Math.cos介绍及应用-实现鼠标点击后的烟花效果

  • A+
所属分类:Web前端
摘要

Math.sin(x) :x 的正玄值。返回值在 -1.0 到 1.0 之间;Math.cos(x) :x 的余弦值。返回的是 -1.0 到 1.0 之间的数;


基本介绍

Math.sin(x) :x 的正玄值。返回值在 -1.0 到 1.0 之间;

Math.cos(x) :x 的余弦值。返回的是 -1.0 到 1.0 之间的数;

其中函数中是x是指“弧度”而非角度。

弧度定义:两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧。当这段弧长正好等于圆的半径时,两条射线的夹角大小为1弧度(单位:rad)。

角度定义:两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧。当弧长正好等于圆周长的360分之一时,两条射线的夹角的大小为1度。(单位: º)

如图所示:

JS之Math.sin与Math.cos介绍及应用-实现鼠标点击后的烟花效果

 

角度转弧度(弧度计算公式):2π / 360  = π / 180 ≈ 0.0174rad, 即: 度数 * (π / 180) = 弧度

弧度转角度(角度计算公式): 360 / 2π  = 180 / π ≈ 57.3º,  即:   弧度 * (180 / π) = 度数

// 将30º转为弧度rad  30º * (π / 180)= 0.523320 rad     // 将0.523320rad转为度º  0.523320rad * (180 / π) = 29.9992352688º 

可参考:

特殊值:

30°
45°
60°
90°
120°
135°
150°
180°
270°
360°
弧度
0
π/6
π/4
π/3
π/2
2π/3
3π/4
5π/6
π
3π/2

正弦函数和余弦函数的图像如图所示:

JS之Math.sin与Math.cos介绍及应用-实现鼠标点击后的烟花效果

实例

实例1:如何得到圆上每个点的坐标?

解决思路:根据三角形的正玄、余弦来得值;

假设一个圆的圆心坐标是(a,b),半径为r,

则圆上每个点的X坐标=a + Math.sin(2*Math.PI / 360) * r ;Y坐标=b + Math.cos(2*Math.PI / 360) * r ;

实例2:如何求时钟的秒针转动一圈的轨迹?

假设秒针的初始值(起点)为12点钟方向,圆心的坐标为(a,b)。

解决思路:一分钟为60秒,一个圆为360°,所以平均每秒的转动角度为 360°/60 = 6°;

for(var times=0; times<60; times++) {        var hudu = (2*Math.PI / 360) * 6 * times;        var X = a + Math.sin(hudu) * r;        var Y = b - Math.cos(hudu) * r    //  注意此处是“-”号,因为我们要得到的Y是相对于(0,0)而言的。 }

注意:
1、本例是以“12点为起点, 角度增大时为顺时针方向“,求X坐标和Y坐标的方法是:
X坐标=a + Math.sin(角度 * (Math.PI / 180)) * r ;
Y坐标=b - Math.cos(角数 * (Math.PI / 180)) * r ;

2、一般“3点为起点, 角度增大时为逆时针方向“,求X坐标和Y坐标的方法是:
X坐标 = a + Math.cos(角度 * (Math.PI / 180)) * r;
Y坐标 = b - Math.sin(角度 * (Math.PI / 180)) * r;

实例3:使用Math.sin与Math.cos实现鼠标点击后的烟花效果

cursor-effects.js网上代码:

class Circle {   constructor({ origin, speed, color, angle, context }) {     this.origin = origin     this.position = { ...this.origin }     this.color = color     this.speed = speed     this.angle = angle     this.context = context     this.renderCount = 0   }    draw() {     this.context.fillStyle = this.color     this.context.beginPath()     this.context.arc(this.position.x, this.position.y, 2, 0, Math.PI * 2)     this.context.fill()   }    move() {     this.position.x = (Math.sin(this.angle) * this.speed) + this.position.x     this.position.y = (Math.cos(this.angle) * this.speed) + this.position.y + (this.renderCount * 0.3)     this.renderCount++   } }  class Boom {   constructor ({ origin, context, circleCount = 10, area }) {     this.origin = origin     this.context = context     this.circleCount = circleCount     this.area = area     this.stop = false     this.circles = []   }    randomArray(range) {     const length = range.length     const randomIndex = Math.floor(length * Math.random())     return range[randomIndex]   }    randomColor() {     const range = ['8', '9', 'A', 'B', 'C', 'D', 'E', 'F']     return '#' + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range)   }    randomRange(start, end) {     return (end - start) * Math.random() + start   }    init() {     for(let i = 0; i < this.circleCount; i++) {       const circle = new Circle({         context: this.context,         origin: this.origin,         color: this.randomColor(),         angle: this.randomRange(Math.PI - 1, Math.PI + 1),         speed: this.randomRange(1, 6)       })       this.circles.push(circle)     }   }    move() {     this.circles.forEach((circle, index) => {       if (circle.position.x > this.area.width || circle.position.y > this.area.height) {         return this.circles.splice(index, 1)       }       circle.move()     })     if (this.circles.length == 0) {       this.stop = true     }   }    draw() {     this.circles.forEach(circle => circle.draw())   } }  class CursorSpecialEffects {   constructor() {     this.computerCanvas = document.createElement('canvas')     this.renderCanvas = document.createElement('canvas')      this.computerContext = this.computerCanvas.getContext('2d')     this.renderContext = this.renderCanvas.getContext('2d')      this.globalWidth = window.innerWidth     this.globalHeight = window.innerHeight      this.booms = []     this.running = false   }    handleMouseDown(e) {     const boom = new Boom({       origin: { x: e.clientX, y: e.clientY },       context: this.computerContext,       area: {         width: this.globalWidth,         height: this.globalHeight       }     })     boom.init()     this.booms.push(boom)     this.running || this.run()   }    handlePageHide() {     this.booms = []     this.running = false   }    init() {     const style = this.renderCanvas.style     style.position = 'fixed'     style.top = style.left = 0     style.zIndex = '999999999999999999999999999999999999999999'     style.pointerEvents = 'none'      style.width = this.renderCanvas.width = this.computerCanvas.width = this.globalWidth     style.height = this.renderCanvas.height = this.computerCanvas.height = this.globalHeight      document.body.append(this.renderCanvas)      window.addEventListener('mousedown', this.handleMouseDown.bind(this))     window.addEventListener('pagehide', this.handlePageHide.bind(this))   }    run() {     this.running = true     if (this.booms.length == 0) {       return this.running = false     }     requestAnimationFrame(this.run.bind(this))     this.computerContext.clearRect(0, 0, this.globalWidth, this.globalHeight)     this.renderContext.clearRect(0, 0, this.globalWidth, this.globalHeight)      this.booms.forEach((boom, index) => {       if (boom.stop) {         return this.booms.splice(index, 1)       }       boom.move()       boom.draw()     })     this.renderContext.drawImage(this.computerCanvas, 0, 0, this.globalWidth, this.globalHeight)   } }  const cursorSpecialEffects = new CursorSpecialEffects() cursorSpecialEffects.init()

优化后的代码:

class Circle {     constructor({origin,context,color,angle,speed}) {         this.position = {...origin};         this.context = context;         this.color = color;         this.angle = angle;         this.speed = speed;         this.renderCount = 0;     }     draw() {         this.context.fillStyle = this.color;         this.context.beginPath();         this.context.arc(this.position.x, this.position.y, 2, 0, Math.PI * 2, false);         this.context.fill();     }     move() {         this.position.x += Math.sin(this.angle) * this.speed;         this.position.y += Math.cos(this.angle) * this.speed + this.renderCount * 0.3;         this.renderCount ++;     } }  class Boom {     constructor({origin,context,area,circleNum = 10}) {         this.origin = origin;         this.context = context;         this.area = area;         this.circleNum = circleNum;         this.circles = [];         this.stop = false;     }          randomColor() {         const rang = '89ABCDEF';         const num = 6;         let resultStr = '';         for(let i = 0, num = 6; i < num; i++) {             resultStr += rang.charAt(Math.floor(rang.length * Math.random()));         }         return '#' + resultStr;     }          randomRange(start,end) {         return start + Math.random() * (end - start)     }          init() {         for(let i = 0; i < this.circleNum; i++) {             const circle = new Circle({                 origin: this.origin,                 context: this.context,                 color: this.randomColor(),                 angle: this.randomRange(Math.PI / 2, Math.PI * 3 / 2),                 speed: this.randomRange(1,6)             })             this.circles.push(circle);         }     }          move() {         for(let i = 0; i < this.circles.length; i++) {             const curCircle = this.circles[i];             if(curCircle.x >= this.area.width || curCircle.y >= this.area.height) {                 this.circles.splice(i,1);                 i--;                 continue;             }             curCircle.move();         }         if(this.circles.length === 0) {             this.stop = true;         }     }          draw() {         this.circles.forEach((circle) => circle.draw());     } }  class MouseClickEffect {     constructor() {         this.drawCanvas = document.createElement('canvas');         this.drawContext = this.drawCanvas.getContext('2d');         const style = this.drawCanvas.style;         style.left = style.top = 0;         style.position = 'fixed';         style.zIndex = '999999999';         style.pointerEvents = 'none';         this.drawCanvas.width = this.globalWidth = window.innerWidth;         this.drawCanvas.height = this.globalHeight = window.innerHeight;         document.body.appendChild(this.drawCanvas);         this.booms = [];         this.running = false;                  window.addEventListener('mousedown', this.handleMouseDown.bind(this));         window.addEventListener('resize',this.changeWindow.bind(this));     }          handleMouseDown(e) {         const boom = new Boom({             origin: {x: e.clientX, y: e.clientY},             area: {width: this.globalWidth, height: this.globalHeight},             context: this.drawContext         });         boom.init();         this.booms.push(boom);         this.running || this.run();     }          changeWindow() {         this.booms = [];         this.running = false;         this.drawCanvas.width = this.globalWidth = window.innerWidth;         this.drawCanvas.height = this.globalHeight = window.innerHeight;         this.drawContext.clearRect(0, 0, this.globalWidth, this.globalHeight);     }          run() {         this.running = true;         if(this.booms.length === 0) {             return this.running = false;         }         requestAnimationFrame(this.run.bind(this));         this.drawContext.clearRect(0, 0, this.globalWidth, this.globalHeight);         for(let i = 0; i < this.booms.length; i++) {             const boom = this.booms[i];             if(boom.stop) {                 this.booms.splice(i, 1);                 i--;                 continue;             }             boom.move();             boom.draw();         }     } }  new MouseClickEffect();