首页 > 解决方案 > 带有 HTML5 画布的三角形每个顶点的渐变

问题描述

如何在给定每个顶点颜色的情况下使用从顶点开始的渐变填充三角形?

我正在尝试重现这样的内容:

三角形

我正在使用fillHTML5 画布 Context2D 中的内置函数。我试图避免必须根据它们到顶点的距离来处理逐像素插值。我担心它不会像内置fill函数(?)那样高性能。我现在也不能处理 WebGL。

我已经使用径向渐变做了一个技巧,但是,我的幼稚方法存在一些问题:

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>

标签: javascripthtml5-canvasradial-gradients

解决方案


  • 颜色似乎没有很好地融合

为此,您可以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>


推荐阅读