Jqueryの有無にかかわらずJavaScriptを使用して、開始色と終了色に基づいて色のグラデーションを作成する必要があります。これをプログラムで行うことは可能ですか?
終了色は、開始色の濃い色合いになるだけです。これは、順序付けられていないリスト用で、liアイテムの数を制御することはできません。開始色と終了色を選択し、16進数値をRGBに変換して、コードで操作できるようにするソリューションを探しています。開始RGB値は、アイテムの数に基づいて計算されたステップ値で増分されます。
リストに8つの項目がある場合、最終的な色を実現するには、8つのステップで個別の赤緑青の値を増やす必要があります。それを行うためのより良い方法はありますか?その場合、どこでサンプルコードを見つけることができますか?
この一般的な問題を解決するために、JSライブラリ RainbowVis-JS を作成しました。 setNumberRange
を使用してアイテムの数を設定し、setSpectrum
を使用して開始色と終了色を設定するだけです。次に、colourAt
を使用して16進カラーコードを取得します。
var numberOfItems = 8;
var Rainbow = new Rainbow();
Rainbow.setNumberRange(1, numberOfItems);
Rainbow.setSpectrum('red', 'black');
var s = '';
for (var i = 1; i <= numberOfItems; i++) {
var hexColour = Rainbow.colourAt(i);
s += '#' + hexColour + ', ';
}
document.write(s);
// gives:
// #ff0000, #db0000, #b60000, #920000, #6d0000, #490000, #240000, #000000,
ライブラリのソースコードをご覧ください。 :)
色の配列を生成する正しい関数!
function hex (c) {
var s = "0123456789abcdef";
var i = parseInt (c);
if (i == 0 || isNaN (c))
return "00";
i = Math.round (Math.min (Math.max (0, i), 255));
return s.charAt ((i - i % 16) / 16) + s.charAt (i % 16);
}
/* Convert an RGB triplet to a hex string */
function convertToHex (rgb) {
return hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
}
/* Remove '#' in color hex string */
function trim (s) { return (s.charAt(0) == '#') ? s.substring(1, 7) : s }
/* Convert a hex string to an RGB triplet */
function convertToRGB (hex) {
var color = [];
color[0] = parseInt ((trim(hex)).substring (0, 2), 16);
color[1] = parseInt ((trim(hex)).substring (2, 4), 16);
color[2] = parseInt ((trim(hex)).substring (4, 6), 16);
return color;
}
function generateColor(colorStart,colorEnd,colorCount){
// The beginning of your gradient
var start = convertToRGB (colorStart);
// The end of your gradient
var end = convertToRGB (colorEnd);
// The number of colors to compute
var len = colorCount;
//Alpha blending amount
var alpha = 0.0;
var saida = [];
for (i = 0; i < len; i++) {
var c = [];
alpha += (1.0/len);
c[0] = start[0] * alpha + (1 - alpha) * end[0];
c[1] = start[1] * alpha + (1 - alpha) * end[1];
c[2] = start[2] * alpha + (1 - alpha) * end[2];
saida.Push(convertToHex (c));
}
return saida;
}
// Exemplo de como usar
var tmp = generateColor('#000000','#ff0ff0',10);
for (cor in tmp) {
$('#result_show').append("<div style='padding:8px;color:#FFF;background-color:#"+tmp[cor]+"'>COLOR "+cor+"° - #"+tmp[cor]+"</div>")
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result_show"></div>
そのとおり。
これはJavaで行いますが、JavaScriptでも簡単に実行できるはずです。
まず、色をRGBコンポーネントに分割する必要があります。
次に、コンポーネントの開始と終了の差を計算します。
最後に、パーセンテージの差を計算し、各コンポーネントの開始色を掛けて、開始色に追加します。
RGB値を取得できると仮定すると、次のようになります。
var diffRed = endColor.red - startColor.red;
var diffGreen = endColor.green - startColor.green;
var diffBlue = endColor.blue - startColor.blue;
diffRed = (diffRed * percentFade) + startColor.red;
diffGreen = (diffGreen * percentFade) + startColor.green;
diffBlue = (diffBlue * percentFade) + startColor.blue;
「percentFade」は浮動小数点で、「endColor」にフェードする距離を示します。 1は完全なフェードになります(したがって、終了色が作成されます)。 0はフェードなし(開始色)です。
私は@desauの回答に基づいてこの関数を使用します:
getGradientColor = function(start_color, end_color, percent) {
// strip the leading # if it's there
start_color = start_color.replace(/^\s*#|\s*$/g, '');
end_color = end_color.replace(/^\s*#|\s*$/g, '');
// convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
if(start_color.length == 3){
start_color = start_color.replace(/(.)/g, '$1$1');
}
if(end_color.length == 3){
end_color = end_color.replace(/(.)/g, '$1$1');
}
// get colors
var start_red = parseInt(start_color.substr(0, 2), 16),
start_green = parseInt(start_color.substr(2, 2), 16),
start_blue = parseInt(start_color.substr(4, 2), 16);
var end_red = parseInt(end_color.substr(0, 2), 16),
end_green = parseInt(end_color.substr(2, 2), 16),
end_blue = parseInt(end_color.substr(4, 2), 16);
// calculate new color
var diff_red = end_red - start_red;
var diff_green = end_green - start_green;
var diff_blue = end_blue - start_blue;
diff_red = ( (diff_red * percent) + start_red ).toString(16).split('.')[0];
diff_green = ( (diff_green * percent) + start_green ).toString(16).split('.')[0];
diff_blue = ( (diff_blue * percent) + start_blue ).toString(16).split('.')[0];
// ensure 2 digits by color
if( diff_red.length == 1 ) diff_red = '0' + diff_red
if( diff_green.length == 1 ) diff_green = '0' + diff_green
if( diff_blue.length == 1 ) diff_blue = '0' + diff_blue
return '#' + diff_red + diff_green + diff_blue;
};
例:
getGradientColor('#FF0000', '#00FF00', 0.4);
=> "#996600"
desauの答え は素晴らしい。これはjavascriptにあります:
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
function map(value, fromSource, toSource, fromTarget, toTarget) {
return (value - fromSource) / (toSource - fromSource) * (toTarget - fromTarget) + fromTarget;
}
function getColour(startColour, endColour, min, max, value) {
var startRGB = hexToRgb(startColour);
var endRGB = hexToRgb(endColour);
var percentFade = map(value, min, max, 0, 1);
var diffRed = endRGB.r - startRGB.r;
var diffGreen = endRGB.g - startRGB.g;
var diffBlue = endRGB.b - startRGB.b;
diffRed = (diffRed * percentFade) + startRGB.r;
diffGreen = (diffGreen * percentFade) + startRGB.g;
diffBlue = (diffBlue * percentFade) + startRGB.b;
var result = "rgb(" + Math.round(diffRed) + ", " + Math.round(diffGreen) + ", " + Math.round(diffBlue) + ")";
return result;
}
function changeBackgroundColour() {
var count = 0;
window.setInterval(function() {
count = (count + 1) % 200;
var newColour = getColour("#00FF00", "#FF0000", 0, 200, count);
document.body.style.backgroundColor = newColour;
}, 20);
}
changeBackgroundColour();
xolor library には勾配関数があります。これにより、開始色から終了色までのグラデーションで8色の配列が作成されます。
var gradientColors = []
var startColor = "rgb(100,200,50)", endColor = "green"
var start = xolor(startColor)
for(var n=0; n<8; n++) {
gradientColors.Push(start.gradient(endColor, n/8))
}
Githubの詳細を参照してください: https://github.com/fresheneesz/xolor
それほど強力ではありませんが、ほとんどの場合は機能し、次のコードにはjQuery以外のライブラリを含める必要はありません。
HTML:
<div id="colors"></div>
JavaScript:
function Rainbow(value, s, l, max, min, start, end) {
value = ((value - min) * (start - end) / max)+end;
return 'hsl(' + value + ','+s+'%,'+l+'%)';
}
function createRainbowDiv(start,end){
var gradient = $("<div>").css({display:"flex", "flex-direction":"row",height:"100%"});
for (var i = start; ((i <= end) && (i >= start)) || ((i >= end) && (i <= start));
i += (end-start) / Math.abs(end-start)){
gradient.append($("<div>").css({float:"left","background-color":Rainbow(i, 100,50, Math.max(start,end), Math.min(start,end), start,end),flex:1}));
}
return gradient;
}
$("#colors").append(createRainbowDiv(0,150));
$("#colors").css("width","100%").css("height","10px");
これにより、Rainbowを含むdivが作成されます。 http://jsfiddle.net/rootandy/54rV7/ を参照してください
動的な要素の未知のセットに対して十分な大きさの色オプションの配列を作成する必要がありましたが、各要素が開始色と終了色の間を進むようにする必要がありました。この種類は、「パーセントフェード」アプローチに従いますが、そのロジックを追うのが困難でした。これは、2つのRGB色値の入力を使用してページ上の要素数を計算する方法です。
概念を示す codepenへのリンク があります。
以下は、問題のコードスニペットです。
<style>
#test {
width:200px;
height:100px;
border:solid 1px #000;
}
.test {
width:49%;
height:100px;
border:solid 1px #000;
display: inline-block;
}
</style>
</head>
<body>
<div id="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<div class="test"></div>
<script>
var GColor = function(r,g,b) {
r = (typeof r === 'undefined')?0:r;
g = (typeof g === 'undefined')?0:g;
b = (typeof b === 'undefined')?0:b;
return {r:r, g:g, b:b};
};
// increases each channel by the difference of the two
// divided by 255 (the number of colors stored in the range array)
// but only stores a whole number
// This should respect any rgb combinations
// for start and end colors
var createColorRange = function(c1) {
var colorList = [], tmpColor, rr = 0, gg = 0, bb = 0;
for (var i=0; i<255; i++) {
tmpColor = new GColor();
if (rExp >= 0) {
tmpColor.r = Math.floor(c1.r - rr);
rr += rAdditive;
} else {
tmpColor.r = Math.floor(c1.r + rr);
rr += rAdditive;
}
if (gExp >= 0) {
tmpColor.g = Math.floor(c1.g - gg);
gg += gAdditive;
} else {
tmpColor.g = Math.floor(c1.g + gg);
gg += gAdditive;
}
if (bExp >= 0) {
tmpColor.b = Math.floor(c1.b - bb);
bb += bAdditive;
} else {
tmpColor.b = Math.floor(c1.b + bb);
bb += bAdditive;
}
console.log(tmpColor);
colorList.Push(tmpColor);
}
return colorList;
};
/* ==================
Testing Code Below
================== */
var firstColor = new GColor(255, 24, 0);
var secondColor = new GColor(255, 182, 0);
// Determine the difference
var rExp = firstColor.r - secondColor.r;
// Divide that difference by length of the array
// you would like to create (255 in this case)
var rAdditive = Math.abs(rExp)/255;
var gExp = firstColor.g - secondColor.g;
var gAdditive = Math.abs(gExp)/255;
var bExp = firstColor.b - secondColor.b;
var bAdditive = Math.abs(bExp)/255;
var range = createColorRange(firstColor, secondColor);
console.log(range);
var pointer = 0;
// This gently cycles through
// all the colors on a single element
function rotateColors() {
var currentColor = range[pointer];
document.getElementById("test").style.backgroundColor = "rgb("+currentColor.r+","+currentColor.g+","+currentColor.b+")";
pointer++;
if (pointer < range.length) window.setTimeout(rotateColors, 5);
}
rotateColors();
// say I have 5 elements
// so I need 5 colors
// I already have my first and last colors
// but I need to locate the colors between
// my start color and my end color
// inside of this range
// so I divide the range's length by the
// number of colors I need
// and I store the index values of the middle values
// those index numbers will then act as my keys to retrieve those values
// and apply them to my element
var myColors = {};
var objects = document.querySelectorAll('.test');
myColors.num = objects.length;
var determineColors = function(numOfColors, colorArray) {
var colors = numOfColors;
var cRange = colorArray;
var distance = Math.floor(cRange.length/colors);
var object = document.querySelectorAll('.test');
var j = 0;
for (var i = 0; i < 255; i += distance) {
if ( (i === (distance*colors)) ) {
object[j].style.backgroundColor = "rgb(" + range[255].r + ", " + range[255].g + ", " + range[255].b + ")";
j = 0;
// console.log(range[i]);
} else {
// Apply to color to the element
object[j].style.backgroundColor = "rgb(" + range[i].r + ", " + range[i].g + ", " + range[i].b + ")";
// Have each element bleed into the next with a gradient
// object[j].style.background = "linear-gradient( 90deg, rgb(" + range[i].r + ", " + range[i].g + ", " + range[i].b + "), rgb(" + range[i+distance].r + ", " + range[i+distance].g + ", " + range[i+distance].b + "))";
j++;
}
}
};
setTimeout( determineColors(myColors.num, range), 2000);
</script>
</body>
これは、要素の背景をグラデーションに設定する既製の関数です
Element.prototype.setGradient = function( from, to, vertical ){
this.style.background = 'linear-gradient(to '+(vertical ? 'top' : 'left')+', '+from+', '+to+' 100%)';
}
そして使用法:
document.querySelector('.mydiv').setGradient('red','green');
これはChromeでの動作がテストされました。他のブラウザ用に更新してみます
最も基本的な水平方向は次のとおりです。
Element.prototype.setGradient = function( fromColor, toColor ){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var b = this.getBoundingClientRect();
var grd = ctx.createLinearGradient(0, 0, b.width, 0);
canvas.width = b.width;
canvas.height = b.height;
grd.addColorStop(0, fromColor);
grd.addColorStop(1, toColor);
ctx.fillStyle = grd;
ctx.fillRect(0, 0, b.width, b.height);
this.style.backgroundImage = 'url('+canvas.toDataURL()+')';
}
そして使用法:
document.querySelector('.mydiv').setGradient('red','green');
A Fiddle: https://jsfiddle.net/jch39bey/
-
垂直を設定する単純なフラグ
Element.prototype.setGradient = function( fromColor, toColor, vertical ){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var b = this.getBoundingClientRect();
var grd = ctx.createLinearGradient(0, 0, vertical ? 0 : b.width, vertical ? b.height : 0);
canvas.width = b.width;
canvas.height = b.height;
grd.addColorStop(0, fromColor);
grd.addColorStop(1, toColor);
ctx.fillStyle = grd;
ctx.fillRect(0, 0, b.width, b.height);
this.style.backgroundImage = 'url('+canvas.toDataURL()+')';
}
そして使用法:
document.querySelector('.mydiv').setGradient('red','green',true);
要素のリストを取得できます。私はjQueryに慣れていませんが、prototypejsにはElement.childElements()があり、これが配列を返します。配列の長さがわかれば、各ステップでピクセルコンポーネントをどれだけ変更するかを決定できます。次のコードのいくつかは、提示している形式ではテストしていませんが、うまくいけばアイデアが得られるはずです。
function hex (c) {
var s = "0123456789abcdef";
var i = parseInt (c);
if (i == 0 || isNaN (c))
return "00";
i = Math.round (Math.min (Math.max (0, i), 255));
return s.charAt ((i - i % 16) / 16) + s.charAt (i % 16);
}
/* Convert an RGB triplet to a hex string */
function convertToHex (rgb) {
return hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
}
/* Remove '#' in color hex string */
function trim (s) { return (s.charAt(0) == '#') ? s.substring(1, 7) : s }
/* Convert a hex string to an RGB triplet */
function convertToRGB (hex) {
var color[];
color[0] = parseInt ((trim(hex)).substring (0, 2), 16);
color[1] = parseInt ((trim(hex)).substring (2, 4), 16);
color[2] = parseInt ((trim(hex)).substring (4, 6), 16);
}
/* The start of your code. */
var start = convertToRGB ('#000000'); /* The beginning of your gradient */
var end = convertToRGB ('#ffffff'); /* The end of your gradient */
var arr = $('.gradientList').childElements();
var len = arr.length(); /* The number of colors to compute */
var alpha = 0.5; /* Alpha blending amount */
for (i = 0; i < len; i++) {
var c = [];
c[0] = start[0] * alpha + (1 - alpha) * end[0];
c[1] = start[1] * alpha + (1 - alpha) * end[1];
c[2] = start[2] * alpha + (1 - alpha) * end[2];
/* Set the background color of this element */
arr[i].setStyle ({ 'background-color': convertToHex (c) });
}