diff --git a/src/mappings/coloring.js b/src/mappings/coloring.js index 8882f40..3a7c253 100644 --- a/src/mappings/coloring.js +++ b/src/mappings/coloring.js @@ -10,7 +10,7 @@ import { numerical } from "./numeric.js"; * * @param {object} conf The configuration of the mapping. * @param {HTMLElement} conf.element The element whose text's red value should be mapped. - * @param {string} conf.color Where r for red, g, for green, b for blue, and a for alpha. + * @param {string} conf.select Where r for red, g, for green, b for blue, and a for alpha. * @param {number} conf.lowerBin The lower bound of the bins to be mapped. * @param {VisUpdateRouter} conf.visUpdateRouter The visualizer update manager associated with the audio playback you would like the mapping with. * @param {Function} conf.interpolator The interpolation function to use. @@ -20,17 +20,17 @@ import { numerical } from "./numeric.js"; * @param {number} [conf.upperVal=0] The upper boundary of possible values for the color component (0 to 255 inclusive). * @returns {{lower: number, upper: number, listener: VisUpdateRouter~visualizerRangedUpdateListener}} The ranged listener that was added. */ -export function backgroundColorRgba({ element, color, lowerBin, visUpdateRouter, interpolator, upperBin = undefined, reversed = false, lowerVal = 0, upperVal = 255 }) { +export function backgroundColorRgba({ element, select, lowerBin, visUpdateRouter, interpolator, upperBin = undefined, reversed = false, lowerVal = 0, upperVal = 255 }) { const rgbaStr = "rgba"; - color = rgbaStr.indexOf(color); - if (color < 0) throw new Error("Invalid color parameter provided."); + select = rgbaStr.indexOf(select); + if (select < 0) throw new Error("Invalid color parameter provided."); const getter = () => { if (!element.style.backgroundColor) element.style.backgroundColor = "rgba(0, 0, 0, 255)"; - return parseColorToRgba(element.style.backgroundColor)[color]; + return parseColorToRgba(element.style.backgroundColor)[select]; }; const setter = (value) => { const changed = parseColorToRgba(element.style.backgroundColor); - changed[color] = value; + changed[select] = value; if (element.style.backgroundColor.startsWith("rgb")) { element.style.backgroundColor = rgbaToCssRgba(changed); } else if (element.style.backgroundColor.startsWith("hsl")) { @@ -121,7 +121,7 @@ export function backgroundColorHsla({ element, select, lowerBin, visUpdateRouter * * @param {object} conf The configuration of the mapping. * @param {HTMLElement} conf.element The element whose text's red value should be mapped. - * @param {string} conf.color Where r for red, g, for green, b for blue, and a for alpha. + * @param {string} conf.select Where r for red, g, for green, b for blue, and a for alpha. * @param {number} conf.lowerBin The lower bound of the bins to be mapped. * @param {VisUpdateRouter} conf.visUpdateRouter The visualizer update manager associated with the audio playback you would like the mapping with. * @param {Function} conf.interpolator The interpolation function to use. @@ -131,17 +131,17 @@ export function backgroundColorHsla({ element, select, lowerBin, visUpdateRouter * @param {number} [conf.upperVal=0] The upper boundary of possible values for the color component (0 to 255 inclusive). * @returns {{lower: number, upper: number, listener: VisUpdateRouter~visualizerRangedUpdateListener}} The ranged listener that was added. */ -export function fontColorRgba({ element, color, lowerBin, visUpdateRouter, interpolator, upperBin = undefined, reversed = false, lowerVal = 0, upperVal = 255 }) { +export function fontColorRgba({ element, select, lowerBin, visUpdateRouter, interpolator, upperBin = undefined, reversed = false, lowerVal = 0, upperVal = 255 }) { const rgbaStr = "rgba"; - color = rgbaStr.indexOf(color); - if (color < 0) throw new Error("Invalid color parameter provided."); + select = rgbaStr.indexOf(select); + if (select < 0) throw new Error("Invalid color parameter provided."); const getter = () => { if (!element.style.color) element.style.color = "rgba(0, 0, 0, 255)"; - return parseColorToRgba(element.style.color)[color]; + return parseColorToRgba(element.style.color)[select]; }; const setter = (value) => { const changed = parseColorToRgba(element.style.color); - changed[color] = value; + changed[select] = value; if (element.style.color.startsWith("rgb")) { element.style.color = rgbaToCssRgba(changed); } else if (element.style.color.startsWith("hsl")) { @@ -167,3 +167,65 @@ export function fontColorRgba({ element, color, lowerBin, visUpdateRouter, inter }; return numerical(conf); } + +/** + * Maps a hsla color component of an element's font color to a certain range of frequency bins. + * + * @param {object} conf The configuration of the mapping. + * @param {HTMLElement} conf.element The element whose text's red value should be mapped. + * @param {number} conf.select Where h for hue, s, for saturation, l for lightness, and a for alpha. + * @param {number} conf.lowerBin The lower bound of the bins to be mapped. + * @param {VisUpdateRouter} conf.visUpdateRouter The visualizer update manager associated with the audio playback you would like the mapping with. + * @param {Function} conf.interpolator The interpolation function to use. + * @param {number} [conf.upperBin=undefined] The upper bound of the bins to be mapped. If left undefined, then only the bin defined by the min value is used. + * @param {boolean} [conf.reversed=true] If true, then the quieter, the greater the red value. + * @param {number} [conf.lowerVal=0] The lower boundary of possible values for the color component (0 to upperVal inclusive). + * @param {number} [conf.upperVal=0] The upper boundary of possible values for the color component (0 to 360 if conf.color is "h", 1 if conf.color is "s" or "l", and 255 if conf.color is "a"). + * @returns {{lower: number, upper: number, listener: VisUpdateRouter~visualizerRangedUpdateListener}} The ranged listener that was added. + */ +export function fontColorHsla({ element, select, lowerBin, visUpdateRouter, interpolator, upperBin = undefined, reversed = false, lowerVal = 0, upperVal = undefined }) { + const rgbaStr = "hsla"; + select = rgbaStr.indexOf(select); + if (select < 0) throw new Error("Invalid color parameter provided."); + + const getter = () => { + if (!element.style.color) element.style.color = "hsl(0, 50%, 50%, 255)"; + return parseColorToHsla(element.style.color)[select]; + }; + const setter = (value) => { + const changed = parseColorToHsla(element.style.color); + changed[select] = value; + if (element.style.color.startsWith("hsl")) { + element.style.color = hslaToCssHsla(changed); + } else if (element.style.color.startsWith("rgb")) { + element.style.color = rgbaToCssRgba(hslaToRgba(changed)); + } else if (element.style.color.startsWith("#")) { + element.style.color = rgbaToHexRgba(hslaToRgba(changed)); + } else { + element.style.color = rgbaToHexRgba(hslaToRgba(changed)); // If we don't recognize the currently used color function, then just use hex. + } + }; + let upperBound = 360; + if (select === "s" || select === "l") { + upperBound = 1; + } else if (select === "a") { + upperBound = 255; + } + if (isNaN(upperVal)) upperVal = upperBound; + + upperVal = Math.min(Math.max(0, upperVal), upperBound); + lowerVal = Math.min(Math.max(0, lowerVal), upperVal); + + const conf = { + minVal: lowerVal, + maxVal: upperVal, + lowerBin: lowerBin, + upperBin: upperBin, + getter: getter, + setter: setter, + interpolator: interpolator, + visUpdateRouter: visUpdateRouter, + reversed: reversed + }; + return numerical(conf); +} \ No newline at end of file diff --git a/tutorials/VisMusicPlayer.html b/tutorials/VisMusicPlayer.html index e5a17ba..6a36d0f 100644 --- a/tutorials/VisMusicPlayer.html +++ b/tutorials/VisMusicPlayer.html @@ -99,15 +99,15 @@

Mapping Font Color

Now for a bit more of an eccentric mapping, you can map the color of a font to the music!

-
- Hello world! +
+ Hello colors!

-            const fontColorElem = document.getElementById("font-color-map-demo");
+            const fontColorRgbaElem = document.getElementById("font-color-rgba-map-demo");
             ask.mappings.coloring.fontColorRgba({ // Under mappings, the text module. We just want to map one of the RGBA color components...
-                element: fontColorElem, // The element to map (same as above examples).
-                color: "r", // Choose the red component.
+                element: fontColorRgbaElem, // The element to map (same as above examples).
+                select: "r", // Choose the red component.
                 lowerBin: 128, // All other values are what we've seen above.
                 upperBin: 160,
                 visUpdateRouter: player.visUpdateRouter,
@@ -115,6 +115,32 @@
             });
         
+

In the same vein of mapping, we can also map HSL values. If you haven't heard of HSL values, you can read up about it anywhere online really, but essentially, it's another way of describing a color where a hue is used to describe a color, and then the color is adjusted by its saturation and lightness. Importantly for your case, it may make it easier to achieve the type of dynamic color mapping you're looking for (potentially when used in conjunction with any of RGBA components).

+
+
+ Hello more colors! +
+
+

+        const fontColorHslElem = document.getElementById("font-color-hsla-map-demo");
+        ask.mappings.coloring.fontColorHsla({ // Similar to the rgba example, except now with hsla.
+            element: fontColorHslElem,
+            select: "h", // Selecting the "hue" component.
+            lowerBin: 200,
+            upperBin: 220,
+            visUpdateRouter: player.visUpdateRouter,
+            interpolator: ask.support.easings.createEaseLinear(2.5)
+        })
+    
+ +
+

Mapping Background Color

+

This is kind of like the one for fonts, except, instead, for background colors!

+
+
+
+
+
@@ -172,14 +198,23 @@ ask.mappings.dimensions.width(squareElemConf); ask.mappings.dimensions.height(squareElemConf); - const fontColorElem = document.getElementById("font-color-map-demo"); + const fontColorRgbaElem = document.getElementById("font-color-rgba-map-demo"); ask.mappings.coloring.fontColorRgba({ - element: fontColorElem, - color: "r", + element: fontColorRgbaElem, + select: "r", lowerBin: 128, upperBin: 160, visUpdateRouter: player.visUpdateRouter, interpolator: ask.support.easings.createEaseLinear(2.5) }); + const fontColorHslElem = document.getElementById("font-color-hsla-map-demo"); + ask.mappings.coloring.fontColorHsla({ + element: fontColorHslElem, + select: "h", + lowerBin: 200, + upperBin: 220, + visUpdateRouter: player.visUpdateRouter, + interpolator: ask.support.easings.createEaseLinear(2.5) + }) \ No newline at end of file