I want the result of the math function into my css file, that the kind of blur is variable. But it doesn't work and I don't know how, because there are no errors. The variable number is between 1 and 5.
This is the Javascript code I'm using:
var minNumber = 1;
var maxNumber = 5;
var result;
var randomNumber = randomNumberFromRange(minNumber, maxNumber);
function randomNumberFromRange(min, max) {
result = Math.floor(Math.random() * (max - min + 1) + min);
return;
}
document.getElementById("test").style.filter = blur(result + "px");
Set that style as a string:
document.getElementById("test").style.filter = "blur(" + result + "px)";
var minNumber = 1;
var maxNumber = 5;
var result;
var randomNumber = randomNumberFromRange(minNumber, maxNumber);
function randomNumberFromRange(min, max) {
result = Math.floor(Math.random() * (max - min + 1) + min);
}
document.getElementById("test").style.filter = "blur(" + result + "px)";
#test {
position: absolute left: 10px;
top: 10px;
background-color: lightgreen;
width: 200px;
height: 200px;
z-index: 9999;
opacity: .9;
}
#test2 {
position: absolute;
left: 30px;
top: 40px;
background-color: black;
width: 100px;
height: 100px;
}
<div id="test">
</div>
<div id="test2"></div>
Check your console. You should have an error saying blur is undefined.
blur is not a function defined in JS, but rather a CSS filter function, and as such should be set as a string in your case.
For example:
document.getElementById("test").style.filter = 'blur('+result+'px)';
If ES6 is possible in your case, you can also use a template string and plug the value as an embedded expression:
document.getElementById("test").style.filter = `blur(${result}px)`;
You need to pass blur as a text value to the CSS filter property:
var minNumber = 1;
var maxNumber = 5;
var result;
var randomNumber = randomNumberFromRange(minNumber, maxNumber);
function randomNumberFromRange(min, max) {
result = Math.floor(Math.random() * (max - min + 1) + min);
return;
}
console.log('random value for blur: ', result);
document.getElementById("test").style.filter = 'blur('+ result +'px)';
<p id="test">test</p>
Related
How can this script start counting from zero? At the moment it starts with the number it's supposed to count to before starting from zero
The JavaScript function loads the counter when it is called into view. How can the numerical values in the counter start with zeros when it is called into view
function isVisible(el) {
const element = $(el);
var WindowTop = $(window).scrollTop();
var WindowBottom = WindowTop + $(window).height();
var ElementTop = element.offset().top;
//var ElementBottom = ElementTop + element.height();
var ElementBottom = ElementTop + 20;
return ElementBottom <= WindowBottom && ElementTop >= WindowTop;
}
function Counter(el) {
obj = $(el);
if (obj.hasClass("ms-animated")) {
return;
}
obj.addClass("ms-animated");
// get the number
var number = obj.text();
obj.attr("data-number", number);
// clear the HTML element
obj.empty();
// create an array from the text, prepare to identify which characters in the string are numbers
var numChars = number.split("");
var numArray = [];
var setOfNumbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// for each number, create the animation elements
for (var i = 0; i < numChars.length; i++) {
if ($.inArray(parseInt(numChars[i], 10), setOfNumbers) != -1) {
obj.append(
'<span class="digit-con"><span class="digit' +
numArray.length +
'">0<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br></span></span>'
);
numArray[numArray.length] = parseInt(numChars[i], 10);
} else {
obj.append("<span>" + numChars[i] + "</span>");
}
}
// determine the height of each number for the animation
var increment = obj.find(".digit-con").outerHeight();
var speed = 2000;
// animate each number
for (var i = 0; i < numArray.length; i++) {
obj
.find(".digit" + i)
.animate({
top: -(increment * numArray[i])
},
Math.round(speed / (1 + i * 0.333))
);
}
}
$(window).scroll(function() {
const counterNumbers = $(".number").toArray();
counterNumbers.filter(isVisible).map(Counter);
});
$(window).trigger("scroll");
.number {
display: block;
font-size: 6rem;
line-height: 6.5rem;
}
.number *+* {
margin-top: 0;
}
.digit-con {
display: inline-block;
height: 6.5rem;
overflow: hidden;
vertical-align: top;
}
.digit-con span {
display: block;
font-size: 6rem;
line-height: 6.5rem;
position: relative;
text-align: center;
top: 0;
width: 0.55em;
}
.month {
height: 100vh;
}
<h1>Scroll</h1>
<div class="number">$2,350,354.43</div>
<div class="month">March</div>
<div class="number">$6,350,354.43</div>
<div class="month">March</div>
<div class="number">$8,500,435.33</div>
<div class="month">April</div>
<div class="number">$3,500,435.53</div>
<div class="month">May</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js'></script>
Your issue is a something similar to FOUC - Flash of Unstyled Content - where what's originally in the HTML is displayed before it can be updated.
This can be fixed by changing the html and showing the value you want to display on load, while storing the required number in a data- attribute, eg:
<div class="number" data-number="$2,350,354.43">$0,000,000.00</div>
with a small change to your existing code to read the data- instead of text, from
var number = obj.text();
obj.attr("data-number", number); // this is never used
to
var number = obj.data("number");
If you can't change the html (or don't want to) then you can have an initialisation script run before your first scroll initialisation:
$(".number").each((i,e) => {
var obj = $(e);
var number = obj.text();
obj.data("number", number);
obj.text(number.replace(/\d/g, "0"));
});
You will still get FOUC on the very first counter if it's already visible because that's how javascript works: to keep things simple/basic: the page is rendered, then js runs. So there's a short time before the js runs where it's parsing/processing the js ready to run - how long this will be depends on how much js you have (including libraries) / whether it's cached / how much initialisation code there is.
Generally better to output your HTML as you want it displayed rather than rely on JS to update it, but that's not always possible.
Updated snippet:
function isVisible(el) {
const element = $(el);
var WindowTop = $(window).scrollTop();
var WindowBottom = WindowTop + $(window).height();
var ElementTop = element.offset().top;
//var ElementBottom = ElementTop + element.height();
var ElementBottom = ElementTop + 20;
return ElementBottom <= WindowBottom && ElementTop >= WindowTop;
}
function Counter(el) {
obj = $(el);
if (obj.hasClass("ms-animated")) {
return;
}
obj.addClass("ms-animated");
// get the number
//var number = obj.text();
//obj.attr("data-number", number);
var number = obj.data("number");
// clear the HTML element
obj.empty();
// create an array from the text, prepare to identify which characters in the string are numbers
var numChars = number.split("");
var numArray = [];
var setOfNumbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// for each number, create the animation elements
for (var i = 0; i < numChars.length; i++) {
if ($.inArray(parseInt(numChars[i], 10), setOfNumbers) != -1) {
obj.append(
'<span class="digit-con"><span class="digit' +
numArray.length +
'">0<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>9<br></span></span>'
);
numArray[numArray.length] = parseInt(numChars[i], 10);
} else {
obj.append("<span>" + numChars[i] + "</span>");
}
}
// determine the height of each number for the animation
var increment = obj.find(".digit-con").outerHeight();
var speed = 2000;
// animate each number
for (var i = 0; i < numArray.length; i++) {
obj
.find(".digit" + i)
.animate({
top: -(increment * numArray[i])
},
Math.round(speed / (1 + i * 0.333))
);
}
}
$(window).scroll(function() {
const counterNumbers = $(".number").toArray();
counterNumbers.filter(isVisible).map(Counter);
});
$(".number").each((i,e) => {
var obj = $(e);
var number = obj.text();
obj.data("number", number);
obj.text(number.replace(/\d/g, "0"));
});
$(window).trigger("scroll");
.number {
display: block;
font-size: 6rem;
line-height: 6.5rem;
}
.number *+* {
margin-top: 0;
}
.digit-con {
display: inline-block;
height: 6.5rem;
overflow: hidden;
vertical-align: top;
}
.digit-con span {
display: block;
font-size: 6rem;
line-height: 6.5rem;
position: relative;
text-align: center;
top: 0;
width: 0.55em;
}
.month {
height: 100vh;
}
<h1>Scroll</h1>
<div class="number">$2,350,354.43</div>
<div class="month">March</div>
<div class="number">$6,350,354.43</div>
<div class="month">March</div>
<div class="number">$8,500,435.33</div>
<div class="month">April</div>
<div class="number">$3,500,435.53</div>
<div class="month">May</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js'></script>
So i got input type range, which works fine and input box, when user types number 10-500 It sets value on range and I need to set the color of progress in range. Now its showing up the previous value.
var textInputKg = document.getElementById("text");
var rangeInputKg = document.getElementById("range");
function rangeProgress(to, from) {
var min = rangeInputKg.min;
var max = rangeInputKg.max;
var value = rangeInputKg.value;
var p = ((value - min) / (max - min)) * 100;
rangeInputKg.style.backgroundImage =
"-webkit-gradient(linear, left top, right top, " +
"color-stop(" +
p +
"%, yellow), " +
"color-stop(" +
p +
"%, black)" +
")";
to.value = from.value;
}
function delay(fn, ms) {
let timer = 0;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(fn.bind(this, ...args), ms || 0);
};
}
rangeInputKg.addEventListener("input", e => {
rangeProgress(textInputKg, rangeInputKg);
});
textInputKg.addEventListener(
"keyup",
delay(e => {
rangeProgress(rangeInputKg, textInputKg);
console.log(textInputKg.value);
}, 500)
);
#range {
outline: none;
-webkit-appearance: none;
width: 100%;
height: 15px;
border-radius: 10px;
background: black;
}
<input id="range" type="range" max="500" min="10" value="10" autocomplete="off">
<input id="text">
Use from parameter value
var p = ((value - min) / (max - min)) * 100;
to
var p = ((from.value - min) / (max - min)) * 100;
var textInputKg = document.getElementById("text");
var rangeInputKg = document.getElementById("range");
function rangeProgress(to, from) {
var min = rangeInputKg.min;
var max = rangeInputKg.max;
var p = ((from.value - min) / (max - min)) * 100;
rangeInputKg.style.backgroundImage =
"-webkit-gradient(linear, left top, right top, " +
"color-stop(" +
p +
"%, yellow), " +
"color-stop(" +
p +
"%, black)" +
")";
to.value = from.value;
}
function delay(fn, ms) {
let timer = 0;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(fn.bind(this, ...args), ms || 0);
};
}
rangeInputKg.addEventListener("input", e => {
rangeProgress(textInputKg, rangeInputKg);
});
textInputKg.addEventListener(
"keyup",
delay(e => {
rangeProgress(rangeInputKg, textInputKg);
}, 500)
);
#range {
outline: none;
-webkit-appearance: none;
width: 100%;
height: 15px;
border-radius: 10px;
background: black;
}
<input id="range" type="range" max="500" min="10" value="10" autocomplete="off">
<input id="text">
how to make a stimulus (image, div, whichever's easiest) show up on right or left half of screen randomly using javascript.
Any ideas about having the button clicks record the reaction time, which button is clicked (left or right), and which side the stimulus was presented on?? Also, the left button should be "true" when stimulus is presented on the right and vice versa.
<head>
<style >
.divStyleLeft {
width: 300px;
height: 300px;
background-color: lightblue;
float: left;
}
.divStyleRight {
width: 300px;
height: 300px;
background-color: lightgreen;
float: right;
}
.maxWidth {
width: 100%;
}
.button {
float: right;
}
.button2 {
float: left;
}
</style>
</head>
<body onload="presentStimulus()">
<div class="button">
<button onclick="presentStimulus()">Click Me</button>
</div>
<div class="button2">
<button onclick="presentStimulus()">Click Me </button>
</div>
<div class="maxwidth"></div>
<div id="float" class="divStyleLeft" onclick="recordClick()">
I AM NOT FLOATING
</div>
<script>
let numClicks= 0;
let timeStart = 0;
let timeEnd = 0;
function Trial(trialTime, sidePresented,buttonClicked,) {
this.trialTime = trialTime;
this.sidePresented= sidePresented;
this.buttonClicked= buttonClicked;
}
let allTrials = [];
for(x = 0; x < 12; x++)
allTrials.push(new Trial(0,0,0));
Trial.prototype.toString=function(){
return this.trialTime + "ms, Side : " + this.sidePresented + ", Reaction Time: " + this.buttonClicked
+ "<br>";
};
function presentStimulus() {
const elem = document.querySelector ( '#float' );
const min = 1;
const max = 2;
const v = Math.floor(Math.random() * (max - min + 1)) + min;
console.log ( 'Random num is ' + v + ": ", '1 will go left, 2 will go right' );
v === 1 ?
( () => {
elem.classList = [ 'divStyleLeft' ];
elem.innerText = 'Hello!';
} ) () :
( () =>{
elem.classList = [ 'divStyleRight' ];
elem.innerText = 'Hi!';
} ) ();
}
function recordClick()
{
let theData = document.getElementById("#float").data;
timeEnd = Date.now();
allTrials[numClicks].trialTime = timeEnd - timeStart;
allTrials[numClicks].sidePresented = theData.sidePresented;
allTrials[numClicks].buttonClicked = theData.buttonClicked;
if (numClicks < 11) {
numClicks++;
presentStimulus();
}
else {
document.getElementById("float").style.visibility = "hidden";
let output = "";
for (x = 0; x < allTrials.length; x++)
output = output + "<b>:" + (x + 1) + "</b>:" + allTrials[x].toString();
document.getElementById("display").innerHTML = output;
}
}
</script>
<p id="display"></p>
</body>
There's a bunch of ways you could go about this.
If you're using plain 'ol JS, I'd probably create classes in CSS that float left or right, possibly appear as a flex container that displays left or right, whatever your specific need might be (again, there's a lot of ways to go about it, and one might be better than the other given your context).
When you've determined left or right (gen a random number or whatever), update the classlist on the DOM elements with the desired class to make it go this way or that.
For what it's worth, here's a bare-bones vanilla JS example. Again, I don't know your specific context, but this should give you a start on how to look at it. Floating may not be ideal, you may want to just hide/show containers that already exist on the left or right or actually create whole new DIVs and insert them into known "holder" containers (usually just empty divs), but the idea is the same; gen the random number, alter the classlists of the elements you want to hide/show/move/whatever, and if necessary, alter the innerHTML or text as needed.
<html>
<head>
<style>
.divStyleLeft {
width: 300px;
height: 300px;
background-color: lightblue;
float: left;
}
.divStyleRight {
width: 300px;
height: 300px;
background-color: lightgreen;
float: right;
}
.maxWidth {
width: 100%;
}
</style>
</head>
<body>
<button onclick="onClick()">Click Me</button>
<div class="maxwidth">
<div id="floater" class="divStyleLeft">
I AM NOT FLOATING
</div>
<div>
<script>
function onClick () {
const elem = document.querySelector ( '#floater' );
const min = 1;
const max = 2;
const v = Math.floor(Math.random() * (max - min + 1)) + min;
console.log ( 'Random num is ' + v + ": ", '1 will go left, 2 will go right' );
v === 1 ?
( () => {
elem.classList = [ 'divStyleLeft' ];
elem.innerText = 'I am floating LEFT';
} ) () :
( () =>{
elem.classList = [ 'divStyleRight' ];
elem.innerText = 'I am floating RIGHT';
} ) ();
}
</script>
</body>
</html>
SOLVED! see EDITs
I built a color picker app. Very simple; you click on the rgb color palette, and it creates a swatch with RGB values, HSL values, and HEX values.
I used this formula for the conversions.
Basically, I built my HSL values from the x and y mouse positions with a static 99% saturation.
From there, I created the color palette to pick from by converting HSL to RGB.
A click event on the palette will create RGB, HSL, and HEX swatches along with the values for each.
Since I can't get the RGB and HSL values to match I haven't incorporated the HEX values yet.
I finally found a working solution. Can someone tell me where my calculations drift away from the working solution? I don't just want to accept the working solution and move on; I want to know where my logic starts to break down.
Thanks so much for any help!
EDIT: So Bob__ suggested I use a better way to normalize my RGB values instead of just adding or subtracting 1 depending on their values. I added this function to make the RGB channels based on the hue value(-0.333 - 360.333)
function normalizeRGB(color){
var newVal = (360.333 - (-0.333))/(360.333 - (-0.333)) *
(color- (-0.333) + (-0.333));
return newVal;
}
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Color Picker, Bro</title>
<link href='http://fonts.googleapis.com/css? family=Raleway:700,300' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="style.css">
<script src='https://code.jquery.com/jquery-2.1.3.min.js'></script>
<script type="text/javascript" src='myColorPickerSol.js'></script>
<!-- <script type="text/javascript" src='actualWorkingColorPickerSol.js'></script> -->
</head>
<body>
<div id='container'>
<h1>Color Picker, bro</h1>
<section id='canvas'></section>
<section id='readout'>
<p>HSL: <span id='hsl'></span></p>
<section id='swatchhsl'></section>
<p>RGB: <span id='rgb'></span></p>
<section id='swatchrgb'></section>
<p>HEX: <span id='hex'></span></p>
</section>
</section>
</div>
</body>
</html>
style.css:
body {
background: url(http://subtlepatterns.com/patterns/subtle_white_mini_waves.png);
}
#container {
margin: 0 auto;
width: 800px;
height: inherit;
text-align: center;
font-family: Raleway;
font-weight: 300;
}
#canvas {
margin: 0 auto;
border: 5px solid black;
box-sizing: border-box;
height: 360px;
width: 360px;
}
#readout {
background: rgba(117,117,117, .2);
margin: 20px auto;
height: 400px;
width: 360px;
border: 1px #333 solid;
box-sizing: border-box;
border-radius: 20px;
}
#swatchhsl,#swatchrgb {
margin: 0 auto;
height: 75px;
width: 95%;
border-radius: 20px;
}
p, span {
letter-spacing: 1px;
}
p {
font-weight: 700;
}
span {
font-weight: 300;
}
myColorPickerSol.js
$(document).ready(function(){
var canvas = $('#canvas');
//swatch matches closest when either pure blue, green or red; loses all accuracy when colors mix.
// dark blue gets really close. Purple gets really close, which makes me suspect the Green channel value is where the problem lies.
// y-axis as Luminace(0-100%)
// x-axis as Hue(0-360)
var yPos;
var lum;
var hue;// aka xPos;
var temp1;//for hslToRGB
var temp2;//for hslToRGB
var tempR;
var tempG;
var tempB;
var red;
var blue;
var green;
var realColVal;
$('#canvas').mousemove(function(event){
hue = Math.abs(event.offsetX);
hueForRGB = (hue/360);
yPos = Math.abs(event.offsetY);
lum = (yPos/360);
// console.log(lum + ' lum');
$(canvas).css({'background-color':'hsl('+ event.offsetX + ',99%,'+ Math.round(lum *100) + '%)'});
});
// swatch listener
$(canvas).click(function(event){
hsl2RGB(lum);
$('#rgb').text(red + ','+ green + ',' + blue);
$('#hsl').text(hue + ',99%,' + Math.round(lum * 100) + '%');
$(canvas).css({'background-color':'rgb('+ red + ','+ green + ','+ blue + ')'});
});
//red channel must be in upper third; green in middle third; blue in lower third.
function hsl2RGB(lum){
tempR = (hueForRGB + 0.333);
tempG = hueForRGB;
tempB = (hueForRGB - 0.333);
// set temporary lum based on whether it is above/below 50%
temp1 = lumMorOrLess50(lum);
// set secondary temporary lum value
temp2 = ((2.0 * (lum)) - temp1);
//-----------EDIT -----------------------------
// used the formula to make the tempR|G|B values between 0 and 1
// tempR = makeRGB01(tempR);
// tempG = makeRGB01(tempG);
// tempB = makeRGB01(tempB);
//-----------------------------------------------
red = Math.round(convert2RGB(tempR,temp1,temp2));
green = Math.round(convert2RGB(tempG,temp1,temp2));
blue = Math.round(convert2RGB(tempB,temp1,temp2));
//swatch appears on click for hsl and rgb
$('#swatchhsl').css({'background-color':'hsl('+ hue + ',99%,'+ Math.round(lum * 100 )+ '%)'});
$('#swatchrgb').css({'background-color':'rgb('+ red + ','+ green + ','+ blue + ')'});
};
//force tempR|G|B to be between 0-1
function makeRGB01(input) {
if(input > 1){
input -= 1.0;
} else if(input < 0){
input += 1.0;
};
return input;
};
//get value for each rgb channel
function convert2RGB(tempColVal, val1, val2){
//first convert tempColVal to between 0 and 1 then make it an RGB value
tempColVal = makeRGB01(tempColVal);
//next run 3 test;
if(6.0 * tempColVal < 1){
realColVal = (val2 + (val1 - val2) * 6 * tempColVal);
console.log(realColVal + 'test 1; val1: '+ val1 + 'val2: ' + val2 );
//-------EDIT ------------------------------------------
// test2 will set realColVal to val1 instead of tempColVal
//-------------------------------------------------------
} else if(2.0 * tempColVal < 1){
realColVal = val1;
console.log(realColVal + 'test 2');
} else if(3.0 * tempColVal < 2){
realColVal = (val2 + (val1 - val2)*(0.666 - tempColVal) * 6.0);
console.log(realColVal + 'test 3');
} else {
realColVal = val2;
console.log(realColVal + 'realColVal = default (temp 2)');
};
//-------EDIT ------------------------------------------
// normalize value before multiplying by 255
realColVal = normalizeRGB(realColVal);
//-------------------------------------------------------
// force value between 0 and 1 then set it to RGB scale and
// return
return (Math.abs(realColVal) * 255.0));
};
//configure temporary luminance value, temp1, based on luminance
function lumMorOrLess50(val){
if(val < 0.50){
return ((1.0 + 0.99) * val);
} else {
return ((.99 + val) - (val * .99));
};
};
});
This is the working solution, actualColorPickerSol.js What did I do differently?
$(function() {
console.log('Loaded, bro');
colorPicker();
});
function colorPicker() {
var canvas = $('#canvas');
canvas.on('mousemove', changeCanvasBackground);
canvas.on('click', printColorReadout);
}
function changeCanvasBackground(event) {
var xCoord = Math.abs(event.offsetX);
var yCoord = Math.abs(event.offsetY);
var rgbValues = 'rgb(' + rgb(hsl(xCoord, yCoord)) + ')';
$(this).css('background', rgbValues);
}
function printColorReadout(event) {
var xCoord = event.offsetX;
var yCoord = event.offsetY;
var hslValues = hsl(xCoord, yCoord);
var rgbValues = rgb(hslValues);
var hexValues = hex(rgbValues);
var hslString = parseHSL(hslValues);
var rgbString = parseRGB(rgbValues);
var hexString = parseHEX(hexValues);
$('#hsl').text(hslString);
$('#rgb').text(rgbString);
$('#hex').text(hexString);
$('#swatchhsl').css('background', hslString);
$('#swatchrgb').css('background', rgbString);
}
function hsl(xCoord, yCoord) {
// HSL = hsl(hue, saturation, luminance)
var hsl;
var hue = xCoord;
var luminance = Math.round(((yCoord / 360) * 100));
return [hue, 100, luminance];
}
function rgb(hslValues) {
var hue = hslValues[0];
var sat = hslValues[1] / 100;
var lum = hslValues[2] / 100;
var tempLum1, tempLum2, tempHue, tempR, tempG, tempB;
if (lum < .50) {
tempLum1 = lum * (1 + sat);
} else {
tempLum1 = (lum + sat) - (lum * sat);
}
tempLum2 = (2 * lum) - tempLum1;
tempHue = hue / 360;
tempR = tempHue + .333;
tempG = tempHue;
tempB = tempHue - .333;
//This is the only part I think I did differently.
//The code below makes sure the green and blue values
//are between 0 and 1, then it checks all the colors to
//make sure they are between 0 and 1. I tried this,
// and there was no change in the effect;
// the hsl and rgb values were still different.
if (tempG < 0) { tempG += 1};
if (tempG > 1) { tempG -= 1};
if (tempB < 0) { tempB += 1};
if (tempB > 1) { tempB -= 1};
var normalizedRGB = [tempR, tempG, tempB].map(function(color, idx) {
if (color < 0) { return color += 1};
if (color > 1) { return color -= 1};
return color;
});
var rgbArray = normalizedRGB.map(function(color) {
if (colorCondition1(color)) {
return tempLum2 + ( tempLum1 - tempLum2 ) * 6 * color;
} else if (colorCondition2(color)) {
return tempLum1;
} else if (colorCondition3(color)) {
return tempLum2 + (tempLum1 - tempLum2) * (.666 - color) * 6;
} else {
return tempLum2;
}
});
var rgbValues = rgbArray.map(function(color, idx) {
var convertedVal = color * 255;
return Math.round(convertedVal);
});
return rgbValues;
}
function hex(rgbValues) {
var r = rgbValues[0];
var g = rgbValues[1];
var b = rgbValues[2];
return [numToHex(r), numToHex(g), numToHex(b)];
}
function numToHex(num) {
var hexCode = num.toString(16);
if (hexCode.length < 2) { hexCode = "0" + hexCode; }
return hexCode;
}
function colorCondition1(val) {
return 6 * val < 1;
}
function colorCondition2(val) {
return 2 * val < 1;
}
function colorCondition3(val) {
return 3 * val < 2;
}
function parseHSL(hslValues) {
return [
"hsl(",
hslValues[0], ", ",
hslValues[1], "%, ",
hslValues[2], "%)"
].join('');
}
function parseRGB(rgbValues) {
return "rgb(" + rgbValues.join(', ') + ")";
}
function parseHEX(hexValues) {
return "#" + hexValues.join('');
}
Comparing your functions to the algorythm presented in the link you posted, I think that a more correct implementation of convert2RGB, as I told in my comments, may be:
function convert2RGB(tempColVal, val1, val2){
//first convert tempColVal to between 0 and 1 then make it an RGB value
tempColVal = makeRGB01(tempColVal);
//next run 3 test;
if(6.0 * tempColVal < 1){
realColVal = (val2 + (val1 - val2) * 6.0 * tempColVal);
// console.log(realColVal + 'test 1; val1: '+ val1 + 'val2: ' + val2 );
} else if(2.0 * tempColVal < 1){
realColVal = val1;
// console.log(realColVal + 'test 2');
} else if(3.0 * tempColVal < 2){
realColVal = (val2 + (val1 - val2)*(0.666 - tempColVal) * 6.0);
// console.log(realColVal + 'test 3');
} else {
realColVal = val2;
// console.log(realColVal + 'realColVal = default (temp 2)');
};
// Convert them to 8-bit by multiply them with 255 and return
return Math.round(realColVal * 255.0);
};
Edit:
Don't change your makeRGB01(), in that algorythm is used in the same way you did before calling convert2RGB(). Your mistake is applying that to returned corrected value too.
I have the following code that runs a loop and updates the page as it goes. At the moment the page does not update until the entire loop has run its course.
As you can see, I tried adding a draw function drawValues that is called every 5000 times to draw the current values to the screen. My understanding is that when drawValues is updated, the page should update and then the main loop will resume with its calculations until another 5000 loops.
At the moment the page will not update until the loop runs in its entirety, somehow ignoring every other call to drawValues
Full Snippet:
/*jslint browser: true*/
/*global $, jQuery, alert*/
$(document).ready(function() {
'use strict';
var namesAtStart = ["Sam", "John"],
specialNum = 8,
amountOfNames = namesAtStart.length,
counter = [],
renderCounter = 0,
x,
a,
loopLength,
number,
id,
preId = "content_",
finalId;
for (a = 0; a < amountOfNames; a += 1) {
counter.push(0);
}
for (x = 1; x <= specialNum; x += 1) {
// Start the counter array at zero
for (a = 0; a < amountOfNames; a += 1) {
counter[a] = 0;
}
loopLength = Math.pow(10, x);
finalId = preId + loopLength.toString();
$(".output-small").append('<span id="' + finalId + '"></span>');
for (a = 0; a < loopLength; a += 1) {
number = Math.floor((Math.random() * amountOfNames) + 1);
counter[number - 1] += 1;
renderCounter += 1;
if (renderCounter == 5000) {
drawValues(namesAtStart, counter, finalId, x, a);
}
if (a == loopLength - 1) {
// This is where I am trying to make the code non blocking and async
drawValues(namesAtStart, counter, finalId, x, a);
}
}
}
});
// This is the part that I want to run when called and update page.
function drawValues(names, counter, finalId, id, currentCount) {
'use strict';
var a;
$("#" + finalId).empty();
$("#" + finalId).append("<h3>" + Math.pow(10, id).toLocaleString() + "</h1>");
for (a = 0; a < names.length; a += 1) {
$("#" + finalId).append(
names[a] + ": " + counter[a].toLocaleString() + " (" + (counter[a] / currentCount * 100).toFixed(2) + "%)</br>"
);
}
$("#" + finalId).append("Numerical Difference: " + Math.abs(counter[0] - counter[1]) + "</br>");
$("#" + finalId).append(
"Percentage Difference: " + Math.abs(
(counter[0] / currentCount * 100) - (counter[1] / currentCount * 100)
).toFixed(6) + "%</br>"
);
$("#" + finalId).append("</br>");
}
body {} p,
h3 {
padding: 0px;
margin: 0px;
}
.container {} .output {} .output-small {
margin: 20px;
padding: 5px;
border: 1px solid rgba(0, 0, 0, 1);
width: 300px;
border-radius: 10px;
}
#stats-listing {}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<title>Roll The Dice</title>
<body>
<div class="container">
<div class="output" id="stats-listing">
<div class="output-small"></div>
</div>
</div>
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script src="logic.js"></script>
</body>
</html>
The main UI thread in browsers, which is used to run JavaScript, is single-threaded. So if you have a function that's taking a lot of time, the browser doesn't update the display.
To give the browser a chance to update the display, you need to yield back to it by letting your current function end and scheduling a timed callback to another run of it for the next block of updates, via setTimeout. You'll have to experiment with the browsers you want to support to determine the delay in the timed callback; some browsers are happy with 0 (call back as soon as possible), others want longer (50 — 50 milliseconds — is plenty for every browser I know).
Here's a simple example that adds 10 boxes to the page, yields, then adds another 10, yields, etc. until it's done 1,000 boxes:
(function() {
var total = 0;
addBoxes();
function addBoxes() {
var n;
for (n = 0; n < 10 && total < 1000; ++n, ++total) {
box = document.createElement('div');
box.className = "box";
document.body.appendChild(box);
}
if (total < 1000) {
setTimeout(addBoxes, 10); // 10ms
}
}
})();
.box {
display: inline-block;
border: 1px solid green;
margin: 2px;
width: 20px;
height: 20px;
}