Render text with javascript

Render HTML with Vanilla JavaScript and lit-html

Sometimes you need to render HTML elements on a web page. And like Goldilocks’ search for «just right», you have to try a few techniques before you find the right one. Using a framework may be too hard. Using pure HTML and the DOM API may be too soft. What you need is something in the middle that is just right. Is lit-html «just right»? Let’s find out. First, I’ll show how this all works. Then at the end of this article, I’ll explain everything you need to get started with lit-html to try this for yourself.

When you’re done, you can push your HTML app with lit-html to the cloud to see it in all of its glory! I included a link to a free Azure trial, so you can try it yourself.

The Sample App

Here is the app I’ll demonstrate in this article. It fetches a list of heroes and renders them when you click the button. It also renders a progress indicator while it is fetching.

What’s the Value of lit-html

When you focus on rendering content, and nothing else, lit-html is a good fit. It works closely with the DOM to render content, and refresh it in an optimal manner. The docs can provide you with more details, but the basic code for lit-html looks like this.

// Credit: As seen in official docs https://lit-html.polymer-project.org/guide/getting-started // Import lit-html import  html, render > from 'lit-html'; // Define a template const myTemplate = name => html` 

Hello $name> `; // Render the template to the document render(myTemplate('World'), document.body);

You import lit-html, define a template, then render it to the DOM. That’s it!

Rendering HTML

A progress bar is fairly basic. There is some HTML, and we show it when needed and hide it when it is not required. While we could use a template, or innerHTML, or the DOM API for this, let’s see what this would look like with lit-html.

First, we get a reference to the element in the DOM where the progress bar will appear.

Then we define the template. This code looks and feels like JSX (or TSX). The advantage here is that you can write the HTML. You wrap the HTML in a template string (notice the back-tick character is used and not a single quote). Template strings allow you to span lines and insert variables where needed (we’ll see this soon). The magic that makes this work is the html tag that precedes the template string. The html tag is what tells lit-html that you are about to define a template.

Next, we compile the template and pass those results to lit-html’s render function, which places the results in the DOM. Finally, we hide or show the progress bar as needed.

function showProgress(show = true)  const container = document.getElementById('progress-placeholder'); const template: () => TemplateResult = () => html` `; const result = template(); render(result, container); container.style.display = show ? 'block' : 'none'; > 

Now you can run this showProgress function any time you want to show the progress bar.

Note that when a template is re-rendered, the only part that is updated is the data that changed. If no data changed, nothing is updated.

Rendering HTML with Dynamic Values

The progress bar does not change each time it is rendered. You will have situations where you want your HTML to change. For example, you may have a message area on your web app that shows a styled message box with a title and a message. The title and message will change every time you show the message area. Now you have dynamic values.

The HTML is defined with a template string, so it is trivial to add a variable into it. Notice the code below adds a title and text into the template, using the $ and $ syntax, respectively.

Then the template is compiled and rendered were needed.

When this template is re-rendered, the only part that is updated is the data that changed. In this case, that’s the title and text.

function showMessage(text: string, title = 'Info')  const template: (data: any) => TemplateResult = (data: Message) => html` 
$data.title> $data.text>
`
; const el = document.getElementById('message-placeholder'); const result = template( title, text >); render(result, el); el.style.visibility = !!text ? 'visible' : 'hidden'; >

Rendering a List

So there is a little more logic here, regardless of whether we use lit-html or any other technique. Let’s explore how the replaceHeroList function renders the rows using lit-html.

function replaceHeroList(heroes?: Hero[])  const heroPlaceholder = document.querySelector('.hero-list'); // Define the template let template: () => TemplateResult; if (heroes && heroes.length)  // Create the template for every hero row template = createList(); > else  // Create the template with a simple "not found" message template = () => html` 

heroes not found

