Градиенты в каждой вершине треугольника с холстом HTML5

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

Я пытаюсь воспроизвести что-то вроде этого:

треугольник

Я использую встроенную функцию fill из холста HTML5 Context2D. Я стараюсь избегать попиксельной интерполяции на основе их расстояния до вершин. Боюсь, что она не будет такой перформативной, как встроенная функция fill (?). Также я не могу сейчас заниматься WebGL.

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

  • Цвета плохо сочетаются
  • Последний примененный градиент перезаписывает остальные
  • Значение, используемое в переменной radius, произвольно.

OBS: Я не знаю, актуально ли это, но я строю полосу треугольников (на самом деле, индексированная геометрия).

var canvas = document.querySelector("canvas");

var ctx = canvas.getContext("2d");

var v1 = { x: 100, y: 0 };
var v2 = { x: 0, y: 180 };
var v3 = { x: 200, y: 180 };

var radius = 175;

var grd1 = ctx.createRadialGradient(v1.x, v1.y, 0, v1.x, v1.y, radius);
grd1.addColorStop(0, "#FF0000FF");
grd1.addColorStop(1, "#FF000000");

var grd2 = ctx.createRadialGradient(v2.x, v2.y, 0, v2.x, v2.y, radius);
grd2.addColorStop(0, "#00FF00FF");
grd2.addColorStop(1, "#00FF0000");

var grd3 = ctx.createRadialGradient(v3.x, v3.y, 0, v3.x, v3.y, radius);
grd3.addColorStop(0, "#0000FFFF");
grd3.addColorStop(1, "#0000FF00");

ctx.beginPath();

ctx.moveTo(v1.x, v1.y);
ctx.lineTo(v2.x, v2.y);
ctx.lineTo(v3.x, v3.y);

ctx.closePath();

ctx.fillStyle = "#FFFFFFFF"; // fill with white and apply the gradients on top of it
ctx.fill();

ctx.fillStyle = grd1;
ctx.fill();

ctx.fillStyle = grd2;
ctx.fill();

ctx.fillStyle = grd3;
ctx.fill();
<canvas width="200" height="180"></canvas>


person Pedro Henrique    schedule 09.07.2020    source источник
comment
Можете ли вы сделать квадрат с верхними углами синего цвета и перевести ширину сверху вниз от 0% до 100%?   -  person iAmOren    schedule 09.07.2020


Ответы (1)


  • Цвета плохо сочетаются

Для этого вы можете использовать свойство globalCompositeOperation вашего 2D-контекст для одного из его режимов наложения, хотя в вашем случае режим композитинга "lighter" с черным фоном, кажется, дает результат, наиболее близкий к вашей модели.

  • Последний примененный градиент перезаписывает остальные

Благодаря предыдущему пункту, это больше не так.

  • Значение, используемое в переменной радиуса, произвольно.

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

var canvas = document.querySelector("canvas");

var ctx = canvas.getContext("2d");

// reordered to make the same as OP's image
var v1 = { x: 0, y: 180 };
var v2 = { x: 200, y: 180 };
var v3 = { x: 100, y: 0 };

var radius = 180;

var grd1 = ctx.createRadialGradient(v1.x, v1.y, 0, v1.x, v1.y, radius);
grd1.addColorStop(0, "#FF0000FF");
grd1.addColorStop(1, "#FF000000");

var grd2 = ctx.createRadialGradient(v2.x, v2.y, 0, v2.x, v2.y, radius);
grd2.addColorStop(0, "#00FF00FF");
grd2.addColorStop(1, "#00FF0000");

var grd3 = ctx.createRadialGradient(v3.x, v3.y, 0, v3.x, v3.y, radius);
grd3.addColorStop(0, "#0000FFFF");
grd3.addColorStop(1, "#0000FF00");

ctx.beginPath();

ctx.moveTo(v1.x, v1.y);
ctx.lineTo(v2.x, v2.y);
ctx.lineTo(v3.x, v3.y);

ctx.closePath();

// fill with black
ctx.fill();

// set blend mode
ctx.globalCompositeOperation = "lighter";

ctx.fillStyle = grd1;
ctx.fill();

ctx.fillStyle = grd2;
ctx.fill();

ctx.fillStyle = grd3;
ctx.fill();

// if you need to draw something else, don't forget to reset the gCO
ctx.globalCompositeOperation = "source-over";
<canvas width="200" height="180"></canvas>

person Kaiido    schedule 09.07.2020