diff --git a/js/HuesCanvas.js b/js/HuesCanvas.js index 92b1e68..e4621ec 100644 --- a/js/HuesCanvas.js +++ b/js/HuesCanvas.js @@ -51,6 +51,12 @@ function HuesCanvas(element, aContext, core) { this.blurDistance = 0; this.xBlur = false; this.yBlur = false; + + // trippy mode + this.trippyStart = [0, 0]; // x, y + this.trippyRadii = [0, 0]; // x, y + this.trippyOn = false; + this.trippyRadius = 0; this.blackout = false; this.blackoutColour = "#000"; // for the whiteout case we must store this @@ -68,6 +74,8 @@ function HuesCanvas(element, aContext, core) { this.setBlurQuality("high"); this.setBlurDecay("fast"); this.canvas = document.getElementById(element).getContext("2d"); + this.offscreenCanvas = document.createElement('canvas').getContext('2d'); + this.offscreenCanvas.globalCompositeOperation = "source-over"; window.addEventListener('resize', this.resize.bind(this)); this.resize(); @@ -86,14 +94,18 @@ HuesCanvas.prototype.settingsUpdated = function() { this.setBlurAmount(localStorage["blurAmount"]); this.setBlurDecay(localStorage["blurDecay"]); this.setBlurQuality(localStorage["blurQuality"]); + this.trippyOn = localStorage["trippyMode"] == "on"; } HuesCanvas.prototype.resize = function() { // height is constant 720px, we expand width to suit var ratio = window.innerWidth / window.innerHeight; this.canvas.canvas.width = Math.ceil(720 * ratio); + this.offscreenCanvas.canvas.height = this.canvas.canvas.height; + this.offscreenCanvas.canvas.width = this.canvas.canvas.width; var snow = document.getElementById("snow").getContext("2d"); snow.canvas.width = Math.ceil(720 * ratio); + this.trippyRadius = Math.max(this.canvas.canvas.width, this.canvas.canvas.height) / 2; this.needsRedraw = true; }; @@ -166,10 +178,42 @@ HuesCanvas.prototype.redraw = function() { this.canvas.drawImage(bitmap, offset, 0); } } + + if(this.trippyOn && (this.trippyStart[0] || this.trippyStart[1])) { + // x blur moves inwards from the corners, y comes out + // So the base colour is inverted for y, normal for x + // Thus if the y start is more recent, we invert + var baseInvert = this.trippyStart[1] > this.trippyStart[0]; + var invertC = this.intToHex(0xFFFFFF ^ this.colour); + var normalC = this.intToHex(this.colour); + this.offscreenCanvas.fillStyle = baseInvert ? invertC : normalC; + this.offscreenCanvas.fillRect(0,0,width,720); + + // sort high to low + this.trippyRadii.sort(function(a,b) { + return b - a; + }); + + var invert = !baseInvert; + for(var i = 0; i < 2; i++) { + if(this.trippyRadii[i] == 0) { + continue; + } + // Invert for each subsequent draw + this.offscreenCanvas.beginPath(); + this.offscreenCanvas.fillStyle = this.intToHex(invert ? invertC : normalC); + this.offscreenCanvas.arc(width/2, this.canvas.canvas.height/2, this.trippyRadii[i], 0, 2 * Math.PI, false); + this.offscreenCanvas.fill(); + this.offscreenCanvas.closePath(); + invert = !invert; + } + } else { + this.offscreenCanvas.fillStyle = this.intToHex(this.colour); + this.offscreenCanvas.fillRect(0,0,width,720); + } this.canvas.globalAlpha = 0.7; - this.canvas.fillStyle = this.intToHex(this.colour); this.canvas.globalCompositeOperation = this.blendMode; - this.canvas.fillRect(0,0,width,720); + this.canvas.drawImage(this.offscreenCanvas.canvas, 0, 0); if(this.blackout) { this.canvas.globalAlpha = bOpacity; this.canvas.fillStyle = this.blackoutColour; @@ -231,6 +275,22 @@ HuesCanvas.prototype.animationLoop = function() { else this.core.blurUpdated(0, dist); } + if(this.trippyOn && (this.trippyStart[0] || this.trippyStart[1])) { + for(var i = 0; i < 2; i++) { + this.trippyRadii[i] = Math.floor((this.aContext.currentTime - this.trippyStart[i]) * this.trippyRadius) * 2; + if(this.trippyRadii[i] > this.trippyRadius) { + this.trippyStart[i] = 0; + this.trippyRadii[i] = 0; + continue; + } + // x comes from outside the window + if(i % 2 == 0) { + this.trippyRadii[i] = this.trippyRadius - this.trippyRadii[i]; + } + } + this.needsRedraw = true; + } + if(this.blurStart && this.blurDistance < 1) { this.core.blurUpdated(0, 0); this.blurDistance = 0; @@ -372,6 +432,7 @@ HuesCanvas.prototype.mixColours = function(percent) { HuesCanvas.prototype.doXBlur = function() { this.blurStart = this.aContext.currentTime; + this.trippyStart[0] = this.blurStart; this.blurDistance = this.blurAmount; this.xBlur = true; this.yBlur = false; @@ -380,6 +441,7 @@ HuesCanvas.prototype.doXBlur = function() { HuesCanvas.prototype.doYBlur = function() { this.blurStart = this.aContext.currentTime; + this.trippyStart[1] = this.blurStart; this.blurDistance = this.blurAmount; this.xBlur = false; this.yBlur = true; diff --git a/js/HuesSettings.js b/js/HuesSettings.js index f123b67..50faecc 100644 --- a/js/HuesSettings.js +++ b/js/HuesSettings.js @@ -56,6 +56,7 @@ HuesSettings.prototype.defaultSettings = { autoSongDelay: 5, // loops or minutes depending on autoSong value autoSongShuffle: "on", autoSongFadeout: "on", + trippyMode: "off", volume: 0.7 }; @@ -92,7 +93,8 @@ HuesSettings.prototype.settingsCategories = { "Graphics" : [ "blurAmount", "blurDecay", - "blurQuality" + "blurQuality", + "trippyMode" ], "Audio" : [ "playBuildups" @@ -175,6 +177,10 @@ HuesSettings.prototype.settingsOptions = { autoSongFadeout : { name : "AutoSong fade out", options : ["off", "on"] + }, + trippyMode : { + name : "Trippy Mode", + options : ["off", "on"] } };