25

我目前正在使用 HTML5 的画布使用 fillText 方法呈现多个字符串。这很好用,但我也想给每个字符串一个 1px 黑色外笔划。不幸的是,strokeText 函数似乎应用了内部笔划。为了解决这个问题,我编写了一个 drawStrokedText 函数来实现我想要的效果。不幸的是,它太慢了(原因很明显)。

有没有一种快速、跨浏览器的方式来使用原生画布功能实现 1px 的外部笔划?

drawStrokedText = function(context, text, x, y)
{
    context.fillStyle = "rgb(0,0,0)";
    context.fillText(text, x-1, y-1);
    context.fillText(text, x+1, y-1);
    context.fillText(text, x-1, y);
    context.fillText(text, x+1, y);
    context.fillText(text, x-1, y+1);
    context.fillText(text, x+1, y+1);

    context.fillStyle = "rgb(255,255,255)";
    context.fillText(text, x, y);
};

下面是一个工作效果的例子:

在此处输入图像描述

4

4 回答 4

66

中风是怎么回事?由于一半的笔画将在形状之外,因此您始终可以先绘制笔画,线宽为您想要的两倍。所以如果你想要一个 4px 的外部笔划,你可以这样做:

function drawStroked(text, x, y) {
    ctx.font = '80px Sans-serif';
    ctx.strokeStyle = 'black';
    ctx.lineWidth = 8;
    ctx.strokeText(text, x, y);
    ctx.fillStyle = 'white';
    ctx.fillText(text, x, y);
}


drawStroked("37°", 50, 150);

这使得:

在此处输入图像描述

现场小提琴:http: //jsfiddle.net/vNWn6/


如果碰巧在较小的文本渲染比例下看起来不那么准确,您总是可以将其画大但按比例缩小(在上述情况下,您会这样做ctx.scale(0.25, 0.25)

于 2012-11-29T23:43:45.143 回答
28

西蒙的回答是一个很好的解决方案,但在某些情况下可能会出现斜接故障,尤其是大写字母“M”、“V”和“W”:

drawStroked("MVW", 50, 150);

http://jsfiddle.net/hwG42/1/

在这种情况下,最好使用:

ctx.miterLimit=2;

http://jsfiddle.net/hwG42/3/

祝你好运!

于 2014-03-07T20:16:09.933 回答
5

对于平滑的阴影,你可以试试这个

ctx.beginPath();
ctx.fillStyle = 'white';
ctx.font = "bold 9pt Tahoma";
ctx.shadowBlur = 3;
ctx.textAlign = "center";
ctx.shadowColor = "#000000";
ctx.shadowOffs = 0;                 
ctx.fillText('www.ifnotpics.com', 100, 50);        
ctx.closePath();
于 2017-07-04T12:39:29.387 回答
5

上面的答案很棒,使用其中一些解决方案*和我自己的一些想法,我在下面的小提琴中做了一个快速参考和一些创造性的替代方案。

*在小提琴代码中到期的所有学分

drawStrokedText   ( text, x, y );
drawShadowedText  ( text, x, y, shadowBlur);
drawGlowingText   ( text, x, y, glowColorHex, glowDistance);
drawBlurredText   ( text, x, y, blurAmount);
drawReflectedText ( text, x, y, reflectionScale, reflectionOpacity);

https://jsfiddle.net/vtmnea8/

// Author: Aaron Edmistone
// Text effects using HTML5 Canvas with 2D Context.
// https://stackoverflow.com/questions/7814398/a-glow-effect-on-html5-canvas

var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');

// prepare the presentation of the canvas
ctx.fillStyle = 'black';
ctx.fillRect(0,0,250,450);
ctx.fillStyle = 'gray';
ctx.fillRect(250,0,250,450);
ctx.fillStyle = 'white';
ctx.fillRect(500,0,250,450);
ctx.fillStyle = '#0066CC';
ctx.fillRect(750,0,250,450);

// prepare the font and fill
ctx.font = "80px Sans-serif";
ctx.fillStyle = "white";

function drawStrokedText(text, x, y)
{
        // using the solutions from @Simon Sarris and @Jackalope from
    // https://stackoverflow.com/questions/7814398/a-glow-effect-on-html5-canvas
        ctx.save();
    ctx.strokeStyle = 'black';
    ctx.lineWidth = 8;
    ctx.lineJoin="round";
      ctx.miterLimit=2;
    ctx.strokeText(text, x, y);
    ctx.fillText(text, x, y);
    ctx.restore();
}

function drawShadowedText(text, x, y, shadowBlur = 3)
{
        ctx.save();
    ctx.shadowBlur = shadowBlur;
    ctx.shadowColor = "#000000";
    ctx.shadowOffsetX = 4;
    ctx.shadowOffsetY = 4;
    ctx.fillText(text, x, y);
    ctx.restore();
}

function drawGlowingText(text, x, y, glowColorHexString, glowDistance = 10)
{
        ctx.save();
    ctx.shadowBlur = glowDistance;
    ctx.shadowColor = glowColorHexString;
    ctx.strokeText(text, x, y);
    
    for(let i = 0; i < 3; i++)
        ctx.fillText(text, x, y); //seems to be washed out without 3 fills
      
    ctx.restore();
}

function drawBlurredText(text, x, y, blur = 5)
{
    //using technique from https://www.html5rocks.com/en/tutorials/canvas/texteffects/
    ctx.save();
  let width = ctx.measureText(text).width + blur * 2;
  ctx.shadowColor = ctx.fillStyle;
  ctx.shadowOffsetX = width + x + ctx.canvas.width;
  ctx.shadowOffsetY = 0;
  ctx.shadowBlur = blur;
  ctx.fillText(text, -width + -ctx.canvas.width, y);
  ctx.restore();
}

function drawReflectedText(text, x, y, reflectionScale = 0.2, reflectionAlpha = 0.10)
{
    ctx.save();
  ctx.fillText(text, x, y);
    ctx.scale(1, -reflectionScale);
  ctx.globalAlpha = reflectionAlpha;
  ctx.shadowColor = ctx.fillStyle;
  ctx.shadowBlur = 15;
    ctx.fillText(text, x, -(y * (1 / reflectionScale)));
  ctx.restore();
}

for(let i = 0; i < 4; i++)
{
    drawStrokedText     ("MVW", 20 + i * 250, 80 * 1);
    drawShadowedText    ("MVW", 20 + i * 250, 80 * 2, 3);
  drawGlowingText       ("MVW", 20 + i * 250, 80 * 3, "#FF0000", 10);
  drawBlurredText       ("MVW", 20 + i * 250, 80 * 4, 5);
  drawReflectedText ("MVW", 20 + i * 250, 80 * 5, 0.5, 0.5);
}
<canvas id="myCanvas" width="1000" height="500"></canvas>

小提琴的输出:

下面小提琴的输出

它支持什么:

  • 大纲文本
  • 阴影文字
  • 发光的文字
  • 文字模糊
  • 反射文本

一些性能指标:

考虑在游戏中或以高帧速率使用它?使用上述方法检查这个jsperf 。

https://jsperf.com/various-text-effects-html5-2d-context

于 2019-04-22T06:30:40.190 回答