Layers

DeckGL.jl provides a variety of layer types for different visualization needs. Each example below is self-contained and ready to copy-paste.

Core Layers

Core layers render individual data points directly without aggregation.

ScatterplotLayer

Renders circles at given coordinates.

data = (
    lng = [-122.45, -122.42, -122.38, -122.50, -122.47, -122.41],
    lat = [37.78, 37.76, 37.79, 37.77, 37.80, 37.75],
    size = [80, 200, 120, 300, 150, 250]
)

Deck(
    ScatterplotLayer(
        data = data,
        get_position = [:lng, :lat],
        get_radius = :size,
        get_fill_color = [255, 140, 0, 200],
        radius_min_pixels = 3
    ),
    initial_view_state = ViewState(longitude=-122.44, latitude=37.77, zoom=12)
)
Property Type Default Description
data Any required Tables.jl-compatible data source
get_position Symbol/Vector{Symbol} required Position accessor [:lng, :lat]
get_radius Real/Symbol 1 Circle radius in meters
get_fill_color Vector/Symbol [0,0,0,255] Fill color RGBA
get_line_color Vector/Symbol [0,0,0,255] Outline color RGBA
get_line_width Real/Symbol 1 Outline width
radius_scale Real 1 Radius multiplier
radius_min_pixels Real 0 Minimum radius in pixels
radius_max_pixels Real Inf Maximum radius in pixels
stroked Bool false Draw outline
filled Bool true Draw fill
billboard Bool false Always face camera
opacity Real 1 Layer opacity (0-1)
pickable Bool false Enable interactions

ArcLayer

Renders arcs between source and target coordinates.

trips = (
    src_lng = [-122.45, -122.50, -122.42],
    src_lat = [37.78,   37.77,   37.76],
    dst_lng = [-122.38, -122.41, -122.47],
    dst_lat = [37.79,   37.75,   37.80]
)

Deck(
    ArcLayer(
        data = trips,
        get_source_position = [:src_lng, :src_lat],
        get_target_position = [:dst_lng, :dst_lat],
        get_source_color = [0, 128, 255],
        get_target_color = [255, 0, 128],
        get_width = 3
    ),
    initial_view_state = ViewState(longitude=-122.44, latitude=37.77, zoom=12)
)
Property Type Default Description
data Any required Tables.jl-compatible data source
get_source_position Symbol/Vector{Symbol} required Source position
get_target_position Symbol/Vector{Symbol} required Target position
get_source_color Vector/Symbol [0,0,0,255] Source end color
get_target_color Vector/Symbol [0,0,0,255] Target end color
get_width Real/Symbol 1 Arc width in pixels
get_height Real/Symbol 1 Arc height multiplier (0-1)
get_tilt Real/Symbol 0 Arc tilt in degrees
great_circle Bool false Use great circle arcs
width_scale Real 1 Width multiplier
opacity Real 1 Layer opacity (0-1)

LineLayer

Renders straight lines between source and target coordinates.

connections = (
    from_lng = [-122.45, -122.50, -122.42, -122.48],
    from_lat = [37.78,   37.77,   37.76,   37.79],
    to_lng   = [-122.38, -122.41, -122.47, -122.43],
    to_lat   = [37.79,   37.75,   37.80,   37.74]
)

Deck(
    LineLayer(
        data = connections,
        get_source_position = [:from_lng, :from_lat],
        get_target_position = [:to_lng, :to_lat],
        get_color = [255, 0, 0],
        get_width = 2
    ),
    initial_view_state = ViewState(longitude=-122.44, latitude=37.77, zoom=12)
)
Property Type Default Description
data Any required Tables.jl-compatible data source
get_source_position Symbol/Vector{Symbol} required Source position
get_target_position Symbol/Vector{Symbol} required Target position
get_color Vector/Symbol [0,0,0,255] Line color
get_width Real/Symbol 1 Line width
width_units String "pixels" Width units
opacity Real 1 Layer opacity (0-1)

PathLayer

Renders paths/polylines from coordinate sequences.

routes = (
    path = [
        [[-122.45, 37.78], [-122.43, 37.79], [-122.40, 37.78], [-122.38, 37.79]],
        [[-122.50, 37.77], [-122.48, 37.76], [-122.45, 37.75], [-122.42, 37.76]],
        [[-122.47, 37.80], [-122.44, 37.81], [-122.41, 37.80], [-122.39, 37.81]]
    ],
)

Deck(
    PathLayer(
        data = routes,
        get_path = :path,
        get_color = [0, 128, 255],
        get_width = 5,
        cap_rounded = true,
        joint_rounded = true
    ),
    initial_view_state = ViewState(longitude=-122.44, latitude=37.78, zoom=12)
)
Property Type Default Description
data Any required Tables.jl-compatible data source
get_path Symbol required Path coordinates column
get_color Vector/Symbol [0,0,0,255] Path color
get_width Real/Symbol 1 Path width
cap_rounded Bool false Round line caps
joint_rounded Bool false Round line joints
billboard Bool false Always face camera
miter_limit Real 4 Miter limit for sharp corners
opacity Real 1 Layer opacity (0-1)

