【问题标题】:Replace a color on canvas替换画布上的颜色
【发布时间】:2019-01-25 16:43:05
【问题描述】:

我正在使用html5 画布制作游戏。我制作了一个 spritefont 系统,以便能够从纹理中绘制文本。即

.

现在我希望能够将文本的白色部分更改为我想要的任何颜色。我的猜测是我需要将纹理渲染到临时画布上更改颜色并获取新纹理并绘制它。

但是,我不知道如何使用画布的功能替换颜色。

我什至不知道这是否是最好的方法。我该怎么办?

【问题讨论】:

  • 你的纹理是如何制作的?它是在画布代码中完成的吗?如果只是一个文件,它在字符形状之外是透明的吗?
  • 这是一个 png 文件。是的,它在形状之外是透明的
  • 肯定不是最好的方法,如果存在字体文件,最好从画布本身以编程方式生成该 PNG 文件。拿到键盘后,我将发布更改白色填充的解决方案

标签: javascript html canvas html5-canvas


【解决方案1】:

HTML5 画布遵循绘制和忘记策略。如果您想对之前绘制的内容进行任何更改(无论是字体颜色还是形状或文本或线条等),您需要重新绘制所有内容。

主要取决于我对画布的使用,整个重新绘制过程非常快,并且没有任何延迟或延迟。

编辑

context.fillStyle = 'red';
context.strokeStyle = 'black';

context.font = '20pt Verdana';
context.fillText('Some text', 50, 50);
context.strokeText('Some text', 50, 50);

context.fill();
context.stroke();

【讨论】:

  • 是的,我知道。我的意思是改变颜色之前我在画布上绘制它。或许可以在一个小的临时画布上绘制它。
  • 可以使用canvas的fillStyle和strokeStyle属性来获取。你只需要重新运行代码。我已经编辑了答案以显示实现。
  • 遗憾的是,正如我所说,我使用的是 Spritefont,而不是常规文本。
【解决方案2】:

由于您的 spritefont 是单色的,您可以使用 CanvasRenderingContext2D's 'multiply' globalCompositeOperation 将颜色应用于白色部分。但是乘以一个纯色矩形会消除透明度,所以你需要用'destination-atop'重新绘制透明部分。

const FONT_COLOR = '#39f';

// Load up your spritefont
const spritefont = new Image();
spritefont.src = 'https://i.stack.imgur.com/mDvum.png';

// While waiting for the image to load,
// create a canvas to do the coloring work on
const fontCanvas = document.createElement('canvas');
const fontContext = fontCanvas.getContext('2d');

// Once the spritefont is loaded,
spritefont.addEventListener('load', function () {
  // Resize the canvas to match the image's dimensions
  fontCanvas.width = spritefont.width;
  fontCanvas.height = spritefont.height;

  // Draw your image on the canvas with a black background
  // Without the background, you'll get tinting at the partially-transparent edges
  fontContext.fillStyle = 'black';
  fontContext.fillRect(0, 0, fontCanvas.width, fontCanvas.height);
  fontContext.drawImage(spritefont, 0, 0);
  
  // Multiply by the font color
  // white * color = color, black * color = black
  fontContext.globalCompositeOperation = 'multiply';
  fontContext.fillStyle = FONT_COLOR;
  fontContext.fillRect(0, 0, fontCanvas.width, fontCanvas.height);

  // Restore the transparency
  fontContext.globalCompositeOperation = 'destination-atop';
  fontContext.drawImage(spritefont, 0, 0);
});

// Display the canvas in the snippet
document.body.append(fontCanvas);
/* just to prove that alpha is preserved */
canvas {background:0 0/32px 32px linear-gradient(45deg,#ccc 25%,transparent 25%,transparent 75%,#ccc 75%,#ccc),16px 16px/32px 32px linear-gradient(45deg,#ccc 25%,#999 25%,#999 75%,#ccc 75%,#ccc);}

如果您打算将变色功能放入函数中并重用画布(您应该这样做),请确保将上下文的 globalCompositeOperation 设置回默认值 'source-over'

【讨论】:

  • 谢谢。我开始研究那个。你是最棒的
猜你喜欢
  • 2019-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-23
  • 2019-12-08
  • 2012-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多