Last active
February 28, 2024 19:53
-
-
Save lovasoa/8141243 to your computer and use it in GitHub Desktop.
JS color picker:
HTML5 & javascript color picker that uses HTML5 canvas. User can choose hue and value, saturation is set to 1.
It has color history management.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf8" /> | |
<title>Canvascolor</title> | |
<style> | |
body { | |
background-image:url(http://github.com/favicon.ico); /*Just for fun*/ | |
} | |
main { | |
margin-top:50px; | |
margin-left:25%; | |
margin-right:25%; | |
padding:6%; | |
width:auto; | |
height:1000px; | |
background-color:#ccabfd; | |
text-align:justify; | |
box-shadow: 0 0 12px black; | |
} | |
.fixed { | |
position:fixed; | |
top:0; | |
left:0; | |
width:100%; | |
background-color:black; | |
color:white; | |
box-shadow:0 0 12px grey; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="fixed" > | |
<span>This div is positioned in fixed coordinates. | |
The color picker always appears at the right place. | |
The color picker is added to a normal input of type <code>text</code>: | |
</span> | |
<input type="text" class="canvascolor" value="red" /> | |
</div> | |
<main> | |
<p> | |
This color picker is just an <code><input type="color"></code> | |
If your browser supports a native color picker, it will be used. | |
Else, canvascolor will be used as a fallback. | |
</p> | |
<input type="color" value="#fada55" /> | |
</main> | |
<script src="canvascolor.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* CANVASCOLOR color picker | |
********************************************************* | |
* @licstart The following is the entire license notice for the | |
* JavaScript code in this page. | |
* | |
* Copyright (C) 2013-2014 Ophir LOJKINE | |
* | |
* | |
* The JavaScript code in this page is free software: you can | |
* redistribute it and/or modify it under the terms of the GNU | |
* General Public License (GNU GPL) as published by the Free Software | |
* Foundation, either version 3 of the License, or (at your option) | |
* any later version. The code is distributed WITHOUT ANY WARRANTY; | |
* without even the implied warranty of MERCHANTABILITY or FITNESS | |
* FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. | |
* | |
* As additional permission under GNU GPL version 3 section 7, you | |
* may distribute non-source (e.g., minimized or compacted) forms of | |
* that code without the copy of the GNU GPL normally required by | |
* section 4, provided you include this license notice and a URL | |
* through which recipients can access the Corresponding Source. | |
* | |
* @licend | |
*/ | |
/*jshint bitwise:false*/ | |
// ==ClosureCompiler== | |
// @output_file_name canvascolor.js | |
// @compilation_level ADVANCED_OPTIMIZATIONS | |
// @js_externs var canvascolor; | |
// @language ecmascript5_strict | |
// @use_types_for_optimization true | |
// ==/ClosureCompiler== | |
var canvascolor = (function() {//Code Isolation | |
"use strict"; | |
(function addCSS () { | |
var styleTag = document.createElement("style"); | |
styleTag.innerHTML = [".canvascolor-container{", | |
"background-color:black;", | |
"border-radius:5px;", | |
"overflow:hidden;", | |
"width:179px;", | |
"padding:2px;", | |
"display:none;", | |
"}", | |
".canvascolor-container canvas{", | |
"cursor:crosshair;", | |
"}", | |
".canvascolor-history{", | |
"overflow:auto;", | |
"}", | |
".canvascolor-history > div{", | |
"margin:2px;", | |
"display:inline-block;", | |
"}"].join(""); | |
document.head.appendChild(styleTag); | |
})(); | |
function hsv2rgb (h,s,v) { | |
if( s === 0 ) return [v,v,v]; // achromatic (grey) | |
h /= (Math.PI/6); // sector 0 to 5 | |
var i = h|0, | |
f = h - i, // factorial part of h | |
p = v * ( 1 - s ), | |
q = v * ( 1 - s * f ), | |
t = v * ( 1 - s * ( 1 - f ) ); | |
switch( i%6 ) { | |
case 0: return [v,t,p]; | |
case 1: return [q,v,p]; | |
case 2: return [p,v,t]; | |
case 3: return [p,q,v]; | |
case 4: return [t,p,v]; | |
case 5:return [v,p,q]; | |
} | |
} | |
function isFixedPosition(elem) { | |
do { | |
if (getComputedStyle(elem).position === "fixed") return true; | |
} while ( (elem = elem.parentElement) !== null ); | |
return false; | |
} | |
var containerTemplate; | |
(function createContainer(){ | |
containerTemplate = document.createElement("div"); | |
containerTemplate.className = "canvascolor-container"; | |
var canvas = document.createElement("canvas"); | |
var historyDiv = document.createElement("div"); | |
historyDiv.className = "canvascolor-history"; | |
containerTemplate.appendChild(canvas); | |
containerTemplate.appendChild(historyDiv); | |
})(); | |
function canvascolor(elem) { | |
var curcolor = elem.value || "#000"; | |
var w=200, h=w/2; | |
var container = containerTemplate.cloneNode(true); | |
container.style.width = w+"px"; | |
container.style.position = isFixedPosition(elem) ? "fixed" : "absolute"; | |
var canvas = container.getElementsByTagName("canvas")[0]; | |
var ctx = canvas.getContext("2d"); | |
canvas.width = w; canvas.height=h; | |
var prevcolorsDiv = container.getElementsByClassName("canvascolor-history")[0]; | |
prevcolorsDiv.style.width=w+"px"; | |
prevcolorsDiv.style.maxHeight=h+"px"; | |
var previewdiv = createColorDiv(curcolor); | |
previewdiv.style.border = "1px solid white"; | |
previewdiv.style.borderRadius = "5px"; | |
document.body.appendChild(container); | |
function displayContainer(){ | |
var rect = elem.getBoundingClientRect(); | |
var conttop=(rect.top+rect.height+3), | |
contleft=rect.left; | |
if (container.style.position !== "fixed") { | |
conttop += window.scrollY; | |
contleft += window.scrollX; | |
} | |
container.style.top = conttop+"px"; | |
container.style.left = contleft+"px"; | |
container.style.display = "block"; | |
} | |
function hideContainer(){ | |
container.style.display = "none"; | |
} | |
elem.addEventListener("mouseover", displayContainer, true); | |
container.addEventListener("mouseleave", hideContainer, false); | |
elem.addEventListener("keyup", function(){ | |
changeColor(elem.value, true); | |
}, true); | |
changeColor(elem.value, true); | |
var idata = ctx.createImageData(w,h); | |
function rgb2hex (rgb) { | |
function num2hex (c) {return (c*15/255|0).toString(16);} | |
return "#"+num2hex(rgb[0])+num2hex(rgb[1])+num2hex(rgb[2]); | |
} | |
function colorAt(coords) { | |
var x=coords[0], y=coords[1]; | |
return hsv2rgb(x/w*Math.PI, 1, (1-y/h)*255); | |
} | |
function render() { | |
for (var x=0; x<w; x++) { | |
for (var y=0;y<h; y++) { | |
var i = 4*(x+y*w); | |
var rgb = colorAt([x,y]); | |
idata.data[i] = rgb[0];//Red | |
idata.data[i+1] = rgb[1];//Green | |
idata.data[i+2] = rgb[2];//Blue | |
idata.data[i+3] = 255; | |
} | |
} | |
ctx.putImageData(idata,0,0); | |
} | |
render(); | |
/** Changes the current color (the value of the input field) and updates other variables accordingly | |
* @param {string} color The new color. Must be a valid CSS color string if ensureValid is not specified | |
* @param {boolean} [ensureValid=false] Do not make the change if color is not a valid CSS color | |
*/ | |
function changeColor(color, ensureValid) { | |
elem.style.backgroundColor = color; | |
if (ensureValid && elem.style.backgroundColor.length === 0) { | |
elem.style.backgroundColor = curcolor; | |
return; | |
} | |
previewdiv.style.backgroundColor = color; | |
curcolor = color; | |
elem.value = color; | |
elem.focus(); | |
} | |
function createColorDiv (color) { | |
var div = document.createElement("div"); | |
div.style.width = (w/3-10)+"px"; | |
div.style.height = (h/3-8)+"px"; | |
div.style.backgroundColor = color; | |
div.addEventListener("click", function(){ | |
changeColor(color); | |
}, true); | |
if (prevcolorsDiv.childElementCount <= 1) prevcolorsDiv.appendChild(div); | |
else prevcolorsDiv.insertBefore(div,prevcolorsDiv.children[1]); | |
return div; | |
} | |
function canvasPos(evt) { | |
var canvasrect = canvas.getBoundingClientRect(); | |
return [evt.clientX - canvasrect.left, evt.clientY - canvasrect.top]; | |
} | |
canvas.addEventListener("mousemove", function(evt){ | |
var coords = canvasPos(evt); | |
previewdiv.style.backgroundColor = rgb2hex(colorAt(coords)); | |
}, true); | |
canvas.addEventListener("click", function(evt){ | |
var coords = canvasPos(evt); | |
var color = rgb2hex(colorAt(coords)); | |
createColorDiv(color); | |
changeColor(color); | |
}, true); | |
canvas.addEventListener("mouseleave", function(){ | |
previewdiv.style.backgroundColor = curcolor; | |
}, true); | |
} | |
//Put a color picker on every input[type=color] if the browser doesn't support this input type | |
//and on every input with the class canvascolor | |
var pickers = document.querySelectorAll("input.canvascolor, input[type=color]"); | |
for (var i=0;i <pickers.length; i++) { | |
var input = pickers.item(i); | |
//If the browser supports native color picker and the user didn't | |
//explicitly added canvascolor to the element, we do not add a custom color picker | |
if (input.type !== "color" || | |
input.className.split(" ").indexOf("canvascolor") !== -1) { | |
canvascolor(input); | |
} | |
} | |
return canvascolor; | |
}()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var canvascolor=(function(){function x(a,c){a/=Math.PI/6;var k=a|0,d=a-k,f=0*c,l=c*(1-1*d),d=c*(1-1*(1-d));switch(k%6){case 0:return[c,d,f];case 1:return[l,c,f];case 2:return[f,c,d];case 3:return[f,l,c];case 4:return[d,f,c];case 5:return[c,f,l]}}function y(a){do if("fixed"===getComputedStyle(a).position)return!0;while(null!==(a=a.parentElement));return!1}function v(a){function c(b){return"#"+(15*b[0]/255|0).toString(16)+(15*b[1]/255|0).toString(16)+(15*b[2]/255|0).toString(16)}function k(b){return x(b[0]/ g*Math.PI,255*(1-b[1]/m))}function d(b,z){a.style.backgroundColor=b;z&&0===a.style.backgroundColor.length?a.style.backgroundColor=t:(t=q.style.backgroundColor=b,a.value=b,a.focus())}function f(b){var a=document.createElement("div");a.style.width=g/3-10+"px";a.style.height=m/3-8+"px";a.style.backgroundColor=b;a.addEventListener("click",function(){d(b)},!0);1>=n.childElementCount?n.appendChild(a):n.insertBefore(a,n.children[1]);return a}function l(b){var a=h.getBoundingClientRect();return[b.clientX- a.left,b.clientY-a.top]}var t=a.value||"#000",g=200,m=g/2,e=r.cloneNode(!0);e.style.width=g+"px";e.style.position=y(a)?"fixed":"absolute";var h=e.getElementsByTagName("canvas")[0],p=h.getContext("2d");h.width=g;h.height=m;var n=e.getElementsByClassName("canvascolor-history")[0];n.style.width=g+"px";n.style.maxHeight=m+"px";var q=f(t);q.style.border="1px solid white";q.style.a="5px";document.body.appendChild(e);a.addEventListener("mouseover",function(){var b=a.getBoundingClientRect(),c=b.top+b.height+ 3,b=b.left;"fixed"!==e.style.position&&(c+=window.scrollY,b+=window.scrollX);e.style.top=c+"px";e.style.left=b+"px";e.style.display="block"},!0);e.addEventListener("mouseleave",function(){e.style.display="none"},!1);a.addEventListener("keyup",function(){d(a.value,!0)},!0);d(a.value,!0);var s=p.createImageData(g,m);(function(){for(var b=0;b<g;b++)for(var a=0;a<m;a++){var c=4*(b+a*g),d=k([b,a]);s.data[c]=d[0];s.data[c+1]=d[1];s.data[c+2]=d[2];s.data[c+3]=255}p.putImageData(s,0,0)})();h.addEventListener("mousemove", function(a){a=l(a);q.style.backgroundColor=c(k(a))},!0);h.addEventListener("click",function(a){a=l(a);a=c(k(a));f(a);d(a)},!0);h.addEventListener("mouseleave",function(){q.style.backgroundColor=t},!0)}(function(){var a=document.createElement("style");a.innerHTML=".canvascolor-container{background-color:black;border-radius:5px;overflow:hidden;width:179px;padding:2px;display:none;}.canvascolor-container canvas{cursor:crosshair;}.canvascolor-history{overflow:auto;}.canvascolor-history > div{margin:2px;display:inline-block;}"; document.head.appendChild(a)})();var r;(function(){r=document.createElement("div");r.className="canvascolor-container";var a=document.createElement("canvas"),c=document.createElement("div");c.className="canvascolor-history";r.appendChild(a);r.appendChild(c)})();for(var w=document.querySelectorAll("input.canvascolor, input[type=color]"),p=0;p<w.length;p++){var u=w.item(p);"color"===u.type&&-1===u.className.split(" ").indexOf("canvascolor")||v(u)}return v})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment