I have an issue with zooming in and out multiple elements with CSS zoom property, hard to explain it without showing the actual effect so I uploaded this on youtube:
here it is
I would like the font to zoom smoother than this, hopefully.
I've tried using scale property here but it ruins positioning, these are my current functions:
let zoom_param = 1;
function zooming_out(on_off) {
if (on_off == 0) {
if (zoom_param >= 0.1) {
zoom_out = setInterval(function() {
blocks.style.transition = 50 + 'ms';
blocks.style.zoom = zoom_param;
side_blocks.style.transition = 50 + 'ms';
side_blocks.style.zoom = zoom_param;
zoom_param -= 0.001;
}, 5);
}
} else {
clearInterval(zoom_out);
}
}
function zooming_in(on_off) {
if (on_off == 0) {
zoom_in = setInterval(function() {
blocks.style.transition = 50 + 'ms';
blocks.style.zoom = zoom_param;
side_blocks.style.transition = 50 + 'ms';
side_blocks.style.zoom = zoom_param;
zoom_param += 0.001;
}, 5);
} else {
clearInterval(zoom_in);
}
}
they are called by a mousedown and mouseup events (idk if it is important),
Thanks for help!
The CSS property zoom is not well supported. Try it with transform instead. No timers needed, the animation will be smooth as well. Hope this code snippets can help you.
var element = document.querySelector('.element');
element.style.transition = 'transform';
element.style.transitionTimingFunction = 'linear';
element.style.transformOrigin = 'left top';
element.style.transitionDuration = '2s';
let zoomMin = 1;
let zoomMax = 2;
document.querySelector('.zoom-in').addEventListener('click', function(e) {
zoomingIn();
});
document.querySelector('.zoom-stop').addEventListener('click', function(e) {
zoomingStop();
});
document.querySelector('.zoom-out').addEventListener('click', function(e) {
zoomingOut();
});
function zoomingStop() {
let scaleX = element.getBoundingClientRect().width / element.offsetWidth;
element.style.transform = 'scale(' + scaleX + ', ' + scaleX + ')';
}
function zoomingIn() {
element.style.transform = 'scale(' + zoomMax + ', ' + zoomMax + ')';
}
function zoomingOut() {
element.style.transform = 'scale(' + zoomMin + ', ' + zoomMin + ')';
}
div {
margin: 20px;
padding: 20px;
width: 100px;
height: 100px;
background: #0095ff;
}
<button class="zoom-in">zoomIn</button>
<button class="zoom-stop">stop</button>
<button class="zoom-out">zoomOut</button>
<div class="element">
<p>Some</p>
<p>Text</p>
</div>
Related
I'm trying to create a progress bar with a percentage text using only Javascript, but I don't know what value I need set in the function to limit the incrementation. The bar and the text keep increasing.
Need create 4 skills bar with 30% / 50% / 70% and 90%.
Help, plz! Accept any suggestions!
Here is my code.
<div class="progress">
<div class="progress-bar"></div>
<p value="30" class="text">30</p>
</div>
<script>
function update() {
let element = document.querySelector(".progress-bar");
let counter = document.querySelector(".text");
var width = 1;
var identity = setInterval(scene, 10);
function scene() {
if (width >= counter.value) {
clearInterval(identity);
} else {
width++;
element.style.width = width + '%';
counter.innerHTML = width * 1 + '%';
}
}
}
</script>
I am not sure if I am following the issue you are experiencing. I see your code can be improved and would solve some problems. Here what I suggest:
function update() {
let element = document.querySelector(".progress-bar");
let counter = document.querySelector(".text");
let width = 1;
setTimeout(scene, 1);
function scene() {
if (width < 100) {
width++;
element.style.width = width + '%';
counter.innerHTML = width * 1 + '%';
setTimeout(scene, 1);
} else {
//Complete action here
}
}
}
Welcome to Stackoverflow! Below you can see a working example of your code with minimal changes. I just defined that when the percenteage comes up to 100, it clears the interval on the page.
function update() {
let element = document.querySelector(".progress-bar");
let counter = document.querySelector(".text");
var percenteage = 0;
var identity = setInterval(scene, 50);
function scene() {
if (percenteage < 100) {
percenteage++;
element.style.width = percenteage + '%';
counter.innerHTML = percenteage + ' %';
} else {
clearInterval(identity);
console.log("Cleared!");
}
}
}
update();
.progress-bar {
height: 10px;
background-color: red;
}
<div class="progress">
<div class="progress-bar"></div>
<p value="30" class="text">30</p>
</div>
There are some runner(animation-image) in my program which move from position x to y when clicked on start button, i want to add a (reverse)button on completion that when clicked on that the image moves from y to x.
Here is the link of my js-fiddle: https://jsfiddle.net/o6egL4qr/
I have added the reverse button but when clicked on that the image doesn't move at all.
class raceManager {
raceCount = 0;
races = [];
addRace() {
var mainContainer = document.getElementById('mainContainer');
mainContainer.appendChild(document.createElement('br'));
var race = new raceClass(this.raceCount);
this.races.push(race);
this.raceCount++;
}
}
class raceClass {
runners = [];
count;
runnerCount = 0;
raceDiv = document.createElement('div');
raceNum = document.createElement('div');
startRaceButton = document.createElement('input');
addRunnerButton = document.createElement('input');
revRaceButton = document.createElement('input');
tableDiv = document.createElement('div');
tableNum = document.createElement('div');
startInterval;
startTime;
revStartTime;
reverseInterval;
constructor(number) {
// store the race no.
this.count = number;
// delcare the race div id
this.raceNum.id = 'raceNum' + this.count;
// delcare the table div id
this.tableNum.id = 'tableNum' + this.count;
// Add raceDiv to the race
document.getElementById('races').appendChild(this.raceDiv);
// Add tableDiv to the race
document.getElementById('tables').appendChild(this.tableDiv);
this.applyDivProperty();
this.initializeButtons();
}
applyDivProperty() {
// apply properties to the tableNum
this.tableNum.style.display = "inline-block";
// apply properties to the raceDiv
this.raceDiv.id = "Race" + this.count;
document.getElementById(this.raceDiv.id).classList.add("raceDivClass");
this.raceDiv.appendChild(this.raceNum);
document.getElementById(this.raceNum.id).innerHTML = '<p>Race: ' + this.count + '</p>';
// append the add race button
this.raceDiv.appendChild(this.addRunnerButton);
// apply properties to the tableDiv
this.tableDiv.id = "Table" + this.count;
document.getElementById(this.tableDiv.id).classList.add("tableClass");
this.tableDiv.appendChild(this.tableNum);
document.getElementById(this.tableNum.id).innerHTML = '<p>Table: ' + this.count + '</p>';
}
initializeButtons() {
// initialize add runner button
this.addRunnerButton.type = 'Button';
this.addRunnerButton.value = 'Add Runner';
this.addRunnerButton.id = 'AddRunner' + this.count;
this.addRunnerButton.onclick = this.addRunner.bind(this);
// initialize start race buttton
this.startRaceButton.type = 'Button';
this.startRaceButton.value = 'Start Race';
this.startRaceButton.id = "startRaceButton" + this.count;
this.startRaceButton.onclick = this.startRace.bind(this);
// initialize reverse race buttton
this.revRaceButton.type = 'Button';
this.revRaceButton.value = 'Reverse Race';
this.revRaceButton.id = "revRaceButton" + this.count;
this.revRaceButton.onclick = this.revRace.bind(this);
}
addRunner() {
var track = new Runner(this); //Initialize the runner object
this.runners.push(track); //Store the runner object in runners array of Race class
if (this.runnerCount > 0) {
// append the start race button
this.raceDiv.appendChild(this.startRaceButton);
}
this.runnerCount++;
}
startRace() {
this.startTime = Date.now();
this.startInterval = setInterval(() => {
this.runners.forEach(function(element) {
element.animate();
});
document.getElementById(this.startRaceButton.id).disabled = "true";
document.getElementById(this.addRunnerButton.id).disabled = "true";
}, 50);
}
stop() {
clearInterval(this.startInterval);
// append the start race button
this.raceDiv.appendChild(this.revRaceButton);
}
revRace() {
this.revStartTime = Date.now();
this.reverseInterval = setInterval(() => {
this.runners.forEach(function(element) {
element.animateReverse();
});
document.getElementById(this.revRaceButton.id).disabled = "true";
}, 50);
}
stopRev() {
clearInterval(this.reverseInterval);
}
}
class Runner {
count = 0;
parent;
track;
sprite;
timeTaken;
trackWidth;
element;
speed;
table;
printCount = 1;
stepCount = 1;
trackNum;
tbl;
lastStep;
constructor(race) {
// initialize the divs
this.parent = race;
this.track = document.createElement('div');
this.sprite = document.createElement('div');
this.table = document.createElement('table');
// assigns #id to table and track corresponding with parent div.
this.table.id = race.tableNum.id + '_Table_' + this.parent.runnerCount;
this.track.id = race.raceNum.id + '_Track_' + this.parent.runnerCount;
this.createUI();
this.timeTaken = ((Math.random() * 5) + 3);
this.speed = this.trackWidth / (this.timeTaken * 1000);
console.log(this.trackWidth, this.timeTaken);
console.log(this.timeTaken * 100);
}
createUI() {
this.count = this.parent.runnerCount;
this.createTable();
this.createTrack();
this.createSprite();
}
createTable() {
var parentDiv1 = document.getElementById(this.parent.tableNum.id);
parentDiv1.appendChild(this.table);
this.table.setAttribute = "border"
this.table.border = "1";
document.getElementById(this.table.id).classList.add("tableClass");
this.tbl = document.getElementById(this.table.id);
this.addRow("Track " + (this.count + 1), "");
this.addRow("Time", "Distance");
}
addCell(tr, val) {
var td = document.createElement('td');
td.innerHTML = val;
tr.appendChild(td)
}
addRow(val_1, val_2) {
var tr = document.createElement('tr');
this.addCell(tr, val_1);
this.addCell(tr, val_2);
this.tbl.appendChild(tr)
}
createTrack() {
var parentDiv = document.getElementById(this.parent.raceNum.id);
parentDiv.appendChild(this.track);
this.track.appendChild(this.sprite);
document.getElementById(this.track.id).classList.add("trackClass");
this.trackWidth = this.track.getBoundingClientRect().width;
}
createSprite() {
this.sprite.id = this.track.id + "_Runner";
document.getElementById(this.sprite.id).classList.add("spriteClass");
this.element = document.getElementById(this.sprite.id);
}
animate() {
// declare time variables
var timeNow = Date.now();
var timespent = timeNow - this.parent.startTime;
var diff = Math.floor(this.timeTaken * 100);
// step is position of sprite.
var step = timespent * this.speed;
// Print table for all tracks with 10 laps.
if ((Math.round(timespent / 50) * 50) == (Math.round(((diff - 25) * this.printCount) / 50) * 50)) {
this.addRow(this.printCount + ": " + timespent, (Math.floor(step)));
this.printCount++;
}
// check condition to stop
if (step > this.trackWidth - 23) {
document.getElementById(this.parent.raceNum.id).innerHTML += 'Winner: Runner' + (this.count + 1);
this.parent.stop();
}
this.element.style.left = step + 'px';
// ------------sprite animation----------------
// start position for the image slicer
var position = (3 - (Math.floor(step / 6.5) % 4)) * 25;
// we use the ES6 template literal to insert the variable "position"
this.element.style.backgroundPosition = `${position}px 0px`;
}
animateReverse() {
// declare time variables
var timeNow = Date.now();
var timespent = timeNow - this.parent.revStartTime;
var diff = Math.floor(this.timeTaken * 100);
console.log(this.count + " position of step " + this.element.style.left);
while (this.stepCount < 2) {
this.lastStep = parseFloat(this.element.style.left);
this.stepCount++;
}
console.log(this.count + " this is lastStep " + this.lastStep);
// step is position of sprite.
var step = this.lastStep - (this.speed * timespent);
// Print table for all tracks with 10 laps.
if ((Math.round(timespent / 50) * 50) == (Math.round(((diff - 25) * this.printCount) / 50) * 50)) {
this.addRow(this.printCount + ": " + timespent, (Math.floor(step)));
this.printCount++;
}
// check condition to stop
if (step < 25) {
document.getElementById(this.parent.raceNum.id).innerHTML += 'Winner: Runner' + (this.count + 1);
this.parent.stopRev();
}
this.element.style.left = step + 'px';
// ------------sprite animation----------------
// start position for the image slicer
//var position = (3 - (Math.floor(step / 6.5) % 4)) * 25;
//this.element.style.backgroundPosition = position + 'px 0px';
}
}
manager = new raceManager();
#tableContainer {
float: left;
}
#addRaces {
text-align: center;
}
.raceDivClass {
margin: 1% auto;
width: 60%;
text-align: center;
border: 1px solid;
}
.tableClass {
text-align: center;
border: 1px solid;
margin: 5px;
float: left;
}
.trackClass {
background-color: black;
height: 30px;
width: 98%;
margin: 1%;
position: relative;
}
.spriteClass {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGgAAAAeCAYAAADAZ1t9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAASwSURBVGhD7Zq/axRBFMfv9u4MxATUSgsVm3QWigYbexuxUkiaKIqNoIUiwRSJoJLCxpSCaJoEYimo/4AgQVRIZxdBEIREYwzc5X74vndvlrm5mdnZ3dm9oPnAsDubu52Z93373pvNFQsJOXO9NUKHsU4vZPH90+IXPt/FA2kEmqbDTKcX8pza7K5I/vAtEJghge7zeSrwlDYbtYlmfWuILxWC8uBmUNoz/784wY4WaPRq9SGJcY+7Mt7GEOzUkB0pkGHi4Ci1K53TEK8h7tTE+pPywL6b3JXJQqBcQ7arQwR87AE34ElPUsPE1ZapODsErFHnnD7AfVWb9oylFYjVFcKoQuQC5kD55hB3Qxrbf17RYbHT+/fpCXGSOEmEaYcevofwhkRxXM0/VCi8azXr3+q1Xw8+LRxZ4cte4PneoHaQ2iVck0gVThVbyOhSRM9YOoFMyR9eW6KmLkAGYW6Vmjx47AViUfSkPC5V9p7nS23q1Z9zH+b33+KuF9iAOocUa0lcKFjubQJ2h51D5zbmIAVM9gc1mzgAE0kdFlFaq+JkQYQBV+FYOYoDGy9Tw3dgQ7QxnUBQUHxAtJfUhqllDhbWam4f525mJDCgMynufZFa13d6BILHsOeEjS6PUjMNtsRHFXgExI2V0PN6egiEkTzFMdlJgM/3zMd1H2Tzhjlqa53TLhLFbsvep9Cob70uFsuffbxJoHWZcq1A5CCZyDUZ7gtxotKDCsafdRHIZSFe9j9wBl1xoIJSuxhUVpIK5eB0JiILHo29EouDtVmLBF4IKjIbWOQkfzYVruENn+ESXFe+upBJeDMQVfWiyXQ5fFQV57oQLyLJL0VlsAfi06yJyhMuIOci7Efdqy0ENzxxonVFI22IY0NDHN1mykaX+nHAmKbw1qhtLLVaze8U1o6Jv9OmdaEYlI1lsLQGGVGwmMKbKZ8KXHIQxnUJn062CgVSFmQTRjySpr8n2nlb3lxTztl8W6+u3x0YOlylrpij1Vi0Hl3uxNx/U9MWIYSPtwZxclukSG2B4qreOTV+3skzBBgbuafVrJ0sVYbO8eUe4r5FMAgEbEnbSSC2l/p0grgRB1jHDGKqjt019kkwvoid4okS4D7O+Qji4MmxiQMonI2cGP/qYwMbt6LSAXFEzpCbyYaJcxuKBAwWJQ5EwATCTScLBeUhVGKRTIWBCgQsVYavcdcF8UZEnVveYPwXfIwNBMJCdF/GNeEZCFnahMzX1A0dgEi6MJALigP1SyiMCdu9wZH7sZBzkGpM5zcBljAZGdNPX964UAhKt0vlwbN8SQs2p/Xq2lTSfzU4hvK0OUily4b0PV1etI4Z+SbBFYMBrIPjO1QuT1N+GedLbVC1FYM9Hyk31fgScHYYE5JhD1Dz/r+fKPoqEJAMILAa1VRaU+HwaPnZwBR3vWJwJCDCUSonsKERKHJMrwLFAYbSbUwRyujanawMZfBikPXTEzvCgKhXPZmhe+/W2ZCuTWXpxQbgyWGFmhGILLb8p6V/AmnKa+Qd3783cCDz0JaGvgmEX4jyaRu8W6N8NM/dPGlvvvk8T5ye2r7mIIQ5PEl5/pyXc4FzIeOLZOMWCn8Bh1eBvOSZzIIAAAAASUVORK5CYII=');
position: absolute;
height: 30px;
width: 25px;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="mainContainer">
<div id="addRaces">
<input type="Button" value="Add Race" onclick="manager.addRace()">
</div>
<div id="races">
</div>
<br>
</div>
<div id="tableContainer">
<div id="tables"></div>
</div>
</body>
</html>
I expect it to move from y to x after clicking the reverse button, but it is not moving.
When you run the reverse function the elements are no longer referencing the dom elements.
I am actually not sure why that is, maybe someone else can chime in.
Anyway, this will fix your problem:
Replace this.element.style.left = step + 'px';
With: document.getElementById(this.element.id).style.left = step + 'px';
I have a strange problem. I have digged up this code snippet that allows a text row to be animated left and then repeated infinitely. While this works perfectly. I'd like to have all the rows to be animated on body load but much slower. And then when you mouseover on each of the rows the animation picks up more speed.
https://codepen.io/umbriel/pen/RjYqRR
So far I've tried stuff like looping each of the questions and then running the animation. But it still only grabbed one of the divs and animated it.
var el_text = questions[i].querySelectorAll('.intro-question-text');
for (var i = 0; i < el_text.length; i++) {
el_text[i].style.transform = 'translate3d(' + qScrollPositions[i] + 'px,0,0)'
}
Any pointers? Thank you so much!
You can get it to do what you want by using the setInterval function (and swapping it out to a quicker one when the user hovers over the element).
var textCopy = document.querySelectorAll('.intro-question-text')
for (var i = 0; i < textCopy.length; i++) {
var text = textCopy[i].innerHTML.repeat(5)
textCopy[i].insertAdjacentHTML('beforeend', text)
}
var WIN_H,
WIN_W,
qFrame = [];
var questions = document.querySelectorAll('.intro-question');
var scrollRequest;
var qScrollPositions = [];
var passiveRepeaters = [];
var repeater;
function initIntroScript() {
Array.prototype.map.call(questions, function(q, i) {
addImageHover(i);
})
window.addEventListener('resize', resizeHandler);
resizeHandler();
}
function addImageHover(i) {
qFrame[i] = 0;
qScrollPositions[i] = Math.floor(Math.random() * -200);
questions[i].querySelector('.intro-question-text').style.transform = 'translate3d(' + qScrollPositions[i] + 'px,0,0)';
questions[i].addEventListener('mouseenter', function() {
//console.log("mouseenter -> " + i);
clearInterval(passiveRepeaters[i]);
repeater = setInterval(function() {
scrollQuestionText(i);
}, 10);
});
questions[i].addEventListener('mouseleave', function() {
//console.log("mouseleave -> " + i);
clearInterval(repeater);
passiveRepeaters[i] = setInterval(function() {
scrollQuestionText(i);
}, 20);
});
passiveRepeaters[i] = setInterval(function() {
scrollQuestionText(i);
}, 20);
}
function scrollQuestionText(i) {
var shift = Math.floor(4 + WIN_W/800) * Math.min(0.2, qFrame[i] / 20);
cancelAnimationFrame(scrollRequest);
var el_text = questions[i].querySelector('.intro-question-text');
qScrollPositions[i] = qScrollPositions[i] - shift;
if (qScrollPositions[i] < -el_text.clientWidth / 2 - 5) {
qScrollPositions[i] = 0;
}
el_text.style.transform = 'translate3d(' + qScrollPositions[i] + 'px,0,0)'
qFrame[i]++;
}
initIntroScript();
function resizeHandler() { // NEEDS TO NOT BREAK ON RESIZE
WIN_W = window.innerWidth;
WIN_H = window.innerHeight;
}
body {
font-family: sans-serif;
font-size:4rem;
}
.intro-question {
position: relative;
color: #000000;
cursor: pointer;
transition: .3s;
white-space: nowrap;
padding: 0;
backface-visibility: hidden;
will-change: transform, color, background;
flex-shrink: 2;
/* opacity: 0; */
transition: opacity .5s, transform 1s ease-out;
z-index: 2;
}
.intro-question-text {
backface-visibility: hidden;
will-change: transform;
position: relative;
display: inline-block;
transition: .5s opacity;
}
<div class="intro-questions">
<div class="intro-question">
<div class="intro-question-text white">
Testing content in here
</div>
</div>
<div class="intro-question">
<div class="intro-question-text white">
Content testing
</div>
</div>
<div class="intro-question">
<div class="intro-question-text white">
Content stackoverflow please
</div>
</div>
</div>
edit
You can increase the framerate by reducing the interval between the function calls, for example
questions[i].addEventListener('mouseenter', function() {
//console.log("mouseenter -> " + i);
clearInterval(passiveRepeaters[i]);
repeater = setInterval(function() {
scrollQuestionText(i);
}, 10);
});
questions[i].addEventListener('mouseleave', function() {
//console.log("mouseleave -> " + i);
clearInterval(repeater);
passiveRepeaters[i] = setInterval(function() {
scrollQuestionText(i);
}, 20);
});
passiveRepeaters[i] = setInterval(function() {
scrollQuestionText(i);
}, 20);
if you do this and don't want the scrolling to speed up you can decrease the step size like this
var shift = Math.floor(4 + WIN_W/800) * Math.min(0.2, qFrame[i] / 10);
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.
var start_mouse_y = 0;
var scroll_offset = 0;
function SET_SCROLL(e){
document.getElementById("online_list_scroll").draggable = true;
start_mouse_y = e.clientY;
}
function ADJUST_SCROLL(e){
dont_pass = (412 - set_scroll_height);
mouse_y = e.clientY;
scroll_top = parseInt(document.getElementById("online_list_scroll").style.top);
scroll_offset = (mouse_y - scroll_top) + 46;
new_top = scroll_top + (mouse_y - start_mouse_y);
document.getElementById("DEBUG").innerHTML = "my: "+mouse_y+"<br>new_top: "+new_top+"<br>scroll_offset: "+scroll_offset+"<br>scroll_top: "+scroll_top;
if(new_top <= 0){
document.getElementById("online_list_scroll").style.top = 0+"px";
}else if(new_top >= dont_pass){
document.getElementById("online_list_scroll").style.top = dont_pass+"px";
}else{
document.getElementById("online_list_scroll").style.top = new_top+"px";
}
scroll_bottom = set_scroll_height + new_top;
scroll_percent = scroll_bottom / 412;
online_show = (document.getElementById("online_list").scrollHeight - 412) * scroll_percent;
online_show = Math.round(online_show);
document.getElementById("online_list").scrollTop = online_show;
}
var SCROLL_ON = 0;
document.onmouseup = function(){ SCROLL_ON = 0; };
document.onmousemove = function(event){ if(SCROLL_ON == 1){ADJUST_SCROLL(event);} };
javascript ^^
<div style="float: left; width: 13px; position: relative; height: 412px;">
<div id="online_list_scroll" style="width: 5px; position: absolute; top: 0px; left: 4px; border-radius: 4px; background-color: #3f3f3f; height: 15px;" onmousedown="if(SCROLL_ON == 0){ SET_SCROLL(event); SCROLL_ON = 1; }"></div>
</div>
html^^
i dont know why but the scroll bar scrolls at a very fast and unsteady flow rate. it works, but just jerks when scrolls up and down, jerk as in as u move one way it shoots that way quicker and quicker.
Thanks for any help, worked figuring out how to do this all night.
You have a problem with local var the following code works. Not made as a general thing, just repaired the code. Here you have the code with the comments where is the common mistake.
//first make sure you have defined with var the variables you need.
var start_mouse_y = 0;
var mouse_y = 0;
var scroll_offset = 0;
function SET_SCROLL(e) {
document.getElementById("online_list_scroll").draggable = true;
start_mouse_y = e.clientY;
// you need mouse_y to be initialized with start_mouse_y
mouse_y = start_mouse_y;
}
function ADJUST_SCROLL(e) {
var set_scroll_height = 0;
var dont_pass = (412 - set_scroll_height);
// here you set the last mouse_y to be start_mouse_y or else it would be
// a the first position of the mouse ( eg. 8 ) subtracted from the current ( eg. 50 )
// now remembering the last already added position (eg. 49) which is subtracted from
// the current (eg. 50 ) it works just fine
start_mouse_y = mouse_y;
mouse_y = e.clientY;
var scroll_top = parseInt(document.getElementById("online_list_scroll").style.top);
scroll_offset = (scroll_top- mouse_y ) + 46;
var new_top = scroll_top + (mouse_y- start_mouse_y);
console.log("my: " + mouse_y + "<br>new_top: " + new_top + "<br>scroll_offset: " + scroll_offset + "<br>scroll_top: " + scroll_top);
if(new_top <= 0) {
document.getElementById("online_list_scroll").style.top = 0 + "px";
} else if(new_top >= dont_pass) {
document.getElementById("online_list_scroll").style.top = dont_pass + "px";
} else {
document.getElementById("online_list_scroll").style.top = new_top + "px";
}
var scroll_bottom = set_scroll_height + new_top;
var scroll_percent = scroll_bottom / 412;
var online_show = (document.getElementById("online_list").scrollHeight - 412) * scroll_percent;
online_show = Math.round(online_show);
document.getElementById("online_list").scrollTop = online_show;
}
var SCROLL_ON = 0;
document.onmouseup = function() {
SCROLL_ON = 0;
};
document.onmousemove = function(event) {
if(SCROLL_ON == 1) {ADJUST_SCROLL(event);
}
};
Best regards,