3

我正在尝试在 HTML5 Canvas 上获得动画打字机效果,但我真的很努力使用自动换行。

这是我在 Gist 中的 Shapes.js:https ://gist.github.com/Jamesking56/0d7df54473085b3c5394

在那里,我创建了一个具有很多方法的 Text 对象。其中之一称为typeText().

typeText()基本上是从打字效果开始的,但它一直在下降,我真的很难找到一种修复自动换行的方法。

任何人都可以指导我这样做的最佳方法是什么?

4

4 回答 4

2

我使用的一个解决方案大致是:

var maxWidth = 250;
var text = 'lorem ipsum dolor et sit amet...';

var words = text.split(' ');
var line = [words[0]]; //begin with a single word

for(var i=1; i<words.length; i++){
    while(ctx.measureText(line.join(' ')) < maxWidth && i<words.length-1){
        line.push(words[i++]);
    }
    if(i < words.length-1) { //Loop ended because line became too wide
        line.pop(); //Remove last word
        i--; //Take one step back
    }
    //Ouput the line
}

由于似乎无法测量输出文本的高度,因此您需要手动将输出的每一行偏移一些硬编码的行高。

于 2013-03-31T00:43:31.787 回答
0

我无法弄清楚你的Text构造函数是如何工作的。所以我写了一个独立的函数(不属于任何对象)。您需要传递给这个函数的只是一个字符串、XY位置、行高和填充。它假定将画布分配给变量canvas,并将 2d 上下文分配给变量ctx

var canvas, ctx;
function typeOut(str, startX, startY, lineHeight, padding) {
    var cursorX = startX || 0;
    var cursorY = startY || 0;
    var lineHeight = lineHeight || 32;
    padding = padding || 10;
    var i = 0;
    $_inter = setInterval(function() {
        var w = ctx.measureText(str.charAt(i)).width;
        if(cursorX + w >= canvas.width - padding) {
            cursorX = startX;
            cursorY += lineHeight;
        }
        ctx.fillText(str.charAt(i), cursorX, cursorY);
        i++;
        cursorX += w;
        if(i === str.length) {
            clearInterval($_inter);
        }
    }, 75);
}

在这里查看演示。

提示-

我正在浏览你的代码,发现了一些链接 -

function Rectangle(x,y,width,height,colour) {
    //properties
    this.draw = function() { //Don't assigns object methods through constructors
        ctx.fillStyle = this.colour;
        ctx.fillRect(this.x, this.y, this.width, this.height);
    };
}

您不应该通过构造函数向对象添加方法,因为它会在每次实例化对象时创建方法。而是将方法添加到对象的原型中,这样,它们将只创建一次,并由所有实例共享。喜欢-

function Rectangle(x,y,width,height,colour) {
    //properties
}
Rectangle.prototype.draw = function() {
    ctx.fillStyle = this.colour;
    ctx.fillRect(this.x, this.y, this.width, this.height);
}

另外,我发现您正在创建额外的变量来指向某些对象。喜欢 -

var that = this;
var fadeIn = setInterval(function() {
    //code
    that.draw();
    //code
}, time);

您不应该创建对该对象的额外引用Text。使用bind方法,以便this指向Text对象。喜欢-

var fadeIn = setInterval(function() {
    //code
    this.draw(); // <-- Check this it is `this.draw` no need for `that.draw`
    //code
}.bind(this), time);   //bind the object

在此处阅读有关绑定的更多信息。

希望有帮助。

PS:每个字符75毫秒,那将是神圣的每分钟800个字符!!!


更新- 如果您想要可缩放的图形,您应该考虑SVG。Canvas 是基于光栅的,而 SVG 是基于矢量的。这意味着 SVG 可以轻松调整大小,而当您调整画布大小时,画布的内容将开始像素化并且看起来很模糊。阅读更多

要调整画布内容的大小,您需要重新绘制整个画布。每当在画布上绘制某些东西时,浏览器都会绘制并忘记它。因此,如果您想更改对象的大小/位置,您需要完全清除画布并重新绘制对象。在您的情况下,您需要ctx.font根据画布的大小更改画布,然后更新画布,这将是一项非常乏味的任务。

于 2013-03-31T18:03:35.320 回答
-1

<canvas>不是为文本处理而设计的。通过将透明 DOM 元素覆盖在<canvas>. 这自然假设您不需要在<canvas>. 否则,您需要在 Javascript 中重新实现整个文本处理的东西,这有点重新发明轮子,因为浏览器可以简单地为我们做这件事。

这里有更多信息如何使用 CSSposition: absoluteposition: relative.

允许用户在 HTML5 Canvas 游戏中输入文本

我认为你应该有一个 DOM 元素,它的所有文本都是透明颜色的,每个字母都用<span>. 然后,您只需<span>通过调整不透明度开始使这些 s 可见。这样字母位置就不会改变。

于 2013-03-28T14:53:06.717 回答
-1

就个人而言,当我在画布游戏中需要文本时,我总是使用位图字体。它有几个优点:

  1. 画布上的 FillText 很慢。位图字体要快得多。
  2. 您知道每个字母的宽度,使换行和文本对齐更加容易。

您仍然可以通过使用案例合成操作来选择字体颜色,并通过动态调整绘制宽度高度来选择字体大小。

于 2013-03-28T18:13:09.597 回答