Skip to content

Commit

Permalink
Merge pull request pixijs-userland#30 from pixijs/feature/custom-fonts
Browse files Browse the repository at this point in the history
Support custom fonts, custom CSS style overrides
  • Loading branch information
bigtimebuddy authored Dec 15, 2022
2 parents a0ac79d + 205ad8a commit 18b4fd7
Show file tree
Hide file tree
Showing 15 changed files with 18,048 additions and 9,049 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ jobs:
- name: Install Dependencies
run: npm ci
- name: Built and Test
run: npm test
uses: GabrielBB/xvfb-action@v1
with:
run: npm test
37 changes: 26 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ Disadvantages:

* Unlike `PIXI.Text`, HTMLText rendering will vary slightly between platforms and browsers. HTMLText uses SVG/DOM to render text and not Context2D's fillText like `PIXI.Text`.
* Performance and memory usage is on-par with `PIXI.Text` (that is to say, slow and heavy)
* Only works with browsers that support [`<foreignObject>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject), i.e., no Internet Explorer support.
* Only supports [web-safe fonts](https://www.w3schools.com/cssref/css_websafe_fonts.asp) for the `fontFamily` attribute.
* Only works with browsers that support [`<foreignObject>`](https://caniuse.com/?search=foreignObject).

## Install

Expand All @@ -28,34 +27,51 @@ yarn add @pixi/text-html

```js
import { HTMLText } from '@pixi/text-html';
import { TextStyle } from '@pixi/text';

// Can use the TextStyle class found in @pixi/text
const style = new TextStyle({ fontSize: 20 });

// Make a new HTMLText object
const text = new HTMLText("Hello World", style);
const text = new HTMLText("Hello World", { fontSize: 20 });
```

_**Important:** Because the HTMLText object takes a raw HTML string, it's represents a potential vector for [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting), it's strongly encourage you santize input especially if you're accepting user-strings._

### Custom Fonts

Because rendering within a `<foreignObject>` element does not have access to fonts available in the current document, therefore, you need to load the fonts explicitly.

```js
const text = new HTMLText("Hello World", { fontFamily: 'Custom' });

await text.style.loadFont('./path/to/custom-regular.ttf', { family: 'Custom' });
```

**Multiple Weights**

```js
const text = new HTMLText("Hello <b>World</b>", { fontFamily: 'Custom' });

await Promise.all([
text.style.loadFont('./path/to/custom-regular.ttf', { family: 'Custom' }),
text.style.loadFont('./path/to/custom-bold.ttf', { family: 'Custom', weight: 'bold' });
]);
```

## Styles

Not all styles and values are compatible between PIXI.Text, mainly because Text is rendered using a DOM element instead of Context2D's fillText API.

**Supported**

* `fill`
* `fontFamily` (web-safe fonts only)
* `fontFamily`
* `fontSize`
* `fontWeight`
* `fontStyle`
* `fontVariant`
* `letterSpacing`
* `align` (also supports "justify")
* `align` (also supports `justify` value)
* `padding`
* `breakWords`
* `lineHeight`
* `whiteSpace` (also supports `nowrap`, `pre-wrap` values)
* `wordWrap`
* `wordWrapWidth`
* `strokeThickness`
Expand All @@ -77,7 +93,6 @@ Not all styles and values are compatible between PIXI.Text, mainly because Text
* `fillGradientType`
* `miterLimit`
* `textBaseline`
* `whiteSpace`

## Example

Expand Down
Binary file added demo/OpenSans-Bold.ttf
Binary file not shown.
Binary file added demo/OpenSans-Regular.ttf
Binary file not shown.
37 changes: 27 additions & 10 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,34 +39,51 @@ <h2>Internal Preview</h2>
});
document.getElementById('app').appendChild(app.view);

const style = new PIXI.TextStyle({
const style = new PIXI.HTMLTextStyle({
fontSize: 40,
fontFamily: ['OpenSans', 'Courier New'],
align: 'justify',
letterSpacing: 3,
letterSpacing: 1,
wordWrap: true,
wordWrapWidth: 600,
lineHeight: 48,
dropShadow: true,
dropShadowDistance: 1,
dropShadowAngle: Math.PI / 2,
dropShadowColor: '#cccccc',
dropShadowColor: '#ffffff',
dropShadowAlpha: 0.5,
whiteSpace: 'normal',
});
style.addOverride('background-image: linear-gradient(45deg, #f3ec78, #af4261)');

const text = 'Lorem ipsum dolor sit amet, &#x1F680; <b>consectetur &nbsp; adipiscing elit</b>. <br> Phasellus porta&nbsp;nisi est, vitae <i>sagittis ex gravida ac</i>. Sed vitae malesuada neque.';
const text = 'Lorem ipsum dolor sit amet, &#x1F680; <b>consectetur &nbsp; adipiscing elit</b>.<br>Phasellus porta&nbsp;nisi est, vitae <i>sagittis ex gravida ac</i>. Sed vitae malesuada neque.';

const text2 = new PIXI.HTMLText(text, style);
text2.texture.baseTexture.on('update', () => app.render());
text2.texture.baseTexture.on('update', () => {
app.render();
refreshBounds();
});
text2.y = 20;
text2.x = 20;

// Load the font weights
Promise.all([
text2.style.loadFont('./OpenSans-Regular.ttf', { family: 'OpenSans' }),
text2.style.loadFont('./OpenSans-Bold.ttf', { family: 'OpenSans', weight: 'bold' }),
]).then(() => app.render());

document.getElementById('text').appendChild(text2.canvas);
const rect = new PIXI.Graphics();

const refreshBounds = () => rect
.clear()
.beginFill(0, 0.01)
.lineStyle({ color: 0xffffff, width: 1, native: true })
.drawRect(text2.x, text2.y, text2.width, text2.height);

const rect = new PIXI.Graphics()
.beginFill(0, 0)
.lineStyle({ color: 0xff0000, width: 1, native: true })
.drawShape(text2.getBounds());
refreshBounds();

app.stage.addChild(rect, text2);
app.stage.addChild(text2, rect);
</script>
</body>
</html>
Loading

0 comments on commit 18b4fd7

Please sign in to comment.