PolygonLayer

Renders filled and/or stroked polygons.

regions = (
    polygon = [
        [[-122.46, 37.78], [-122.44, 37.78], [-122.44, 37.80], [-122.46, 37.80], [-122.46, 37.78]],
        [[-122.43, 37.76], [-122.40, 37.76], [-122.40, 37.78], [-122.43, 37.78], [-122.43, 37.76]],
        [[-122.48, 37.74], [-122.45, 37.74], [-122.45, 37.76], [-122.48, 37.76], [-122.48, 37.74]]
    ],
    value = [500, 1200, 800]
)

Deck(
    PolygonLayer(
        data = regions,
        get_polygon = :polygon,
        get_fill_color = [255, 140, 0, 100],
        get_line_color = [255, 140, 0, 255],
        get_line_width = 2,
        extruded = true,
        get_elevation = :value,
        elevation_scale = 1
    ),
    initial_view_state = ViewState(longitude=-122.44, latitude=37.77, zoom=12, pitch=45)
)
Property Type Default Description
data Any required Tables.jl-compatible data source
get_polygon Symbol required Polygon coordinates column
get_fill_color Vector/Symbol [0,0,0,255] Fill color
get_line_color Vector/Symbol [0,0,0,255] Outline color
get_line_width Real/Symbol 1 Outline width
filled Bool true Draw fill
stroked Bool true Draw outline
extruded Bool false Extrude as 3D
wireframe Bool false Draw 3D wireframe
get_elevation Real/Symbol 1000 Polygon height for 3D
elevation_scale Real 1 Elevation multiplier
opacity Real 1 Layer opacity (0-1)

TextLayer

Renders text labels at coordinates.

cities = (
    lng  = [-122.42, -122.47, -122.39, -122.50, -122.44],
    lat  = [37.78,   37.76,   37.79,   37.77,   37.75],
    name = ["Downtown", "Sunset", "Marina", "Richmond", "Mission"]
)

Deck(
    TextLayer(
        data = cities,
        get_position = [:lng, :lat],
        get_text = :name,
        get_size = 18,
        get_color = [0, 0, 128],
        font_family = "Helvetica, Arial, sans-serif",
        background = true,
        get_background_color = [255, 255, 255, 200]
    ),
    initial_view_state = ViewState(longitude=-122.44, latitude=37.77, zoom=12)
)
Property Type Default Description
data Any required Tables.jl-compatible data source
get_position Symbol/Vector{Symbol} required Position accessor
get_text Symbol required Text content column
get_size Real/Symbol 32 Text size in pixels
get_color Vector/Symbol [0,0,0,255] Text color
get_angle Real/Symbol 0 Rotation in degrees
get_text_anchor String "middle" Horizontal anchor
get_alignment_baseline String "center" Vertical anchor
font_family String "Monaco, monospace" Font family
billboard Bool true Always face camera
background Bool false Draw background
opacity Real 1 Layer opacity (0-1)

Aggregation Layers

Aggregation layers bin data points and render aggregated values.

HexagonLayer

Aggregates data into hexagonal bins and renders as 3D hexagons.

# Generate random earthquake-like data around San Francisco
earthquakes = let
    n = 200
    (
        lng = -122.4 .+ 0.2 * randn(n),
        lat = 37.8 .+ 0.15 * randn(n),
        magnitude = 1.0 .+ 3.0 * rand(n)
    )
end

Deck(
    HexagonLayer(
        data = earthquakes,
        get_position = [:lng, :lat],
        get_elevation_weight = :magnitude,
        radius = 500,
        elevation_scale = 50,
        extruded = true,
        coverage = 0.9
    ),
    initial_view_state = ViewState(longitude=-122.4, latitude=37.8, zoom=11, pitch=45)
)
Property Type Default Description
data Any required Tables.jl-compatible data source
get_position Symbol/Vector{Symbol} required Position accessor
radius Real 1000 Hexagon radius in meters
coverage Real 1 Hexagon coverage (0-1)
extruded Bool true Render as 3D
elevation_scale Real 1 Elevation multiplier
elevation_range Vector [0, 1000] Min/max elevation
get_color_weight Real/Symbol 1 Color aggregation weight
get_elevation_weight Real/Symbol 1 Elevation aggregation weight
color_aggregation String "SUM" Aggregation method
elevation_aggregation String "SUM" Aggregation method
color_range Vector yellow-red scale Color gradient
upper_percentile Real 100 Upper filter percentile
lower_percentile Real 0 Lower filter percentile
opacity Real 1 Layer opacity (0-1)

GridLayer

Aggregates data into rectangular grid cells.

# Generate random points around San Francisco
points = let
    n = 300
    (
        lng = -122.4 .+ 0.15 * randn(n),
        lat = 37.8 .+ 0.1 * randn(n),
    )
end

