Смешивать цвета между значениями - PullRequest
0 голосов
/ 19 декабря 2018

Я пытаюсь создать как обратный отсчет времени, используя дугу холста, рисунок в порядке, но дуга будет иметь цвет обводки, который я хочу смешать.

Способ рисования дугис помощью числа от 0 до 100, 100 в основном полная дуга, 0 это ничто.Когда значение больше 66 и меньше (или равно) 100, это будет смесь между зеленым и оранжевым, 100 - зеленый, а 66 - оранжевый.65 и ниже будет смесь между оранжевым и красным, где общий красный равен 0.

Я не знаю, с чего начать, нет идей о том, что искать, чтобы исследовать, как получить значения.

Может ли кто-нибудь указать мне правильное направление?

Вот мой код до сих пор х)

static color (value)
{
    const StartColor  = 0x66BB6A; // Green
    const MiddleColor = 0xFFA726; // Orange
    const EndColor    = 0xEF5350; // Red  
}

РЕДАКТИРОВАТЬ : Это результат яискал.Теперь он работает так, как я хочу.Приветствия.

https://youtu.be/IeR_zMzSaAU

Ответы [ 4 ]

0 голосов
/ 19 декабря 2018

Конечно, использовать библиотеку, выделенную для этого, будет проще.Но на всякий случай, если кому-то интересно заняться математикой, вы можете разбить шестнадцатеричные числа на компоненты, а затем интерполировать каждый компонент отдельно, чтобы получить цвет в определенном месте:

// break hex integer into components:
const getComonents = (color) => Array.from({length: 3}, (_, i) => Math.floor(color / 16 ** (2 * i) % 16 ** 2))

// interpolate arrays by component
const interpolate = (arr1, arr2, percent) => arr1.map((v, index) => Math.floor(v + (arr2[index] - v) * (percent / 100)))

function colors(value) {
  const StartColor  = 0x11FF11; // Green
  const MiddleColor = 0xFFA726; // Orange
  const EndColor    = 0xEF5350; // Red
  
  let [start, end, v] = value < 50 
      ? [StartColor, MiddleColor, value * 2 ] 
      : [MiddleColor, EndColor, (value - 50) * 2]

  let interpoled = interpolate(getComonents(start), getComonents(end), v)
  
  return interpoled.reduce((n, component, index) => n + component * (16 ** (index * 2)), 0)
}

const canvas = document.getElementById('the_canvas')
const ctx = canvas.getContext('2d')

for (let i = 0; i<100; i++){
  ctx.beginPath();
  
  // padStart is needed to make sure a value of `ff` becomes `0000ff`
  ctx.fillStyle = "#" + colors(i).toString(16).padStart(6, '0')
  ctx.rect(i*5, 0, i*5+5, 300);
  ctx.fill()
}
<canvas id="the_canvas" width="500" height="300"></canvas>
0 голосов
/ 19 декабря 2018

Я предположил, что вы хотите

  • создать цветовую шкалу на основе трех известных цветов - '66BB6A', 'FFA726', 'EF5350'
  • введите число из домена (0 - 100)и получите новый цвет, рассчитанный по шкале.

Chroma.js - это симпатичная маленькая библиотека js, которая может делать цветовые шкалы и преобразования.

const colorScale = chroma.scale(['66BB6A', 'FFA726', 'EF5350']).domain([0,100]);

console.log(colorScale(20).toString())

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = colorScale(20);
ctx.beginPath();
ctx.arc(100, 75, 50, 0, 2 * Math.PI);
ctx.fill();
<script src="https://cdnjs.cloudflare.com/ajax/libs/chroma-js/2.0.2/chroma.min.js"></script>
<canvas id="myCanvas"></canvas>
0 голосов
/ 19 декабря 2018

Вот быстрая скрипка Я сделал.

var c = document.getElementById("foo");
var i = 0;
var timer = setInterval(function() {

    var ctx = c.getContext("2d");
    ctx.beginPath();
    ctx.arc(75, 75, 50, 0, (i / 100) * Math.PI);
    ctx.strokeStyle = 'RGB('+((100-i)*2)+', '+i+', 0)';
    ctx.stroke();

    if((i / 100) == 2) {
        clearInterval(timer);
        console.log('FULL');
    }
    i++;
}, 100);
0 голосов
/ 19 декабря 2018

Примечание: Этот ответ является поздним и большим по сравнению с оригинальным.После первой попытки, когда я неправильно понял намерения ОП, ОП добавил ссылку с примером, с тех пор у меня было намерение предложить решение, так как я не был удовлетворен текущими ответами, и упражнение было забавным.


Разбивка ответа состоит из двух основных частей:

  1. Смешивание цветов (уже есть ответы, которые занимаются этим, с использованием библиотеки или создания метода для интерполяции / смешивания).шестнадцатеричное значение цвета)
  2. Нарисуйте дугу и используйте смешанный цвет

/*
 * blending colors 
 * (borrowed and modified from @mark-meyer answer)
 */

// break hex integer into components:
const getComponents = (color) => Array.from({length: 3}, (_, i) => Math.floor(color / 16 ** (2 * i) % 16 ** 2))

// interpolate arrays by component
const interpolate = (arr1, arr2, percent) => arr1.map((v, index) => Math.floor(v + (arr2[index] - v) * (percent / 100)))

const colorBlend = value => {
  const StartColor  = 0x11FF11; // Green
  const MiddleColor = 0xFFA726; // Orange
  const EndColor    = 0xEF5350; // Red
  
  let [start, end, v] = value < 50 
      ? [StartColor, MiddleColor, value * 2 ] 
      : [MiddleColor, EndColor, (value - 50) * 2]

  let interpoled = interpolate(getComponents(start), getComponents(end), v)
  
  const color = interpoled
  .reduce((n, component, index) => n + component * (16 ** (index * 2)), 0)
  .toString(16).padStart(6, '0')
  return `#${color}`
}

/*
 * draw an arc
 */
const canvas = document.getElementById('canvas1')
const ctx = canvas.getContext('2d')
const size = 30
let p = 0

const grad = ctx.createLinearGradient(size, size, size * 2, size * 2)
grad.addColorStop(0, "#66BB6A")
grad.addColorStop(0.5, "#FFA726")
grad.addColorStop(1, "#EF5350")

ctx.lineWidth = 6

const draw = () => {
  p += 0.01
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  ctx.strokeStyle = colorBlend(p * 50)
  ctx.beginPath()
  ctx.arc(size * 1.5, size * 1.5, size, 1.5 * Math.PI, (1.5 + p) * Math.PI)
  ctx.stroke()
  if (p < 2) {
    window.requestAnimationFrame(draw);
  }
}

window.requestAnimationFrame(draw);
<canvas id="canvas1" width="500" height="500"></canvas>
...