LuciadRIA supports display scaling. Display scaling is a feature available in most modern operating systems and graphics cards, allowing users to adjust the size of text, apps, and other items on the screen. It lets you change the balance between readability and screen real estate — the amount of space available for displaying information.
Modern devices have high-resolution (HiDPI) displays which can pack pixels much closer together than older screens. With that higher screen density, images become sharper and text becomes crisper. Without adjustments though, all the elements on the screen — such as menus, icons, and text — appear smaller, which can make them harder to see and interact with.
That’s where display scaling comes in: it scales up these elements, making them bigger and easier to see, without sacrificing the overall screen resolution.
If you run a LuciadRIA version older than 2024.1 on monitors with high display scale settings, it will show a blurrier map. |
Working with display scaling in LuciadRIA
Setting a fixed map display scale
You can set the display scale of a Map
using Map.displayScale
. Typical values for this display scale range
from 1, for a 100% display scale, to 4, for a 400% display scale.
The browser reports the operating system’s display scale through window.devicePixelRatio
. You can pass these
values directly to Map.displayScale
.
WebGLMap
with a fixed display scale that matches the operating system’s display scale.
const map = new WebGLMap("map", {
displayScale: window.devicePixelRatio
});
Note that this code sets the display scale once: at map creation time, it fixes the display scale to the one reported by the
browser.
That’s fine until the user drags the browser window to a monitor with a different display scale, or zooms the webpage, which
also changes the browser’s display scale (window.devicePixelRatio
). The display scale won’t adjust automatically to the change of monitor or page zoom level.
Automatically adjusting the map display scale
To allow the map to adjust the display scale automatically, enable autoAdjustDisplayScaling
on your WebGLMap
. This lets LuciadRIA track changes to window.devicePixelRatio
.
When it changes, Map.displayScale
is automatically updated.
WebGLMap
with automatic display scale adjustment.
const map = new WebGLMap("map", {
autoAdjustDisplayScale: true
});
map.on("DisplayScaleChanged", () => {
// With autoAdjustDisplayScale, map.displayScale always matches window.devicePixelRatio
console.log(`Map display scale is now: ${map.displayScale}`);
})
Understanding CSS pixels and physical pixels
In the context of display scaling, you can make a distinction between CSS pixels and physical pixels. A CSS pixel is defined as a single pixel on a 96 DPI display. A physical pixel is a single pixel on the device’s physical display. With a display scale of 100%, a single CSS pixel corresponds to a single physical pixel. On higher display scales, a single CSS pixel corresponds to multiple physical pixels. For example, with a display scaling of 200%, 1 CSS pixel amounts to 4 physical pixels. With 400% scaling, this number grows to 16 physical pixels.
CSS pixels are independent of display scale. This means that an image with a CSS width of 32px
is always
about the same width as a text character with a CSS size of 32px
, even when the display scale is set to 400%, resulting in the use of
16 times the amount of physical pixels.
In the LuciadRIA API, everything is expressed in CSS pixels.
For example, the |
Drawing high-resolution icons
On maps with high display scale values, it’s best to render icons with a higher-resolution image.
If you don’t do so, the icon might be blurry because a low-resolution image is rendered on more physical pixels.
To render icons with a higher-resolution image, specify a higher-resolution image in the IconStyle.image
:
class HiResIconPainter extends FeaturePainter {
paintBody(geoCanvas: GeoCanvas, feature: Feature, shape: Shape, layer: Layer, map: Map, paintState: PaintState) {
geoCanvas.drawIcon(shape, {
// generate a high-resolution icon image using the IconFactory in @luciad/ria-toolbox-core
image: createStar({
stroke: "black",
fill: "yellow",
width: 32 * map.displayScale,
height: 32 * map.displayScale,
strokeWidth: 2 * map.displayScale,
}),
// IconStyle.width and height are expressed in CSS pixels.
// ie. they're always the same size on screen, regardless of display scale.
width: "32px",
height: "32px"
});
}
}
If you’re using a UrlIconStyle
, you can provide a URL to a different, higher-resolution icon image.
UrlIconStyle
.
class HiResUrlIconPainter extends FeaturePainter {
paintBody(geoCanvas: GeoCanvas, feature: Feature, shape: Shape, layer: Layer, map: Map, paintState: PaintState) {
geoCanvas.drawIcon(shape, {
// provide a URL to a high-resolution icon image
url: map.displayScale >= 2 ? "/images/star@2x.png" : "/images/star.png",
// IconStyle.width and height are expressed in CSS pixels.
// ie. they're always the same size on screen, regardless of display scale.
width: "32px",
height: "32px"
});
}
}
LuciadRIA invalidates the |
Drawing high-resolution raster tile sets
LuciadRIA will draw the same raster tiles as on a classic 96 DPI screen regardless of display scale for two reasons:
-
Compatibility: Text, icons and line widths will remain the same size on screen
-
Performance: Loading the same amount of raster tiles results in the same performance as before
To configure the RasterTileSetLayer
to load higher or lower resolution tiles, you can configure the
RasterTileSetLayer.detailFactor
. The default value is 1 and if you increase it, the raster layer loads more
detailed tiles at the cost of performance. Decreasing it, loads less detailed tiles, which improves performance.
To display pixel-perfect tiles, make sure the RasterTileSetLayer.detailFactor
is equal to Map.displayScale
.
If you get a RasterTileSetModel
that contains text — city or street labels, for example — from a tile service,
it’s recommended to request a scaled version of the tile imagery. Otherwise, the text in the raster data will be
too small. Most raster imagery providers expose API to control this scaling. For example, HERE Maps has a
ppi
URL parameter
in their API. To use it, it should be applied to the HEREMapsTileSetModel
as is done in the HereMapsDataLoader
,
which can be found in LuciadRIA’s toolbox. A similar URL parameter is applied to the GoogleTileSetModel
and
BingMapsTileSetModel
in the toolbox. If you are using any other raster tileset with text in it,
check with the imagery provider whether they support scaled tile images for high-density displays.
Performance considerations
Display scaling affects performance. With a display scale of 200%, LuciadRIA uses 4 times as many physical pixels to render the map. With a display scale of 400%, this goes up to 16 times the amount of physical pixels. If you enable display scaling on devices with a high display scale and a relatively low-powered GPU, such as mobile devices, the device performance will be strongly impacted. The map is rendered at a higher quality at the cost of performance.
As the pixel resolution of the map increases,
the impact of map effects that scale with pixel resolution becomes stronger. Examples include MapEffects.antiAliasing
and MapEffects.eyeDomeLighting
.