📜  使用 webpack 加载 bmfont 三 - Javascript (1)

📅  最后修改于: 2023-12-03 15:22:17.470000             🧑  作者: Mango

使用 webpack 加载 bmfont 三 - Javascript

在前两篇教程中,我们讨论了如何使用 webpack 和 bmfont-loader 来加载 bmfont 字体。现在,我们将进一步探讨如何在 JavaScript 中使用 bmfont 加载的字体。在这个教程中,我们将使用 pixi.js 来演示如何在 canvas 上绘制文字。

安装 pixi.js

首先,让我们安装 pixi.js:

npm install pixi.js --save
创建 canvas

接下来,我们需要在 HTML 中创建一个 canvas 元素:

<canvas id="canvas"></canvas>

然后,在 JavaScript 中获取它并设置其大小:

const canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
加载 bmfont

接下来,我们需要加载我们之前使用 bmfont-loader 加载的字体。让我们在 JavaScript 文件中创建一个新的 Font 类,该类负责加载字体和渲染文字:

class Font {
  constructor(texture, data) {
    this.texture = texture;
    this.chars = {};

    // Parse the XML data
    const parser = new DOMParser();
    const xml = parser.parseFromString(data, 'text/xml');

    // Extract the info and common elements
    const info = xml.getElementsByTagName('info')[0];
    const common = xml.getElementsByTagName('common')[0];
    const scaleW = common.getAttribute('scaleW');
    const scaleH = common.getAttribute('scaleH');

    // Loop through each char element and extract the data
    const chars = xml.getElementsByTagName('char');
    for (let i = 0; i < chars.length; i++) {
      const id = chars[i].getAttribute('id');
      const x = chars[i].getAttribute('x');
      const y = chars[i].getAttribute('y');
      const width = chars[i].getAttribute('width');
      const height = chars[i].getAttribute('height');
      const xoffset = chars[i].getAttribute('xoffset');
      const yoffset = chars[i].getAttribute('yoffset');
      const xadvance = chars[i].getAttribute('xadvance');

      // Store the data into the chars object
      this.chars[id] = {
        x: x / scaleW,
        y: y / scaleH,
        width: width / scaleW,
        height: height / scaleH,
        xoffset: xoffset / scaleW,
        yoffset: yoffset / scaleH,
        xadvance: xadvance / scaleW
      };
    }
  }

  // Get the width of a string of text
  getTextWidth(text, size) {
    let width = 0;

    for (let i = 0; i < text.length; i++) {
      const char = this.chars[text.charCodeAt(i)];

      if (char) {
        width += char.width * size;
        if (i < text.length - 1) {
          width += char.xadvance * size;
        }
      }
    }

    return width;
  }

  // Render a string of text to the canvas
  render(text, size, x, y) {
    for (let i = 0; i < text.length; i++) {
      const char = this.chars[text.charCodeAt(i)];

      if (char) {
        const sprite = new PIXI.Sprite(this.texture);
        sprite.x = x + char.xoffset * size;
        sprite.y = y + char.yoffset * size;
        sprite.width = char.width * size;
        sprite.height = char.height * size;
        sprite.texture.frame = new PIXI.Rectangle(
          char.x * this.texture.width,
          char.y * this.texture.height,
          char.width * this.texture.width,
          char.height * this.texture.height
        );
        PIXI.app.stage.addChild(sprite);

        x += char.width * size + char.xadvance * size;
      }
    }
  }
}

在构造函数中,我们解析 XML 数据并将其存储在 chars 对象中。然后,我们按照逐个字符地显示文本的方式来实现 getTextWidthrender 方法。getTextWidth 方法返回字符串的宽度(以像素为单位),render 方法将字符串呈现在 canvas 上。

要加载字体,请使用以下代码:

import fontData from './font.fnt';
import fontTexture from './font.png';

const font = new Font(PIXI.Texture.from(fontTexture), fontData);

我们在代码中导入字体数据和纹理。然后,我们将它们传递给 Font 类的构造函数来加载字体数据。

呈现文本

现在我们已经加载了字体,让我们呈现一些文本。为此,我们需要使用 Font 类的 render 方法。例如:

font.render('Hello, world!', 32, 50, 50);

这将呈现字符串“Hello, world!”,字体大小为 32,位于 canvas(50, 50)处。

示例代码

下面是示例代码的完整版本:

import * as PIXI from 'pixi.js';
import fontData from './font.fnt';
import fontTexture from './font.png';

class Font {
  constructor(texture, data) {
    this.texture = texture;
    this.chars = {};

    // Parse the XML data
    const parser = new DOMParser();
    const xml = parser.parseFromString(data, 'text/xml');

    // Extract the info and common elements
    const info = xml.getElementsByTagName('info')[0];
    const common = xml.getElementsByTagName('common')[0];
    const scaleW = common.getAttribute('scaleW');
    const scaleH = common.getAttribute('scaleH');

    // Loop through each char element and extract the data
    const chars = xml.getElementsByTagName('char');
    for (let i = 0; i < chars.length; i++) {
      const id = chars[i].getAttribute('id');
      const x = chars[i].getAttribute('x');
      const y = chars[i].getAttribute('y');
      const width = chars[i].getAttribute('width');
      const height = chars[i].getAttribute('height');
      const xoffset = chars[i].getAttribute('xoffset');
      const yoffset = chars[i].getAttribute('yoffset');
      const xadvance = chars[i].getAttribute('xadvance');

      // Store the data into the chars object
      this.chars[id] = {
        x: x / scaleW,
        y: y / scaleH,
        width: width / scaleW,
        height: height / scaleH,
        xoffset: xoffset / scaleW,
        yoffset: yoffset / scaleH,
        xadvance: xadvance / scaleW
      };
    }
  }

  // Get the width of a string of text
  getTextWidth(text, size) {
    let width = 0;

    for (let i = 0; i < text.length; i++) {
      const char = this.chars[text.charCodeAt(i)];

      if (char) {
        width += char.width * size;
        if (i < text.length - 1) {
          width += char.xadvance * size;
        }
      }
    }

    return width;
  }

  // Render a string of text to the canvas
  render(text, size, x, y) {
    for (let i = 0; i < text.length; i++) {
      const char = this.chars[text.charCodeAt(i)];

      if (char) {
        const sprite = new PIXI.Sprite(this.texture);
        sprite.x = x + char.xoffset * size;
        sprite.y = y + char.yoffset * size;
        sprite.width = char.width * size;
        sprite.height = char.height * size;
        sprite.texture.frame = new PIXI.Rectangle(
          char.x * this.texture.width,
          char.y * this.texture.height,
          char.width * this.texture.width,
          char.height * this.texture.height
        );
        PIXI.app.stage.addChild(sprite);

        x += char.width * size + char.xadvance * size;
      }
    }
  }
}

const canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

const app = new PIXI.Application({
  view: canvas,
  transparent: true
});

const font = new Font(PIXI.Texture.from(fontTexture), fontData);
font.render('Hello, world!', 32, 50, 50);
结论

在本教程中,我们学习了如何在 JavaScript 中使用 pixi.js 来渲染使用 bmfont 加载的字体。我们创建了一个包含 Font 类的 JavaScript 文件,并使用它来加载和呈现字体。我们使用 Font 类的 render 方法在 canvas 上呈现文本。最后,我们演示了如何将文字渲染到 canvas 中。

希望这个教程对您有所帮助!