I am creating a color slider, and I'm trying to make the slider's background-color
a dynamic gradient. I've successfully did it, but I feel this can be done in a lot less code than what I have.
What I currently have is, I go through every slider (without a loop), and give it the correct gradient. I'm sure there is a couple liner thing that can do it, and I want to know what that is.
On each slider there's a div
on the right and left side. Each one of those are half a circle, and solid colors. The reason I don't make the roundness part of the actual slider, (i.e. border-bottom-right-radius: 10px;
) is because the color won't be 100% accurate then. I think. Please correct me if I'm wrong.
Here's the code for just one slider. I have a lot more though:
setGradient(slider[0], "right", [rgba2cssString(0, rgb.g, rgb.b), rgba2cssString(255, rgb.g, rgb.b)]);
slider[0].previousElementSibling.style.backgroundColor = rgba2cssString(0, rgb.g, rgb.b);
slider[0].nextElementSibling.style.backgroundColor = rgba2cssString(255, rgb.g, rgb.b);
Please let me know what you think about this whole thing, and if you have any suggestions, other than to use jQuery.
var myColor = new Colors(),
overallSlidersWrapper = document.getElementById('overallSlidersWrapper'),
slider = document.getElementsByClassName('slider'),
type,
mode,
isLabAB = false,
startPoint,
currentTargetWidth,
maxReal = {
rgb: {
r: 255,
g: 255,
b: 255
},
hsl: {
h: 360,
s: 100,
l: 100
},
hsv: {
h: 360,
s: 100,
v: 100
},
Lab: {
L: 100,
a: 256,
b: 256
}
};
var sliderDown = function(e) {
var target = e.target || e.srcElement,
currentTarget;
if (target !== this) {
if (e.preventDefault) e.preventDefault();
if (hasClass(target, 'sliderRange') || hasClass(target, 'sliderCursor')) {
currentTarget = target.parentNode;
} else if (hasClass(target, 'slider')) {
currentTarget = target;
} else if (hasClass(target, 'leftRoundness')) {
currentTarget = target.nextElementSibling;
} else if (hasClass(target, 'rightRoundness')) {
currentTarget = target.previousElementSibling;
} else {
return;
}
var currentModeType = getModeType(currentTarget);
type = currentModeType.type;
mode = currentModeType.mode;
isLabAB = currentModeType.isLabAB;
startPoint = getOrigin(currentTarget);
currentTargetWidth = currentTarget.offsetWidth;
sliderMove(e);
addEvent(window, 'mousemove', sliderMove);
startRender();
}
},
sliderMove = function(e) {
var newColor = {};
newColor[mode] = (e.clientX - startPoint.left) / currentTargetWidth * maxReal[type][mode];
myColor.setColor(newColor, type);
},
renderColorSliders = function(color) {
for (var n = slider.length; n--;) {
var currentModeType = getModeType(slider[n]),
localType = currentModeType.type,
localMode = currentModeType.mode,
isLabAB = currentModeType.isLabAB;
slider[n].firstElementChild.style.left = (color.RND[localType][localMode] / maxReal[localType][localMode] * 100) + '%';
slider[n].firstElementChild.style.borderColor = color.RGBLuminance > 0.22 ? 'black' : 'white';
}
};
var result = document.getElementById('result');
function renderResult(color) {
result.style.backgroundColor = rgba2cssString(color.RND.rgb.r, color.RND.rgb.g, color.RND.rgb.b);
}
function renderGradients(color) {
var rgb = color.RND.rgb,
hsl = color.RND.hsl,
hsv = color.RND.hsv,
Lab = color.RND.Lab;
setGradient(slider[0], "right", [rgba2cssString(0, rgb.g, rgb.b), rgba2cssString(255, rgb.g, rgb.b)]);
setGradient(slider[1], "right", [rgba2cssString(rgb.r, 0, rgb.b), rgba2cssString(rgb.r, 255, rgb.b)]);
setGradient(slider[2], "right", [rgba2cssString(rgb.r, rgb.g, 0), rgba2cssString(rgb.r, rgb.g, 255)]);
setGradient(slider[3], "right", [hsla2cssString(0, hsl.s, hsl.l), hsla2cssString(60, hsl.s, hsl.l), hsla2cssString(120, hsl.s, hsl.l), hsla2cssString(180, hsl.s, hsl.l), hsla2cssString(300, hsl.s, hsl.l), hsla2cssString(360, hsl.s, hsl.l)]);
setGradient(slider[4], "right", [hsla2cssString(hsl.h, 0, hsl.l), hsla2cssString(hsl.h, 100, hsl.l)]);
setGradient(slider[5], "right", [hsla2cssString(hsl.h, hsl.s, 0), hsla2cssString(hsl.h, hsl.s, 50), hsla2cssString(hsl.h, hsl.s, 100)]);
setGradient(slider[6], "right", [hsva2cssString(0, hsv.s, hsv.v), hsva2cssString(60, hsv.s, hsv.v), hsva2cssString(120, hsv.s, hsv.v), hsva2cssString(180, hsv.s, hsv.v), hsva2cssString(300, hsv.s, hsv.v), hsva2cssString(360, hsv.s, hsv.v)]);
setGradient(slider[7], "right", [hsva2cssString(hsv.h, 0, hsv.v), hsva2cssString(hsv.h, 100, hsv.v)]);
setGradient(slider[8], "right", [hsva2cssString(hsv.h, hsv.s, 0), hsva2cssString(hsv.h, hsv.s, 50), hsva2cssString(hsv.h, hsv.s, 100)]);
setGradient(slider[9], "right", [Laba2cssString(0, Lab.a, Lab.b), Laba2cssString(100, Lab.a, Lab.b)]);
setGradient(slider[10], "right", [Laba2cssString(Lab.L, -128, Lab.b), Laba2cssString(Lab.L, 128, Lab.b)]);
setGradient(slider[10], "right", [Laba2cssString(Lab.L, Lab.a, -128), Laba2cssString(Lab.L, Lab.a, 128)]);
slider[0].previousElementSibling.style.backgroundColor = rgba2cssString(0, rgb.g, rgb.b);
slider[0].nextElementSibling.style.backgroundColor = rgba2cssString(255, rgb.g, rgb.b);
slider[1].previousElementSibling.style.backgroundColor = rgba2cssString(rgb.r, 0, rgb.b);
slider[1].nextElementSibling.style.backgroundColor = rgba2cssString(rgb.r, 255, rgb.b);
slider[2].previousElementSibling.style.backgroundColor = rgba2cssString(rgb.r, rgb.g, 0);
slider[2].nextElementSibling.style.backgroundColor = rgba2cssString(rgb.r, rgb.g, 255);
slider[3].previousElementSibling.style.backgroundColor = hsla2cssString(0, hsl.s, hsl.l);
slider[3].nextElementSibling.style.backgroundColor = hsla2cssString(360, hsl.s, hsl.l);
slider[4].previousElementSibling.style.backgroundColor = hsla2cssString(hsl.h, 0, hsl.l);
slider[4].nextElementSibling.style.backgroundColor = hsla2cssString(hsl.h, 100, hsl.l);
slider[5].previousElementSibling.style.backgroundColor = hsla2cssString(hsl.h, hsl.s, 0);
slider[5].nextElementSibling.style.backgroundColor = hsla2cssString(hsl.h, hsl.s, 100);
slider[6].previousElementSibling.style.backgroundColor = hsva2cssString(0, hsv.s, hsv.v);
slider[6].nextElementSibling.style.backgroundColor = hsva2cssString(360, hsv.s, hsv.v);
slider[7].previousElementSibling.style.backgroundColor = hsva2cssString(hsv.h, 0, hsv.v);
slider[7].nextElementSibling.style.backgroundColor = hsva2cssString(hsv.h, 100, hsv.v);
slider[8].previousElementSibling.style.backgroundColor = hsva2cssString(hsv.h, hsv.s, 0);
slider[8].nextElementSibling.style.backgroundColor = hsva2cssString(hsv.h, hsv.s, 100);
slider[9].previousElementSibling.style.backgroundColor = Laba2cssString(0, Lab.a, Lab.b);
slider[9].nextElementSibling.style.backgroundColor = Laba2cssString(100, Lab.a, Lab.b);
slider[10].previousElementSibling.style.backgroundColor = Laba2cssString(Lab.L, -128, Lab.b);
slider[10].nextElementSibling.style.backgroundColor = Laba2cssString(Lab.L, 128, Lab.b);
slider[11].previousElementSibling.style.backgroundColor = Laba2cssString(Lab.L, Lab.a, -128);
slider[11].nextElementSibling.style.backgroundColor = Laba2cssString(Lab.L, Lab.a, 128);
}
addEvent(overallSlidersWrapper, 'mousedown', sliderDown);
function removeMouseUpEvents() {
removeEvent(window, 'mousemove', sliderMove);
stopRender();
}
addEvent(window, 'mouseup', removeMouseUpEvents);
var doRender = function(color) {
renderColorSliders(color);
renderResult(color);
renderGradients(color);
},
renderTimer,
startRender = function() {
renderTimer = setInterval(function() {
doRender(myColor.colors);
// http://stackoverflow.com/questions/2940054/
}, 13); // 1000 / 60); // ~16.666 -> 60Hz or 60fps
},
stopRender = function() {
clearInterval(renderTimer);
};
doRender(myColor.colors);
/*-----------------------------*/
/*------ Function Helpers -----*/
/*-----------------------------*/
function getOrigin(elm) {
var box = (elm.getBoundingClientRect) ? elm.getBoundingClientRect() : {
top: 0,
left: 0
},
doc = elm && elm.ownerDocument,
body = doc.body,
win = doc.defaultView || doc.parentWindow || window,
docElem = doc.documentElement || body.parentNode,
clientTop = docElem.clientTop || body.clientTop || 0, // border on html or body or both
clientLeft = docElem.clientLeft || body.clientLeft || 0;
return {
left: box.left + (win.pageXOffset || docElem.scrollLeft) - clientLeft,
top: box.top + (win.pageYOffset || docElem.scrollTop) - clientTop
};
}
function addEvent(obj, type, func) {
addEvent.cache = addEvent.cache || {
_get: function(obj, type, func, checkOnly) {
var cache = addEvent.cache[type] || [];
for (var n = cache.length; n--;) {
if (obj === cache[n].obj && '' + func === '' + cache[n].func) {
func = cache[n].func;
if (!checkOnly) {
cache[n] = cache[n].obj = cache[n].func = null;
cache.splice(n, 1);
}
return func;
}
}
},
_set: function(obj, type, func) {
var cache = addEvent.cache[type] = addEvent.cache[type] || [];
if (addEvent.cache._get(obj, type, func, true)) {
return true;
} else {
cache.push({
func: func,
obj: obj
});
}
}
};
if (!func.name && addEvent.cache._set(obj, type, func) || typeof func !== 'function') {
return;
}
if (obj.addEventListener) obj.addEventListener(type, func, false);
else obj.attachEvent('on' + type, func);
}
function removeEvent(obj, type, func) {
if (typeof func !== 'function') return;
if (!func.name) {
func = addEvent.cache._get(obj, type, func) || func;
}
if (obj.removeEventListener) obj.removeEventListener(type, func, false);
else obj.detachEvent('on' + type, func);
}
function hasClass(ele, cls) {
return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}
function getModeType(elem) {
var id = elem.id, // rgbR
len = id.length - 1, // 3
type = id.substr(0, len), // rgb
mode = id.charAt(len), // r
isLabAB = type === 'Lab' && (/(?:a|b)/.test(mode)); //is 'Lab && ()'a' || 'b')
if (elem.id === 'rgbA') mode = 'alpha';
return {
type: type,
mode: mode,
isLabAB: isLabAB
};
}
function rgba2cssString(r, g, b, a) {
if (a || a === 0) {
return "rgba(" + r + "," + g + "," + b + "," + a + ")";
}
return "rgb(" + r + "," + g + "," + b + ")";
}
/**
* Formats the given HSL values into a string that can be used in CSS
*/
function hsla2cssString(h, s, l, a) {
if (a || a === 0) {
return "hsla(" + h + "," + s + "%," + l + "%," + a + ")";
}
return "hsl(" + h + "," + s + "%," + l + "%)";
}
/**
* Formats the given HSV values into a string that can be used in CSS
*/
function hsva2cssString(h, s, v, a) {
var hslColor = myColor.convertColor({
h: h,
s: s,
v: v
}, 'HSV2HSL');
if (a || a === 0) {
return "hsla(" + hslColor.h + "," + hslColor.s + "%," + hslColor.l + "%," + a + ")";
}
return "hsl(" + hslColor.h + "," + hslColor.s + "%," + hslColor.l + "%)";
}
/**
* Formats the given Lab values into a string that can be used in CSS
*/
function Laba2cssString(L, a, b, alpha) {
var rgbColor = myColor.convertColor({
L: L,
a: a,
b: b
}, 'LAB2RGB');
if (alpha || alpha === 0) {
return "rgba(" + rgbColor.r + "," + rgbColor.g + "," + rgbColor.b + "," + alpha + ")";
}
return "rgb(" + rgbColor.r + "," + rgbColor.g + "," + rgbColor.b + ")";
}
function setGradient(el, direction, steps, multipleBG) {
var gradientString = "linear-gradient(to " + direction + ",";
stepSize = 100 / (steps.length - 1);
for (var i = 0; i < steps.length; i++) {
gradientString += (i > 0 ? "," : "") + steps[i] + (i * stepSize) + "%";
}
gradientString += ")";
if (multipleBG) {
gradientString += ', ' + multipleBG;
}
el.style.backgroundImage = gradientString;
}
#overallSlidersWrapper {
width: 500px;
}
.sliderContent {
height: 138px;
}
.colorSliderTabsLabel {
width: calc(100% /4);
display: inline-block;
text-align: center;
cursor: pointer;
}
#colorSliderTabUnderliner {
height: 3px;
width: calc(100% /4);
background-color: green;
transition: transform 0.3s cubic-bezier(0.45, 0.05, 0.55, 0.95);
}
#tabContentWrapper {
width: 680px;
align-items: flex-start;
position: relative;
}
#overallSlidersWrapper {} .sliderOuterWrapper {
margin-bottom: 10px;
}
.sliderLabel {} .sliderInnerWrapper {
height: 18px;
width: 100%;
cursor: pointer;
position: relative;
display: flex;
}
.slider {
height: 100%;
width: calc(100% - 62px);
/* Subtract TextField (44px) and Both Rounders for Slider (19px each)*/
position: relative;
border: 1px solid black;
border-right: none;
border-left: none;
}
.leftRoundness,
.rightRoundness {
width: 9px;
height: 100%;
border: 1px solid black;
}
.leftRoundness {
border-right: none;
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
}
.rightRoundness {
border-left: none;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
}
.sliderCursor {
width: 14px;
height: 14px;
border-radius: 50%;
position: relative;
border: 2px solid black;
}
#result {
width: 100px;
height: 100px;
}
<script src="https://cdn.rawgit.com/PitPik/colorPicker/master/colors.js"></script>
<div id="result"></div>
<div id="overallSlidersWrapper">
<div id="rgbSliderContent" class="sliderContent">
<div class="sliderOuterWrapper">
<div class="sliderLabel">red</div>
<div class="sliderInnerWrapper">
<div class="leftRoundness"></div>
<div id="rgbr" class="slider">
<div class="sliderCursor"></div>
</div>
<div class="rightRoundness"></div>
</div>
</div>
<div class="sliderOuterWrapper">
<div class="sliderLabel">green</div>
<div class="sliderInnerWrapper">
<div class="leftRoundness"></div>
<div id="rgbg" class="slider">
<div class="sliderCursor"></div>
</div>
<div class="rightRoundness"></div>
</div>
</div>
<div class="sliderOuterWrapper">
<div class="sliderLabel">blue</div>
<div class="sliderInnerWrapper">
<div class="leftRoundness"></div>
<div id="rgbb" class="slider">
<div class="sliderCursor"></div>
</div>
<div class="rightRoundness"></div>
</div>
</div>
</div>
<div id="hslSliderContent" class="sliderContent">
<div class="sliderOuterWrapper">
<div class="sliderLabel">hue</div>
<div class="sliderInnerWrapper">
<div class="leftRoundness"></div>
<div id="hslh" class="slider">
<div class="sliderCursor"></div>
</div>
<div class="rightRoundness"></div>
</div>
</div>
<div class="sliderOuterWrapper">
<div class="sliderLabel">saturation</div>
<div class="sliderInnerWrapper">
<div class="leftRoundness"></div>
<div id="hsls" class="slider">
<div class="sliderCursor"></div>
</div>
<div class="rightRoundness"></div>
</div>
</div>
<div class="sliderOuterWrapper">
<div class="sliderLabel">lightness</div>
<div class="sliderInnerWrapper">
<div class="leftRoundness"></div>
<div id="hsll" class="slider">
<div class="sliderCursor"></div>
</div>
<div class="rightRoundness"></div>
</div>
</div>
</div>
<div id="hsvSliderContent" class="sliderContent">
<div class="sliderOuterWrapper">
<div class="sliderLabel">hue</div>
<div class="sliderInnerWrapper">
<div class="leftRoundness"></div>
<div id="hsvh" class="slider">
<div class="sliderCursor"></div>
</div>
<div class="rightRoundness"></div>
</div>
</div>
<div class="sliderOuterWrapper">
<div class="sliderLabel">saturation</div>
<div class="sliderInnerWrapper">
<div class="leftRoundness"></div>
<div id="hsvs" class="slider">
<div class="sliderCursor"></div>
</div>
<div class="rightRoundness"></div>
</div>
</div>
<div class="sliderOuterWrapper">
<div class="sliderLabel">value</div>
<div class="sliderInnerWrapper">
<div class="leftRoundness"></div>
<div id="hsvv" class="slider">
<div class="sliderCursor"></div>
</div>
<div class="rightRoundness"></div>
</div>
</div>
</div>
<div id="LabSliderContent" class="sliderContent" style="width: 0px; overflow: hidden;">
<div class="sliderOuterWrapper">
<div class="sliderLabel">Lightness</div>
<div class="sliderInnerWrapper">
<div class="leftRoundness"></div>
<div id="LabL" class="slider">
<div class="sliderCursor"></div>
</div>
<div class="rightRoundness"></div>
</div>
</div>
<div class="sliderOuterWrapper">
<div class="sliderLabel">a (Green ↔ Red)</div>
<div class="sliderInnerWrapper">
<div class="leftRoundness"></div>
<div id="Laba" class="slider">
<div class="sliderCursor"></div>
</div>
<div class="rightRoundness"></div>
</div>
</div>
<div class="sliderOuterWrapper">
<div class="sliderLabel">b (Blue ↔ Yellow)</div>
<div class="sliderInnerWrapper">
<div class="leftRoundness"></div>
<div id="Labb" class="slider">
<div class="sliderCursor"></div>
</div>
<div class="rightRoundness"></div>
</div>
</div>
</div>
</div>