Skip to content

Instantly share code, notes, and snippets.

@charlenopires
Created November 28, 2014 02:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save charlenopires/6b77c987eee010ca7796 to your computer and use it in GitHub Desktop.
Save charlenopires/6b77c987eee010ca7796 to your computer and use it in GitHub Desktop.
Sine Wave Experiment
#title="Sine Wave Experiment"
canvas#waves
/**
* Generates multiple customizable animated sines waves
* using a canvas element. Supports retina displays and
* limited mobile support
*/
function SineWaveGenerator(options) {
$.extend(this, options || {});
if(!this.el) { throw "No Canvas Selected"; }
this.ctx = this.el.getContext('2d');
if(!this.waves.length) { throw "No waves specified"; }
// Internal
this._resizeWidth();
window.addEventListener('resize', this._resizeWidth.bind(this));
// User
this.resizeEvent();
window.addEventListener('resize', this.resizeEvent.bind(this));
if(typeof this.initialize === 'function') {
this.initialize.call(this);
}
// Start the magic
this.loop();
}
// Defaults
SineWaveGenerator.prototype.speed = 10;
SineWaveGenerator.prototype.amplitude = 50;
SineWaveGenerator.prototype.wavelength = 50;
SineWaveGenerator.prototype.segmentLength = 10;
SineWaveGenerator.prototype.lineWidth = 2;
SineWaveGenerator.prototype.strokeStyle = 'rgba(255, 255, 255, 0.2)';
SineWaveGenerator.prototype.resizeEvent = function() {};
// fill the screen
SineWaveGenerator.prototype._resizeWidth = function() {
this.dpr = window.devicePixelRatio || 1;
this.width = this.el.width = window.innerWidth * this.dpr;
this.height = this.el.height = window.innerHeight * this.dpr;
this.el.style.width = window.innerWidth + 'px';
this.el.style.height = window.innerHeight + 'px';
this.waveWidth = this.width * 0.95;
this.waveLeft = this.width * 0.025;
}
SineWaveGenerator.prototype.clear = function () {
this.ctx.clearRect(0, 0, this.width, this.height);
}
SineWaveGenerator.prototype.time = 0;
SineWaveGenerator.prototype.update = function(time) {
this.time = this.time - 0.007;
if(typeof time === 'undefined') {
time = this.time;
}
var index = -1;
var length = this.waves.length;
while(++index < length) {
var timeModifier = this.waves[index].timeModifier || 1;
this.drawSine(time * timeModifier, this.waves[index]);
}
index = void 0;
length = void 0;
}
// Constants
var PI2 = Math.PI * 2;
var HALFPI = Math.PI / 2;
SineWaveGenerator.prototype.ease = function(percent, amplitude) {
return amplitude * (Math.sin(percent * PI2 - HALFPI) + 1) * 0.5;
}
SineWaveGenerator.prototype.drawSine = function(time, options) {
options = options || {};
amplitude = options.amplitude || this.amplitude;
wavelength = options.wavelength || this.wavelength;
lineWidth = options.lineWidth || this.lineWidth;
strokeStyle = options.strokeStyle || this.strokeStyle;
segmentLength = options.segmentLength || this.segmentLength;
var x = time;
var y = 0;
var amp = this.amplitude;
// Center the waves
var yAxis = this.height / 2;
// Styles
this.ctx.lineWidth = lineWidth * this.dpr;
this.ctx.strokeStyle = strokeStyle;
this.ctx.lineCap = 'round';
this.ctx.lineJoin = 'round';
this.ctx.beginPath();
// Starting Line
this.ctx.moveTo(0, yAxis);
this.ctx.lineTo(this.waveLeft, yAxis);
for(var i = 0; i < this.waveWidth; i += segmentLength) {
x = (time * this.speed) + (-yAxis + i) / wavelength;
y = Math.sin(x);
// Easing
amp = this.ease(i / this.waveWidth, amplitude);
this.ctx.lineTo(i + this.waveLeft, amp * y + yAxis);
amp = void 0;
}
// Ending Line
this.ctx.lineTo(this.width, yAxis);
// Stroke it
this.ctx.stroke();
// Clean up
options = void 0;
amplitude = void 0;
wavelength = void 0;
lineWidth = void 0;
strokeStyle = void 0;
segmentLength = void 0;
x = void 0;
y = void 0;
}
SineWaveGenerator.prototype.loop = function() {
this.clear();
this.update();
window.requestAnimationFrame(this.loop.bind(this));
}
new SineWaveGenerator({
el: document.getElementById('waves'),
speed: 8,
waves: [
{
timeModifier: 1,
lineWidth: 3,
amplitude: 150,
wavelength: 200,
segmentLength: 20,
// strokeStyle: 'rgba(255, 255, 255, 0.5)'
},
{
timeModifier: 1,
lineWidth: 2,
amplitude: 150,
wavelength: 100,
// strokeStyle: 'rgba(255, 255, 255, 0.3)'
},
{
timeModifier: 1,
lineWidth: 1,
amplitude: -150,
wavelength: 50,
segmentLength: 10,
// strokeStyle: 'rgba(255, 255, 255, 0.2)'
},
{
timeModifier: 1,
lineWidth: 0.5,
amplitude: -100,
wavelength: 100,
segmentLength: 10,
// strokeStyle: 'rgba(255, 255, 255, 0.1)'
}
],
initialize: function (){
},
resizeEvent: function() {
var gradient = this.ctx.createLinearGradient(0, 0, this.width, 0);
gradient.addColorStop(0,"rgba(0, 0, 0, 0)");
gradient.addColorStop(0.5,"rgba(255, 255, 255, 0.5)");
gradient.addColorStop(1,"rgba(0, 0, 0, 0)");
var index = -1;
var length = this.waves.length;
while(++index < length){
this.waves[index].strokeStyle = gradient;
}
// Clean Up
index = void 0;
length = void 0;
gradient = void 0;
}
});
@import "compass/css3";
@import url(http://fonts.googleapis.com/css?family=Raleway:100,300);
body {
background-color: #222;
@include background-image(linear-gradient(top, rgba(#111,1) 0%,rgba(#222,1) 50%,rgba(#111,1) 100%));
font-family: 'Raleway', sans-serif;
font-weight: 100;
color: rgba(255, 255, 255, 0.5);
height: 100vh;
width: 100vw;
}
#title {
position: fixed;
top: 10px;
left: 10px;
font-size: 20px;
letter-spacing: 0.1em;
z-index: 100;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment