Sizes & Resolutions

This document is a part of the <little-planet> project. Learn about it, see more examples and study the docs at the official README.

Rendering and layout size

When using the <little-planet> element, you need to specify its size using the width and height attributes (or the corresponding JS properties). This is the rendering size; it directly corresponds to the size of the underlying <canvas> element.

The panorama might be displayed in different size, though – the layout size that is set via CSS. Based on your design needs, you can apply different styles based on media queries or relative units (percentages, viewport-relative units). The CSS sizing is optional (if you do not apply any CSS, the element will be displayed using the rendering size), but desirable in certain situation (see below). If you decide to use CSS sizing, take care to always use size that is smaller or equal to the rendering size. The browser will have to upscale the canvas otherwise, which will look bad.

The following two panoramas have the same source image and the same layout size, but very different rendering sizes:

Large render size, downscaled to layout size (good)
Very small render size, upscaled to layout size (bad)

Maximum rendering size

While you can specify any rendering size (that your browser and/or video card is willing to accept), it only makes sense to pick values that can be reasonably covered with pixels from the source image. This means that the maximum good-looking rendering size is proportional to the size of that image. There is no exact equation (because it also depends on aspect ratios and zoom inside of the view), but it is generally pointless to use rendering sizes larger than half of the source image.

The information above holds for the Panorama view. The rules for the Little Planet view are a bit different, though. First, you ideally want a square aspect ratio (1:1), because the view resembles a centered sphere. Second, the maximum theoretical size of such square is twice the height of the source image. You do not need to remember this yourself, because the <little-planet> element will compute the value and provide it via the planetSize (readonly) property.

Hi-DPI (Retina) displays

Certain displays offer a very high physical resolution, but use a different/smaller logical resolution in order to maintain reasonable text visibility. For instance, many Apple devices use a double physical resolution: if you specify a font size of 18px (logical), the text will be rendered at 36 physical pixels.

This behavior is somewhat problematic with respect to raster data (such as bitmap images or <canvas> elements), as the browser has to stretch the image twice (or more) to fit the physical resolution. Fortunately, we can use the rendering/layout size trick to our advantage.

The amount of physical pixels per one logical pixel is available via the devicePixelRatio global variable. It is therefore sufficient to multiply the rendering size with this constant (or divide the logical size) to make the panorama look sharp even on high-resolution displays:

let scene = document.querySelector("little-planet")
let layoutWidth = 900
let layoutHeight = 600

scene.width = layoutWidth * devicePixelRatio
scene.height = layoutHeight * devicePixelRatio
scene.style.width = `${layoutWidth}px`
scene.style.height = `${layoutHeight}px`

Fullscreen

If you wish to display an element (this applies to all HTML elements, not just <little-planet>) in full-screen, you can use the Fullscreen API. Calling the requestFullscreen() method will stretch a particular element across the whole display. This is bad, because the scene will change its aspect ratio (to a value that is probably different from the rendering aspect ratio). If you want your Little Planet to look nice even in full-screen, make sure to update its rendering size to the screen aspect ratio.

The following code shows how to use the clienWidth and clientHeight properties to detect the stretched size and update rendering accordingly. Note that the devicePixelRatio issue matters, so you might need to update the code accordingly.

let scene = document.querySelector("little-planet")
scene.addEventListener("fullscreenchange", e => {
	if (document.fullscreenElement == scene) {
		scene.width = scene.clientWidth
		scene.height = scene.clientHeight
	} else {
		// non-fullscreen/default values
		scene.width = 1200
		scene.height = 900
	}
})

There is a fullscreen demo page available as an example of the techniques described above.