как создать canvas с градиентом

136
06 января 2021, 22:50

Ка сделать так чтобы по ид создавались новые canvas в зависимости от текста то есть
Внутри canvas прозрачный цвет только граница с градиентом нужна

<button type="submit" id="can-img">Кнопка</button>

Answer 1

Давайте покрасим каждый пиксель сами, для этого используем математику и прямые манипуляции с с пикселями, такой подход позволяет очень точно посчитать различные эффекты, сложно достижимые при обычном рисовании встроенными методами.

Я недавно задавал вопрос-ответ на этот счет, в этом примере применен тот же подход:

^^ это анимированный гиф, хоть и не заметно почти

Пару слов о том как это работает.

Signed Distance Function(или Field) - это такой механизм определения минимального расстояния до ближайшего объекта сцены.

SDF может быть задан формулами или массивом значений расстояний (обычно это один канал текстуры)

Вот пример изображения с sdf для звезды, это по сути обрамляющий градиент вокруг фигуры

Теперь, используя цикл по всем пикселям и не хитрые вычисления мы определяем как красить каждый пиксель в зависимости от его расстояния до фигуры.

В коде ниже использована формула, которая возвращает расстояние до скругленного прямоугольника. Больше формул тут. Формулы эти можно всячески комбинировать и использовать получившуюся функцию для получения изображения объектов, (не обязательно в 2d, так же можно получать изображения 3d объектов используя SDF и трассировку лучей)

let c = canvas.getContext('2d'), w = canvas.width, h = canvas.height    
  
requestAnimationFrame(draw)  
  
function draw(t) {   
  let i = c.getImageData(0, 0, w, h)  
  // цикл по всем пикселям  
  for(var x = 0; x < w; x++) {  
  for(var y = 0; y < h; y++) {  
      let v = px(x, y, t)  
      let o = (y*w + x)*4      
      i.data[o++] = v[0]*255  
      i.data[o++] = v[1]*255  
      i.data[o++] = v[2]*255  
      i.data[o++] = v[3]*255  
  }}  
  c.putImageData(i, 0, 0)  
  requestAnimationFrame(draw)  
}  
  
// функция дистанции до скругленного прямоугольника  
// https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm  
function sdRoundBox(x, y, sx, sy, r) {  
  x = Math.abs(x) - sx;  
  y = Math.abs(y) - sy;  
  sx = Math.max(x, 0);   
  sy = Math.max(y, 0);  
  return Math.min(Math.max(x, y), 0) + Math.sqrt(sx*sx + sy*sy) - r;  
}  
  
// функция которая определяет цвет пикселя  
function px(x, y, t) {  
  // определим минимальное расстояние от текущего пикселя до нашей фигуры  
  let d = Math.abs(sdRoundBox(2*x-w, 2*y-h, 150, 40, 15));  
  if (d>16) return [0, 0, 0, 0]  
  // и используем это расстояние и координату пикселя по х для определения цвета пикселя  
  let c = Math.min(d/32 + 0.3 + Math.sin(t/1000)*0.1, d/8);  
  return [0.4+(x/w+1-y/h)*0.3, c, 1, 1-c];  
}
<canvas width="200" height="100" id="canvas"/>

Answer 2

Можно создать градиент с помощью функции ctx.createLinearGradient()

Пример кода:

let canvas = document.getElementById('canvas'); 
let ctx = canvas.getContext('2d'); 
 
//создаем градиент 
let gradient = ctx.createLinearGradient(20, 0, 220, 0); 
 
//добавляем три точки остановки 
gradient.addColorStop(0, 'green'); 
gradient.addColorStop(.5, 'cyan'); 
gradient.addColorStop(1, 'green'); 
 
//рисуем контур прямоугольника с помощью ерадиента 
ctx.strokeStyle = gradient; 
ctx.strokeRect(20, 20, 200, 100);
<canvas id="canvas"></canvas>

Функция ctx.createLinearGradient() принимает четыре аргумента:

x0 - Координата по оси X начальной точки.
y0 - Координата по оси Y начальной точки.
x1 - Координата по оси X конечной точки.
y1 - Координата по оси Y конечной точки.

Чтобы задать точки останова используется функция gradient.addColorStop();, принимающая два параметра: первый - смещение от начала градиента (не должен выходить за пределы 0 - 1), где будет расположена точка останова, второй - цвет до которого дойдет градиент в этой точке останова.

READ ALSO
Показать скрыть div по очереди

Показать скрыть div по очереди

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

103
Верстка резанных углов [дубликат]

Верстка резанных углов [дубликат]

Нужно сверстать резанный уголКаким образом можно это реализовать? Сразу скажу линейный градиент не подходит

119
Передача UTF-8 строки из Python в С++ DLL

Передача UTF-8 строки из Python в С++ DLL

Пытаюсь передать строку UTF-8 (кириллица) из Python на вход с++ DLL

99
шаблонный обьект и Variadic templates

шаблонный обьект и Variadic templates

Создаю по шаблону разные обьекты:

106