Deck(
    GridLayer(
        data = points,
        get_position = [:lng, :lat],
        cell_size = 400,
        elevation_scale = 10,
        extruded = true,
        coverage = 0.8
    ),
    initial_view_state = ViewState(longitude=-122.4, latitude=37.8, zoom=11, pitch=45)
)
Property Type Default Description
data Any required Tables.jl-compatible data source
get_position Symbol/Vector{Symbol} required Position accessor
cell_size Real 1000 Grid cell size in meters
coverage Real 1 Cell coverage (0-1)
extruded Bool true Render as 3D
elevation_scale Real 1 Elevation multiplier
get_color_weight Real/Symbol 1 Color aggregation weight
get_elevation_weight Real/Symbol 1 Elevation aggregation weight
color_aggregation String "SUM" Aggregation method
elevation_aggregation String "SUM" Aggregation method
opacity Real 1 Layer opacity (0-1)

HeatmapLayer

Renders a heatmap based on point density and weights.

# Generate clustered incident data
incidents = let
    n = 500
    # Two clusters
    lng1 = -122.45 .+ 0.03 * randn(n ÷ 2)
    lat1 = 37.78 .+ 0.02 * randn(n ÷ 2)
    lng2 = -122.40 .+ 0.02 * randn(n ÷ 2)
    lat2 = 37.76 .+ 0.015 * randn(n ÷ 2)
    (
        lng = vcat(lng1, lng2),
        lat = vcat(lat1, lat2),
        severity = 1.0 .+ 4.0 * rand(n)
    )
end

Deck(
    HeatmapLayer(
        data = incidents,
        get_position = [:lng, :lat],
        get_weight = :severity,
        radius_pixels = 50,
        intensity = 1,
        threshold = 0.03
    ),
    initial_view_state = ViewState(longitude=-122.43, latitude=37.77, zoom=12)
)
Property Type Default Description
data Any required Tables.jl-compatible data source
get_position Symbol/Vector{Symbol} required Position accessor
radius_pixels Real 30 Radius of influence in pixels
intensity Real 1 Intensity multiplier
threshold Real 0.05 Minimum density threshold
get_weight Real/Symbol 1 Point weight
color_range Vector blue-green-yellow-red Color gradient
aggregation String "SUM" Aggregation method
opacity Real 1 Layer opacity (0-1)

Composite Layers

Composite layers render complex data types using multiple sub-layers.

GeoJsonLayer

Renders GeoJSON data as points, lines, and polygons.

geojson_data = Dict(
    "type" => "FeatureCollection",
    "features" => [
        Dict(
            "type" => "Feature",
            "geometry" => Dict(
                "type" => "Polygon",
                "coordinates" => [[
                    [-122.46, 37.78], [-122.44, 37.78], [-122.44, 37.80],
                    [-122.46, 37.80], [-122.46, 37.78]
                ]]
            ),
            "properties" => Dict("name" => "Area A")
        ),
        Dict(
            "type" => "Feature",
            "geometry" => Dict(
                "type" => "Point",
                "coordinates" => [-122.42, 37.77]
            ),
            "properties" => Dict("name" => "Point B")
        ),
        Dict(
            "type" => "Feature",
            "geometry" => Dict(
                "type" => "LineString",
                "coordinates" => [
                    [-122.48, 37.76], [-122.45, 37.75], [-122.42, 37.76]
                ]
            ),
            "properties" => Dict("name" => "Route C")
        )
    ]
)

Deck(
    GeoJsonLayer(
        data = geojson_data,
        get_fill_color = [0, 100, 200, 100],
        get_line_color = [0, 100, 200, 255],
        get_line_width = 3,
        get_point_radius = 200,
        line_width_min_pixels = 2
    ),
    initial_view_state = ViewState(longitude=-122.44, latitude=37.77, zoom=12)
)
Property Type Default Description
data Dict/String required GeoJSON Dict or URL
filled Bool true Fill polygons
stroked Bool true Draw outlines
extruded Bool false Extrude polygons
get_fill_color Vector/Symbol [0,0,0,255] Fill color
get_line_color Vector/Symbol [0,0,0,255] Line color
get_line_width Real/Symbol 1 Line width
get_point_radius Real/Symbol 1 Point radius
get_elevation Real/Symbol 1000 Polygon elevation
point_type String "circle" Point rendering type
opacity Real 1 Layer opacity (0-1)

GeoInterface.jl Integration

Convert GeoInterface-compatible geometries to GeoJSON:

using Shapefile
using DeckGL

# Load shapefile
shp = Shapefile.Table("boundaries.shp")

# Convert to GeoJSON and create layer
layer = geojson_layer(shp, get_fill_color=[255, 0, 0, 100])

# Or manually convert
geojson_dict = to_geojson(shp)
layer = GeoJsonLayer(data=geojson_dict)

Supported geometry types:

  • Point, MultiPoint
  • LineString, MultiLineString
  • Polygon, MultiPolygon
  • GeometryCollection
  • Feature, FeatureCollection