UNPKG

aframe

Version:

A web framework for building virtual reality experiences.

301 lines (224 loc) 16.2 kB
--- title: text type: components layout: docs parent_section: components source_code: src/components/text.js examples: - title: Stock Font Showcase src: https://glitch.com/~aframe-text-fonts-demo --- The text component renders signed distance field (SDF) font text. [exampleimage]: https://cloud.githubusercontent.com/assets/674727/22357731/f704544a-e3ee-11e6-8e6e-96c3c4e84958.png ![Example Image][exampleimage] <!--toc--> ## Introduction [three-bmfont-text]: https://github.com/Jam3/three-bmfont-text Note that rendering text in 3D is hard. In 2D web development, text is the most basic thing because the browser's renderer and layout engine handle everything. In a 3D context, we don't have those luxuries. There are several other different ways to render text in A-Frame including: - [3D Text Geometry](https://www.npmjs.com/package/aframe-text-geometry-component) - [HTML Materials (DOM-to-Canvas-to-Texture)](https://github.com/mayognaise/aframe-html-shader) - Image Textures As a default, we've selected SDF-based text to be included as a core component due to its **relatively good performance and clarity**. This component uses [mattdesl's `three-bmfont-text` library][three-bmfont-text]. The standard text component has a long lineage, starting out as a community component and was forked and improved several times before landing into A-Frame! ## Example Here's a basic example of text defining just the content with not much other configuration. ```html <a-entity text="value: Hello World;"></a-entity> ``` See more examples to see configuration of alignments, anchors, baselines, scaling, and auto-sizing. [exampletext]: https://aframe.io/aframe/examples/test/text/index.html [codetext]: https://github.com/aframevr/aframe/blob/master/examples/test/text/index.html [exampleanchors]: https://aframe.io/aframe/examples/test/text/anchors.html [codeanchors]: https://github.com/aframevr/aframe/blob/master/examples/test/text/anchors.html [examplescenarios]: https://aframe.io/aframe/examples/test/text/scenarios.html [codescenarios]: https://github.com/aframevr/aframe/blob/master/examples/test/text/scenarios.html [examplesizes]: https://aframe.io/aframe/examples/test/text/sizes.html [codesizes]: https://github.com/aframevr/aframe/blob/master/examples/test/text/sizes.html - [Text Example][exampletext] ([code][codetext]) - [Text Anchors][exampleanchors] ([code][codeanchors]) - [Text Scenarios][examplescenarios] ([code][codescenarios]) - [Text Sizes][examplesizes] ([code][codesizes]) Open any of these example scenes, hit **`<ctrl> + <alt> + i`** to open the Inspector, and play with all the possible values to see the effects instantly! [textinspector]: https://cloud.githubusercontent.com/assets/674727/22358436/ea430ef4-e3f3-11e6-9dd9-e5e72e6e803a.png ![Inspecting Text][textinspector] ## Properties [whitespace]: https://github.com/mattdesl/word-wrapper | Property | Description | Default Value | |---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------| | align | Multi-line text alignment (left, center, right). | left | | alphaTest | Discard text pixels if alpha is less than this value. | 0.5 | | anchor | Horizontal positioning (left, center, right, align). | center | | baseline | Vertical positioning (top, center, bottom). | center | | color | Text color. | white | | font | Font to render text, either the name of one of [A-Frame's stock fonts](#stock-fonts) or a URL to a font file | default | | fontImage | Font image texture path to render text. Defaults to the `font`'s name with extension replaced to `.png`. Don't need to specify if using a stock font. | *derived from font name* | | height | Height of text block. | *derived from text size* | | letterSpacing | Letter spacing in pixels. | 0 | | lineHeight | Line height in pixels. | *derived from font file* | | opacity | Opacity, on a scale from 0 to 1, where 0 means fully transparent and 1 means fully opaque. | 1.0 | | shader | Shader used to render text. | sdf | | side | Side to render. (front, back, double) | front | | tabSize | Tab size in spaces. | 4 | | transparent | Whether text is transparent. | true | | **value** | The actual content of the text. Line breaks and tabs are supported with `\n` and `\t`. | '' | | whiteSpace | How whitespace should be handled (i.e., normal, pre, nowrap). [Read more about whitespace][whitespace]. | normal | | width | Width in meters. | *derived from geometry if exists* | | wrapCount | Number of characters before wrapping text (more or less). | 40 | | wrapPixels | Number of pixels before wrapping text. | *derived from wrapCount* | | xOffset | X-offset to apply to add padding. | 0 | | zOffset | Z-offset to apply to avoid Z-fighting if using with a geometry as a background. | 0.001 | [threetextusage]: https://github.com/Jam3/three-bmfont-text#usage The implementation is based on [mattdesl's three-bmfont-text][three-bmfont-text]. [Read more about the text properties][threetextusage]. ## Events | Event Name | Description | |-------------|----------------------------------------------| | textfontset | Emitted when the font source has been loaded | ## Fonts We can specify different fonts, although the process is not as simple as Web Fonts. The text component defaults to `roboto` which uses a multi-channel signed distance (MSDF) font. MSDF helps to preserve sharp corners and edges. ### Stock Fonts Select from one of A-Frame's built-in fonts. These fonts will be loaded in from over a CDN. If you want your application to work better offline, download these fonts locally and point to them via a URL. | Stock MSDF Fonts | URL | |------------------|----------------------------------------------| | **roboto** | https://cdn.aframe.io/fonts/Roboto-msdf.json | | Stock SDF Fonts | URL | |-----------------|--------------------------------------------------| | aileronsemibold | https://cdn.aframe.io/fonts/Aileron-Semibold.fnt | | dejavu | https://cdn.aframe.io/fonts/DejaVu-sdf.fnt | | exo2bold | https://cdn.aframe.io/fonts/Exo2Bold.fnt | | exo2semibold | https://cdn.aframe.io/fonts/Exo2SemiBold.fnt | | kelsonsans | https://cdn.aframe.io/fonts/KelsonSans.fnt | | monoid | https://cdn.aframe.io/fonts/Monoid.fnt | | mozillavr | https://cdn.aframe.io/fonts/mozillavr.fnt | | sourcecodepro | https://cdn.aframe.io/fonts/SourceCodePro.fnt | ### Custom Fonts Different fonts can be specified using the `font` and `fontImage` properties. ```html <a-entity text="font: mozillavr; value: Via stock font name."></a-entity> <a-entity text="font: https://cdn.aframe.io/fonts/mozillavr.fnt; value: Via URL."></a-entity> <a-entity text="text: Hello World; font: ../fonts/DejaVu-sdf.fnt; fontImage: ../fonts/DejaVu-sdf.png"></a-entity> ``` If not specified, `fontImage` will be the `font`'s name, but with the extension replaced to `.png`. For example, if the `font` path ends with `mozillavr.fnt`, then the `fontImage` texture will default to `mozillavr.png`. ### Generating SDF Fonts [hiero]: https://github.com/libgdx/libgdx/wiki/Hiero [sdffonts]: https://github.com/libgdx/libgdx/wiki/Distance-field-fonts On top of the stock fonts, we can generate SDF fonts using [Hiero][hiero], a bitmap font packing tool. [See this guide for generating SDF fonts][sdffonts]. [msdfgen]: https://github.com/Chlumsky/msdfgen [msdf-bmfont]: https://github.com/Jam3/msdf-bmfont [msdf-bmfont-web]: http://msdf-bmfont.donmccurdy.com/ We can also generate MSDF fonts using [a web-based MSDF tool][msdf-bmfont-web], or on the commandline with [msdfgen] or [msdf-bmfont]. Tools for MSDF fonts may be less mature than the SDF alternatives. Below is an example comparing a font generated with Hiero, Arial Black, with the SDF font, DejaVu: [fontexampleimage]: http://i.imgur.com/iWtXHm5.png ![Arial Black vs. Deja Vu][fontexampleimage] ### Non-ASCII Characters To use non-ascii characters, you need to create your own custom font. The easiest way is to use [a web-based MSDF tool][msdf-bmfont-web]. Select your required character set and generate your own custom msdf font zip file. Here is an example of a French character set you can use: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.?!/:;,*§£$ø@+°-~#&²'{}[]|`\()=%*µ àâéèëêïîöôùüûÀÂÉÈËÊÏÎÖÔÜÛçÇ€ Once you download your custom msdf font zip file, extract it, then put both png and json files to your A-Frame directory. From A-Frame 0.9.0 and above, you don't need to rename `*.png` to `*-msdf.png` anymore, A-Frame loads the image defined in the json file. Lastly, you should specify the character set used in your HTML by using `<meta>` tag to avoid text to be garbled. If your text is garbled, it is not rendered. ```html <html> <head> <meta charset="UTF-8"> <script src="https://aframe.io/releases/1.7.0/aframe.min.js"></script> </head> <body> <a-scene> <a-sky color="lightblue"></a-sky> <a-text value="ABCあいうえお日本語" font="custom-msdf.json" font-image="custom-msdf.png" negate="false" scale="2 2 1" position="-2 2 -4"></a-text> </a-scene> </body> </html> ``` ## Sizing [position]: ./position.md [scale]: ./scale.md To change the size of the text, we can: - Change the `width`. - Change the `wrapCount` (roughly how many characters to fit inside the given width). - Change `wrapPixels`. - Change the [scale component][scale]. - [Position] the text closer or farther away. [sizingimg]: https://cloud.githubusercontent.com/assets/674727/22358452/04528216-e3f4-11e6-8467-f03ac7f0e953.png ![Sizing][sizingimg] Text can be wrapped by specifying width in A-Frame units. In case we need to do custom layout or need to know the bounds of the text, the output length of the text can be pre-calculated dynamically with something like: ``` totalWidth = data.value.length * (data.width / data.wrapCount) ``` ### Auto-Scaling The text component introduces special behavior when using alongside the geometry component (e.g., a background plane) to fit. Note this only works with 2D-friendly geometries that define a width and height (i.e., `box`, `plane`). The text can either be scaled, bounded, or aligned in relation to the geometry, or the text can auto-scale the geometry to fit the text. [geometryimg]: https://cloud.githubusercontent.com/assets/674727/22358470/218689d6-e3f4-11e6-9e00-62c9cb7867da.png ![Geometry Alignments][geometryimg] #### Scaling Text to Fit Geometry To have the text component's `width` property automatically scale to match the geometry component's `width`, do not specify a `width` for the text component: ```html <a-entity geometry="primitive: plane; width: 4; height: 0" material="color: blue" text="value: This text will be 4 units wide."></a-entity> ``` #### Scaling Geometry to Fit Text To have the geometry automatically scale with the text, set the geometry component's `width` and `height` properties to `0`, and set the text component's `width` as desired. In this example, the plane's `width` will be set to 4 units, and its `height` will be set to match the actual height of the text: ```html <a-entity geometry="primitive: plane; height: 0; width: 0" material="color: blue" text="width: 4; value: This text will be 4 units wide."></a-entity> ``` Note that if neither `geometry` nor `text` specify a width, the text `width` property will default to 1 unit (meter), and the geometry `width` property will then become 1 unit as well. ```html <a-entity geometry="primitive: plane" material="color: blue" text="value: 1-wide\ndefault."></a-entity> ``` ## Limitations The text component does not make use of all of the features of the [`three-bmfont-text` library][three-bmfont-text] nor its sister modules. [sdfsmooth]: https://lambdacube3d.wordpress.com/2014/11/12/playing-around-with-font-rendering/ Bitmap font rendering limits you to the characters included in the font (*Unicode this is not*). SDF font rendering tends to produce smooth sharp edges [though there are ways around this][sdfsmooth]. The generated text is not suitable for raycaster intersection testing. For raycaster or cursor detection it is necessary to use a geometry component along with the text component. ## Further Reading If you are curious about the details of text rendering in WebGL, three.js, and A-Frame, below are links to some background reading: [mattdesl]: http://slides.com/mattdeslauriers/hacking-with-three-js#/7 [parris]: https://www.eventbrite.com/engineering/its-2015-and-drawing-text-is-still-hard-webgl-threejs/ [valve]: https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf - [`three-bmfont-text` documentation][three-bmfont-text] - [*Hacking with three.js*][mattdesl] - [*It's 2015 and drawing text is still hard (WebGL, ThreeJS)*][parris] - [*Improved Alpha-Tested Magnification for Vector Textures and Special Effects*][valve]