Я знаю, что ответ принят, но я хотел представить очень простой подход для будущих читателей.Который, в качестве бонуса, автоматически вычисляет высоту каждой части и быстро, используя линейный градиент -
Результат будет
код и демо
var ctx = document.querySelector("canvas").getContext("2d"),
grad = ctx.createLinearGradient(0, 0, 0, 150);
grad.addColorStop(0, "red"); // start of red
grad.addColorStop(1/3, "red"); // end of red at 1/3
grad.addColorStop(1/3, "gold"); // start of gold at 1/3
grad.addColorStop(2/3, "gold"); // end of gold at 2/3
grad.addColorStop(2/3, "blue"); // start of blue at 2/3
grad.addColorStop(1, "blue"); // end of blue at 3/3
// Fill a triangle:
ctx.moveTo(75, 0); ctx.lineTo(150, 150); ctx.lineTo(0, 150);
ctx.fillStyle = grad;
ctx.fill();
<canvas/>
Анимат ред версии с использованием метода композитинга
var ctx = document.querySelector("canvas").getContext("2d"),
grad = ctx.createLinearGradient(0, 0, 0, 150),
step = grad.addColorStop.bind(grad), // function reference to simplify
dlt = -3, y = 150;
step(0, "red"); // start of red
step(1/3, "red"); // end of red at 1/3
step(1/3, "gold"); // start of gold at 1/3
step(2/3, "gold"); // end of gold at 2/3
step(2/3, "blue"); // start of blue at 2/3
step(1, "blue"); // end of blue at 3/3
// store a triangle path - we'll reuse this for the demo loop
ctx.moveTo(75, 0); ctx.lineTo(150, 150); ctx.lineTo(0, 150);
(function loop() {
ctx.globalCompositeOperation = "copy"; // will clear canvas with next draw
// Fill the previously defined triangle path with any color:
ctx.fillStyle = "#000"; // fill some solid color for performance
ctx.fill();
// draw a rectangle to clip the top using the following comp mode:
ctx.globalCompositeOperation = "destination-in";
ctx.fillRect(0, y, 150, 150 - y);
// now that we have the shape we want, just replace it with the gradient:
// to do that we use a new comp. mode
ctx.globalCompositeOperation = "source-in";
ctx.fillStyle = grad;
ctx.fillRect(0, 0, 150, 150);
y += dlt; if (y <= 0 || y >= 150) dlt = -dlt;
requestAnimationFrame(loop);
})();
<canvas/>
кэширования данных градиентного изображения для анимации (рекомендуется)
var ctx = document.querySelector("canvas").getContext("2d"),
tcanvas = document.createElement("canvas"), // to cache triangle
tctx = tcanvas.getContext("2d"),
grad = tctx.createLinearGradient(0, 0, 0, 150),
step = grad.addColorStop.bind(grad), // function reference to simplify
dlt = -3, y = 150;
step(0, "red"); // start of red
step(1/3, "red"); // end of red at 1/3
step(1/3, "gold"); // start of gold at 1/3
step(2/3, "gold"); // end of gold at 2/3
step(2/3, "blue"); // start of blue at 2/3
step(1, "blue"); // end of blue at 3/3
// draw triangle to off-screen canvas once.
tctx.moveTo(75, 0); tctx.lineTo(150, 150); tctx.lineTo(0, 150);
tctx.fillStyle = grad; tctx.fill();
(function loop() {
ctx.clearRect(0, 0, 150, 150);
// draw clipped version of the cached triangle image
if (150-y) ctx.drawImage(tcanvas, 0, y, 150, 150 - y, 0, y, 150, 150 - y);
y += dlt; if (y <= 0 || y >= 150) dlt = -dlt;
requestAnimationFrame(loop);
})();
<canvas/>
Вы можете изменить направление с помощью градиента линии,который определяет угол градиента.
// vertical
ctx.createLinearGradient(0, 0, 0, 150); // x1, y1, x2, y2
// hortizontal
ctx.createLinearGradient(0, 0, 150, 0); // x1, y1, x2, y2
// 45° degrees
ctx.createLinearGradient(0, 0, 150, 150); // x1, y1, x2, y2
и т.д.
Этот подход лучше, короче и не опасен для призрачных останков других рисованных пикселей. – dwana
Мне это тоже нравится, я дам оба выстрела. Сможете ли вы использовать animate() для этого, чтобы заполнить его снизу? – xHocquet
@xHocquet уверен, используя пару шагов компоновки, вы можете закрепить треугольную форму, а затем заполнить ее градиентом. Я добавил демо для удобства :) (вы можете кэшировать треугольник с градиентом на отдельном холсте и просто нарисовать обрезанную версию его обратно на основной холст). – K3N