`
; > // Compile the template const result = template(); // Render the template render(result, heroPlaceholder);

    and embeds the array of hero templates. It’s pretty cool that we can embed templates like this! Finally, we return it all and let the logic compile the templates and render them.

Summary

When you want to render HTML, lit-html is a fast and light-weight option. Is it better than using templates and the DOM API? You’ll have to decide what is best for you. But the real story here is that you have another great option to consider when determining the right tool for your job.

Prologue

You can also get editor help with your lit-html templates. Notice the image below shows the syntax highlighting for the HTML template!

lit html syntax highlighting

Setup

You can install the lit-html package with npm.

Alternately you can load it directly from the unpkg.com CDN

import  html, render > from 'https://unpkg.com/lit-html?module'; 

You have a choice here. npm is my preference, but feel 100% free to use the CDN if that suits you.

TypeScript and lit-html

You only need to include the library for lit-html and you’re done. But I like to use TypeScript, and I absolutely recommend enabling your tooling to work great with typeScript and lit-html.

Let me be very clear here — you do not need TypeScript. I choose to use it because it helps identify mistakes while I write code. If you don’t want TypeScript, you can opt to use plain JavaScript.

Here are the steps to make TypeScript and lit-html light up together:

  1. Install TypeScript support for lit-html
  2. Configure your tsconfig.json file
  3. Install the VS Code extension for lit-html

Run this command to install the plugin and typescript, as development dependencies to your project.

npm install --save-dev typescript-lit-html-plugin typescript 

Edit your tsconfig.json by adding the following to your compilerOptions section.

"compilerOptions":  "plugins": [  "name": "typescript-lit-html-plugin" > ] > 

Now you get syntax highlighting for all of your lit-html templates!

Источник

Drawing text

After having seen how to apply styles and colors in the previous chapter, we will now have a look at how to draw text onto the canvas.

Drawing text

The canvas rendering context provides two methods to render text:

Fills a given text at the given (x,y) position. Optionally with a maximum width to draw.

Strokes a given text at the given (x,y) position. Optionally with a maximum width to draw.

A fillText example

The text is filled using the current fillStyle .

function draw()  const ctx = document.getElementById("canvas").getContext("2d"); ctx.font = "48px serif"; ctx.fillText("Hello world", 10, 50); > 
canvas id="canvas" width="300" height="100">canvas> 

A strokeText example

The text is filled using the current strokeStyle .

function draw()  const ctx = document.getElementById("canvas").getContext("2d"); ctx.font = "48px serif"; ctx.strokeText("Hello world", 10, 50); > 
canvas id="canvas" width="300" height="100">canvas> 

Styling text

In the examples above we are already making use of the font property to make the text a bit larger than the default size. There are some more properties which let you adjust the way the text gets displayed on the canvas:

The current text style being used when drawing text. This string uses the same syntax as the CSS font property. The default font is 10px sans-serif.

Text alignment setting. Possible values: start , end , left , right or center . The default value is start .

Baseline alignment setting. Possible values: top , hanging , middle , alphabetic , ideographic , bottom . The default value is alphabetic .

Directionality. Possible values: ltr , rtl , inherit . The default value is inherit .

These properties might be familiar to you, if you have worked with CSS before.

The top of the em square is roughly at the top of the glyphs in a font, the hanging baseline is where some glyphs like आ are anchored, the middle is half-way between the top of the em square and the bottom of the em square, the alphabetic baseline is where characters like Á, ÿ, f, and Ω are anchored, the ideographic baseline is where glyphs like 私 and 達 are anchored, and the bottom of the em square is roughly at the bottom of the glyphs in a font. The top and bottom of the bounding box can be far from these baselines, due to glyphs extending far outside the em square.

The following diagram from the WHATWG demonstrates the various baselines supported by the textBaseline property.

A textBaseline example

Edit the code below and see your changes update live in the canvas:

canvas id="canvas" width="400" height="200" class="playable-canvas">canvas> div class="playable-buttons"> input id="edit" type="button" value="Edit" /> input id="reset" type="button" value="Reset" /> div> textarea id="code" class="playable-code"> ctx.font = "48px serif"; ctx.textBaseline = "hanging"; ctx.strokeText("Hello world", 0, 100); textarea> 
const canvas = document.getElementById("canvas"); const ctx = canvas.getContext("2d"); const textarea = document.getElementById("code"); const reset = document.getElementById("reset"); const edit = document.getElementById("edit"); const code = textarea.value; function drawCanvas()  ctx.clearRect(0, 0, canvas.width, canvas.height); eval(textarea.value); > reset.addEventListener("click", () =>  textarea.value = code; drawCanvas(); >); edit.addEventListener("click", () =>  textarea.focus(); >); textarea.addEventListener("input", drawCanvas); window.addEventListener("load", drawCanvas); 

Advanced text measurements

In the case you need to obtain more details about the text, the following method allows you to measure it.

Returns a TextMetrics object containing the width, in pixels, that the specified text will be when drawn in the current text style.

The following code snippet shows how you can measure a text and get its width.

function draw()  const ctx = document.getElementById("canvas").getContext("2d"); const text = ctx.measureText("foo"); // TextMetrics object text.width; // 16; > 

Accessibility concerns

The element is just a bitmap and does not provide information about any drawn objects. Text written on canvas can cause legibility issues with users relying on screen magnification. The pixels within a canvas element do not scale and can become blurry with magnification. This is because they are not a vector but letter-shaped collection of pixels. When zooming in on it, the pixels become bigger.

Canvas content is not exposed to accessibility tools like semantic HTML is. In general, you should avoid using canvas in an accessible website or app. An alternative is to use HTML elements or SVG instead of canvas.

Gecko-specific notes

In Gecko (the rendering engine of Firefox, Firefox OS and other Mozilla based applications), some prefixed APIs were implemented in earlier versions to draw text on a canvas. These are now deprecated and removed, and are no longer guaranteed to work.

Found a content problem with this page?

This page was last modified on Feb 19, 2023 by MDN contributors.

Источник

Читайте также:  Java выйти из условия if
Оцените статью