Experimental module to create multiple animated sine waves.
A Pen by Isaac Suttell on CodePen.
| #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; | |
| } | |
| }); |
Experimental module to create multiple animated sine waves.
A Pen by Isaac Suttell on CodePen.
| @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; | |
| } |