IconLayer
The IconLayer renders raster icons at given coordinates.
There are two approaches to load icons. You can pre-generated a sprite image (iconAtlas), which packs all your icons
into one layout, and a JSON descriptor (iconMapping), which describes the position and size of each icon in the iconAtlas.
You can create sprite images with tools such as TexturePacker. This is the
most efficient way to load icons.
It is also possible to ask IconLayer to generate iconAtlas dynamically. This is slower but might be useful in certain
use cases.
Example: pre-packed iconAtlas
- JavaScript
- TypeScript
- React
import {Deck} from '@deck.gl/core';
import {IconLayer} from '@deck.gl/layers';
const layer = new IconLayer({
id: 'IconLayer',
data: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/bart-stations.json',
getColor: d => [Math.sqrt(d.exits), 140, 0],
getIcon: d => 'marker',
getPosition: d => d.coordinates,
getSize: 40,
iconAtlas: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/icon-atlas.png',
iconMapping: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/icon-atlas.json',
pickable: true
});
new Deck({
initialViewState: {
longitude: -122.4,
latitude: 37.74,
zoom: 11
},
controller: true,
getTooltip: ({object}) => object && object.name,
layers: [layer]
});
import {Deck, PickingInfo} from '@deck.gl/core';
import {IconLayer} from '@deck.gl/layers';
type BartStation = {
name: string;
entries: number;
exits: number;
coordinates: [longitude: number, latitude: number];
};
const layer = new IconLayer<BartStation>({
id: 'IconLayer',
data: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/bart-stations.json',
getColor: (d: BartStation) => [Math.sqrt(d.exits), 140, 0],
getIcon: (d: BartStation) => 'marker',
getPosition: (d: BartStation) => d.coordinates,
getSize: 40,
iconAtlas: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/icon-atlas.png',
iconMapping: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/icon-atlas.json',
pickable: true
});
new Deck({
initialViewState: {
longitude: -122.4,
latitude: 37.74,
zoom: 11
},
controller: true,
getTooltip: ({object}: PickingInfo<BartStation>) => object && object.name,
layers: [layer]
});
import React from 'react';
import {DeckGL} from '@deck.gl/react';
import {IconLayer} from '@deck.gl/layers';
import type {PickingInfo} from '@deck.gl/core';
type BartStation = {
name: string;
entries: number;
exits: number;
coordinates: [longitude: number, latitude: number];
};
function App() {
const layer = new IconLayer<BartStation>({
id: 'IconLayer',
data: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/bart-stations.json',
getColor: (d: BartStation) => [Math.sqrt(d.exits), 140, 0],
getIcon: (d: BartStation) => 'marker',
getPosition: (d: BartStation) => d.coordinates,
getSize: 40,
iconAtlas: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/icon-atlas.png',
iconMapping: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/icon-atlas.json',
pickable: true
});
return <DeckGL
initialViewState={{
longitude: -122.4,
latitude: 37.74,
zoom: 11
}}
controller
getTooltip={({object}: PickingInfo<BartStation>) => object && object.name}
layers={[layer]}
/>;
}
Example: auto packing iconAtlas
In some use cases, it is not possible to know the icons that will be used. Instead, each icon needs to be fetched from
a programmatically generated URL at runtime. For example, if you want to visualize avatars of github contributors for
a project on a map, it is not convenient for you to generate the iconAtlas with all the contributors' avatars.
In this case, you can follow this example. Auto packing icons is less efficient than pre-packed.
- JavaScript
- TypeScript
- React
import {Deck} from '@deck.gl/core';
import {IconLayer} from '@deck.gl/layers';
import {Octokit} from '@octokit/rest';
const octokit = new Octokit();
const layer = new IconLayer<User>({
id: 'IconLayer',
data: octokit.repos.getContributors({owner: 'visgl', repo: 'deck.gl'}),
dataTransform: result => result.data,
getIcon: d => ({
url: d.avatar_url,
width: 128,
height: 128
}),
getPosition: (d, {index}) => [index * 100, Math.sqrt(d.contributions) * 10, 0],
getSize: 40,
pickable: true
});
new Deck({
views: new OrthographicView(),
initialViewState: {
target: [0, 0, 0],
zoom: 0
},
controller: true,
getTooltip: ({object}) => object && `${object.login}`,
layers: [layer]
});
import {Deck, OrthographicView, PickingInfo} from '@deck.gl/core';
import {IconLayer} from '@deck.gl/layers';
import {Octokit} from '@octokit/rest';
const octokit = new Octokit();
// https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#list-repository-contributors
type User = {
id: number;
login: string;
avatar_url: string;
contributions: number;
};
const layer = new IconLayer<User>({
id: 'IconLayer',
data: octokit.repos.getContributors({owner: 'visgl', repo: 'deck.gl'}),
dataTransform: result => result.data,
getIcon: (d: User) => ({
url: d.avatar_url,
width: 128,
height: 128
}),
getPosition: (d: User, {index}) => [index * 100, Math.sqrt(d.contributions) * 10, 0],
getSize: 40,
pickable: true
});
new Deck({
views: new OrthographicView(),
initialViewState: {
target: [0, 0, 0],
zoom: 0
},
controller: true,
getTooltip: ({object}: PickingInfo<User>) => object && `${object.login}`,
layers: [layer]
});
import React from 'react';
import {DeckGL} from '@deck.gl/react';
import {IconLayer} from '@deck.gl/layers';
import type {PickingInfo} from '@deck.gl/core';
import {Octokit} from '@octokit/rest';
const octokit = new Octokit();
// https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#list-repository-contributors
type User = {
id: number;
login: string;
avatar_url: string;
contributions: number;
};
function App() {
const layer = new IconLayer<User>({
id: 'IconLayer',
data: octokit.repos.getContributors({owner: 'visgl', repo: 'deck.gl'}),
dataTransform: result => result.data,
getIcon: (d: User) => ({
url: d.avatar_url,
width: 128,
height: 128
}),
getPosition: (d: User, {index}) => [index * 100, Math.sqrt(d.contributions) * 10, 0],
getSize: 40,
pickable: true
});
return <DeckGL
initialViewState={{
longitude: -122.4,
latitude: 37.74,
zoom: 11
}}
controller
getTooltip={({object}: PickingInfo<User>) => object && `${object.login}`}
layers={[layer]}
/>;
}
Installation
To install the dependencies from NPM:
npm install deck.gl
# or
npm install @deck.gl/core @deck.gl/layers
import {IconLayer} from '@deck.gl/layers';
import type {IconLayerProps} from '@deck.gl/layers';
new IconLayer<DataT>(...props: IconLayerProps<DataT>[]);
To use pre-bundled scripts:
<script src="https://unpkg.com/deck.gl@^9.0.0/dist.min.js"></script>
<!-- or -->
<script src="https://unpkg.com/@deck.gl/core@^9.0.0/dist.min.js"></script>
<script src="https://unpkg.com/@deck.gl/layers@^9.0.0/dist.min.js"></script>
new deck.IconLayer({});
Properties
Inherits from all Base Layer properties.
iconAtlas (string | Texture | Image | ImageData | HTMLCanvasElement | HTMLVideoElement | ImageBitmap | Promise | object, optional)
A pre-packed image that contains all icons.
- If a string is supplied, it is interpreted as a URL or a Data URL.
- One of the following, or a Promise that resolves to one of the following:
- One of the valid pixel sources for WebGL2 texture
- A luma.gl Texture instance
- A plain object that can be passed to the
Textureconstructor, e.g.{width: <number>, height: <number>, data: <Uint8Array>}. Note that whenever this object shallowly changes, a new texture will be created.
The image data will be converted to a Texture object. See textureParameters prop for advanced customization.
If you go with pre-packed strategy, this prop is required.
If you choose to use auto packing, this prop should be left empty.
iconMapping (object | string, optional)
Icon names mapped to icon definitions, or a URL to load such mapping from a JSON file. Each icon is defined with the following values:
x(number, required): x position of icon on the atlas imagey(number, required): y position of icon on the atlas imagewidth(number, required): width of icon on the atlas imageheight(number, required): height of icon on the atlas imageanchorX(number, optional): horizontal position of icon anchor. Default: half width.anchorY(number, optional): vertical position of icon anchor. Default: half height.mask(boolean, optional): whether icon is treated as a transparency mask. Iftrue, user defined color is applied. Iffalse, pixel color from the image is applied. User still can specify the opacity through getColor. Default:false
If you go with pre-packed strategy, this prop is required.
If you choose to use auto packing, this prop should be left empty.