функция градации цветов (количество n, цвет в формате HEX),при задании начального и конечного цвета

126
20 декабря 2020, 20:30

нужна функция, или наводки для реализации ее. На входе: начальный цвет(HEX), конечный цвет(HEX), количество разбиений. На выходе: массив цветов HEX[начальный цвет[n1], цвет[n2], цвет[n3], ..., конечный цвет[n]]. Нужна градация между начальным и конечным цветом, есть какие-нибудь идеи?

Answer 1

Предлагаю Вам воспользоваться библиотекой d3 в частности модулем d3-interpolate, который много чего умеет интерполировать, в том числе и цвета, причем не обязательно в hex, подойдет любой валидный css синтаксис цвета, в том числе и именованные цвета:

let colorsCount = 10; 
 
// создаем интерполятор, он принимает значения от `0` до `1` 
let interpolateColor = d3.interpolateRgb('#bad', 'wheat');  
 
// получаем  цвета 
let colors = Array(colorsCount) 
  .fill(0) 
  .map((d,n) => interpolateColor(n/(colorsCount - 1))); 
 
d3.select('body') 
  .selectAll('div') 
  .data(colors) 
  .enter() 
  .append('div') 
  .style('background-color', color => color) 
  .html(color => color)
<script src="https://d3js.org/d3-color.v1.min.js"></script> 
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script> 
<script src="https://d3js.org/d3-selection.v1.min.js"></script>

PS: модуль d3-selection для работы алгоритма не нужен, он в сниппете для dom-манипуляций

UPD: по просьбам трудящихся соорудил собственную функцию интерполяции rgb(простая линейная интерполяция 3х компонентов по отдельности) и привожу неправильный пример интерполяции значения цвета целиком, как числа:

let lerp = (time, left, right) => left + (right - left)*time; 
 
let lerpRgb = (a, b) => time => [ 
    lerp(time, a[0], b[0]), 
    lerp(time, a[1], b[1]), 
    lerp(time, a[2], b[2]), 
]; 
 
 
let interpolate = lerpRgb([255,0,0], [0,0,255]); 
let ctx = draw.getContext("2d"); 
for(var i=0;i<draw.width;i++){ 
 
  let c = interpolate(i/draw.width); 
  ctx.strokeStyle = `rgb(${c[0]},${c[1]},${c[2]})`; 
  ctx.beginPath(); 
  ctx.moveTo(i, 0); 
  ctx.lineTo(i, 40); 
  ctx.stroke(); 
  c = Math.floor(lerp(i/draw.width, 0xff0000, 0x0000ff)); 
  ctx.strokeStyle = '#' + c.toString(16).padStart(6, '0'); 
  ctx.beginPath(); 
  ctx.moveTo(i, 50); 
  ctx.lineTo(i, 90); 
  ctx.stroke(); 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> 
<canvas id="draw" width="500"></canvas>

READ ALSO
Двойной вызов функции Vue.js

Двойной вызов функции Vue.js

Подскажите, почему при клике на кнопку, функция вызывается два раза? Как сделать, что бы она вызывалась один раз?

112
Не работает Spinner | jQuery UI

Не работает Spinner | jQuery UI

Есть интернет магазин в корзине заказов отображены все выбранные к покупке товары

122
Написать фильтр для checkbox во Vue.js

Написать фильтр для checkbox во Vue.js

Нужно выводить данные по определенным требованиям - по полу

93
Конфликт двух компонентов Swiper на одной странице

Конфликт двух компонентов Swiper на одной странице

Использую этот слайдерДобавляю два компонента на страницу

157