Examples

Interactive examples demonstrating each DeckGL.jl layer type. Each visualization is generated by DeckGL.jl and rendered using deck.gl.

ScatterplotLayer

Renders circles at geographic coordinates. Size and color can be data-driven.

data = (
    lng = [-122.4, -122.45, -122.35, -122.42, -122.38, -122.41, -122.43, -122.39],
    lat = [37.8, 37.75, 37.85, 37.78, 37.82, 37.79, 37.81, 37.77],
    size = [100, 150, 80, 120, 90, 110, 95, 130]
)

layer = ScatterplotLayer(
    data = data,
    get_position = [:lng, :lat],
    get_radius = :size,
    get_fill_color = [255, 140, 0, 200],
    radius_min_pixels = 5,
    radius_max_pixels = 50
)

Deck(layer, initial_view_state = ViewState(longitude=-122.4, latitude=37.8, zoom=12))

ArcLayer

Renders arcs between source and target coordinates. Great for showing connections or flows.

trips = (
    src_lng = [-122.4, -122.4, -122.4, -73.9, -87.6],
    src_lat = [37.8, 37.8, 37.8, 40.7, 41.9],
    dst_lng = [-73.9, -87.6, -118.2, -87.6, -118.2],
    dst_lat = [40.7, 41.9, 34.0, 41.9, 34.0]
)

layer = 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
)

Deck(layer, initial_view_state = ViewState(longitude=-98, latitude=39, zoom=3, pitch=30))

LineLayer

Renders straight lines between points. Simpler than arcs, useful for direct connections.

connections = (
    from_lng = [-122.4, -122.45, -122.35, -122.42, -122.38],
    from_lat = [37.8, 37.75, 37.85, 37.78, 37.82],
    to_lng = [-122.45, -122.35, -122.4, -122.38, -122.43],
    to_lat = [37.75, 37.85, 37.8, 37.82, 37.77]
)

layer = LineLayer(
    data = connections,
    get_source_position = [:from_lng, :from_lat],
    get_target_position = [:to_lng, :to_lat],
    get_color = [64, 192, 128, 200],
    get_width = 3
)

Deck(layer, initial_view_state = ViewState(longitude=-122.4, latitude=37.8, zoom=12))

PathLayer

Renders polylines/paths from sequences of coordinates. Ideal for routes, tracks, or boundaries.

routes = (
    path = [
        [[-122.4, 37.8], [-122.42, 37.78], [-122.44, 37.76], [-122.45, 37.75]],
        [[-122.35, 37.85], [-122.37, 37.83], [-122.39, 37.81], [-122.4, 37.8]],
        [[-122.43, 37.82], [-122.41, 37.79], [-122.38, 37.77], [-122.36, 37.76]]
    ],
    color = [[0, 128, 255], [255, 128, 0], [128, 0, 255]]
)

layer = PathLayer(
    data = routes,
    get_path = :path,
    get_color = :color,
    get_width = 5,
    cap_rounded = true,
    joint_rounded = true
)

Deck(layer, initial_view_state = ViewState(longitude=-122.4, latitude=37.8, zoom=12))

PolygonLayer

Renders filled polygons. Supports 3D extrusion for building-like visualizations.

regions = (
    polygon = [
        [[-122.42, 37.78], [-122.44, 37.76], [-122.42, 37.74], [-122.40, 37.76]],
        [[-122.38, 37.82], [-122.40, 37.80], [-122.37, 37.79], [-122.35, 37.81]],
        [[-122.45, 37.80], [-122.47, 37.78], [-122.45, 37.76], [-122.43, 37.78]]
    ],
    height = [200, 300, 150],
    color = [[255, 140, 0, 180], [0, 140, 255, 180], [140, 255, 0, 180]]
)

layer = PolygonLayer(
    data = regions,
    get_polygon = :polygon,
    get_fill_color = :color,
    get_line_color = [80, 80, 80],
    extruded = true,
    get_elevation = :height,
    elevation_scale = 10
)

Deck(layer, initial_view_state = ViewState(longitude=-122.4, latitude=37.78, zoom=12, pitch=45, bearing=15))

TextLayer

Renders text labels at geographic coordinates.

cities = (
    lng = [-122.4, -122.45, -122.35, -122.42, -122.38],
    lat = [37.8, 37.75, 37.85, 37.77, 37.82],
    name = ["Downtown SF", "Daly City", "Berkeley", "Mission", "Marina"],
    size = [20, 16, 16, 14, 14]
)

points_layer = ScatterplotLayer(
    data = cities,
    get_position = [:lng, :lat],
    get_radius = 100,
    get_fill_color = [255, 0, 0, 200],
    radius_min_pixels = 5
)

text_layer = TextLayer(
    data = cities,
    get_position = [:lng, :lat],
    get_text = :name,
    get_size = :size,
    get_color = [0, 0, 0, 255],
    get_pixel_offset = [0, -20]
)

Deck([points_layer, text_layer], initial_view_state = ViewState(longitude=-122.4, latitude=37.8, zoom=11))

HexagonLayer

Aggregates points into hexagonal bins. Height represents density or aggregated values.

using Random
Random.seed!(42)

# Generate clustered point data
points_data = let
    lngs = Float64[]
    lats = Float64[]
    clusters = [(-122.4, 37.8, 500), (-122.45, 37.75, 300), (-122.35, 37.82, 400)]
    for (cx, cy, n) in clusters
        append!(lngs, cx .+ 0.025 .* randn(n))
        append!(lats, cy .+ 0.025 .* randn(n))
    end
    (lng = lngs, lat = lats)
end

layer = HexagonLayer(
    data = points_data,
    get_position = [:lng, :lat],
    radius = 200,
    elevation_scale = 50,
    elevation_range = [0, 500],
    extruded = true,
    coverage = 0.9
)

Deck(layer, initial_view_state = ViewState(longitude=-122.4, latitude=37.8, zoom=11, pitch=45, bearing=15))

GridLayer

Similar to HexagonLayer but uses rectangular grid cells.

Random.seed!(123)

grid_data = let
    lngs = Float64[]
    lats = Float64[]
    centers = [(-122.4, 37.8), (-122.45, 37.76), (-122.35, 37.83)]
    for _ in 1:1000
        cx, cy = centers[rand(1:3)]
        push!(lngs, cx + (rand() - 0.5) * 0.04)
        push!(lats, cy + (rand() - 0.5) * 0.04)
    end
    (lng = lngs, lat = lats)
end

layer = GridLayer(
    data = grid_data,
    get_position = [:lng, :lat],
    cell_size = 200,
    elevation_scale = 50,
    elevation_range = [0, 300],
    extruded = true,
    coverage = 0.9
)

Deck(layer, initial_view_state = ViewState(longitude=-122.4, latitude=37.8, zoom=11, pitch=45, bearing=-15))

HeatmapLayer

Renders a smooth density heatmap. Great for visualizing point density.

Random.seed!(456)

heatmap_data = let
    lngs = Float64[]
    lats = Float64[]
    weights = Float64[]
    clusters = [(-122.41, 37.79, 2000), (-122.43, 37.77, 1500), (-122.38, 37.81, 1200), (-122.45, 37.75, 800)]
    for (cx, cy, n) in clusters
        for _ in 1:n
            push!(lngs, cx + (rand() - 0.5) * 0.03)
            push!(lats, cy + (rand() - 0.5) * 0.03)
            push!(weights, rand())
        end
    end
    (lng = lngs, lat = lats, weight = weights)
end

layer = HeatmapLayer(
    data = heatmap_data,
    get_position = [:lng, :lat],
    get_weight = :weight,
    radius_pixels = 40,
    intensity = 1,
    threshold = 0.03
)

Deck(layer, initial_view_state = ViewState(longitude=-122.41, latitude=37.78, zoom=12))

GeoJsonLayer

Renders GeoJSON data including points, lines, and polygons.

geojson_data = Dict(
    "type" => "FeatureCollection",
    "features" => [
        Dict(
            "type" => "Feature",
            "geometry" => Dict(
                "type" => "Polygon",
                "coordinates" => [[[-122.45, 37.78], [-122.43, 37.75], [-122.40, 37.76], [-122.41, 37.79], [-122.45, 37.78]]]
            ),
            "properties" => Dict("name" => "Region A")
        ),
        Dict(
            "type" => "Feature",
            "geometry" => Dict(
                "type" => "Polygon",
                "coordinates" => [[[-122.40, 37.82], [-122.38, 37.80], [-122.35, 37.81], [-122.36, 37.84], [-122.40, 37.82]]]
            ),
            "properties" => Dict("name" => "Region B")
        ),
        Dict(
            "type" => "Feature",
            "geometry" => Dict(
                "type" => "LineString",
                "coordinates" => [[-122.45, 37.78], [-122.42, 37.80], [-122.40, 37.82]]
            ),
            "properties" => Dict("name" => "Route 1")
        ),
        Dict(
            "type" => "Feature",
            "geometry" => Dict("type" => "Point", "coordinates" => [-122.42, 37.78]),
            "properties" => Dict("name" => "Point A")
        ),
        Dict(
            "type" => "Feature",
            "geometry" => Dict("type" => "Point", "coordinates" => [-122.37, 37.82]),
            "properties" => Dict("name" => "Point B")
        )
    ]
)

layer = GeoJsonLayer(
    data = geojson_data,
    filled = true,
    stroked = true,
    get_fill_color = [255, 140, 0, 150],
    get_line_color = [0, 0, 0, 200],
    get_line_width = 2,
    get_point_radius = 200,
    line_width_min_pixels = 2,
    point_radius_min_pixels = 5
)

Deck(layer, initial_view_state = ViewState(longitude=-122.4, latitude=37.79, zoom=12))

Multiple Layers

Combine multiple layer types in a single visualization.

cities_multi = (
    lng = [-122.4, -122.27, -122.22],
    lat = [37.8, 37.87, 37.77],
    name = ["San Francisco", "Berkeley", "Oakland"],
    size = [300, 200, 250]
)

routes_multi = (
    path = [
        [[-122.4, 37.8], [-122.35, 37.82], [-122.27, 37.87]],
        [[-122.4, 37.8], [-122.32, 37.78], [-122.22, 37.77]],
        [[-122.27, 37.87], [-122.25, 37.82], [-122.22, 37.77]]
    ],
)

path_layer = PathLayer(
    data = routes_multi,
    get_path = :path,
    get_color = [100, 100, 100, 150],
    get_width = 3,
    cap_rounded = true
)

scatter_layer = ScatterplotLayer(
    data = cities_multi,
    get_position = [:lng, :lat],
    get_radius = :size,
    get_fill_color = [0, 128, 255, 200],
    radius_min_pixels = 10
)

label_layer = TextLayer(
    data = cities_multi,
    get_position = [:lng, :lat],
    get_text = :name,
    get_size = 16,
    get_color = [0, 0, 0],
    get_pixel_offset = [0, -30]
)

Deck([path_layer, scatter_layer, label_layer], initial_view_state = ViewState(longitude=-122.32, latitude=37.82, zoom=11))

Base Maps

Add a base map using the map_style parameter. DeckGL.jl supports any MapLibre-compatible tile source. Here are some free options:

  • OpenStreetMap: https://basemaps.cartocdn.com/gl/positron-gl-style/style.json
  • CartoDB Dark: https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json
  • CartoDB Voyager: https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json
airports = (
    lng = [-122.38, -73.78, -87.90, -118.41, -84.43],
    lat = [37.62, 40.64, 41.98, 33.94, 33.64],
    name = ["SFO", "JFK", "ORD", "LAX", "ATL"],
    passengers = [50, 60, 80, 85, 110]  # millions
)

layer = ScatterplotLayer(
    data = airports,
    get_position = [:lng, :lat],
    get_radius = :passengers,
    get_fill_color = [255, 0, 80, 180],
    radius_scale = 5000,
    radius_min_pixels = 5,
    pickable = true
)

Deck(
    layer,
    initial_view_state = ViewState(longitude=-98, latitude=38, zoom=3.5, pitch=0),
    map_style = "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json"
)

Dark Theme Base Map

The dark matter style works well for visualizations with bright colors.

earthquakes = (
    lng = [-122.0, -121.5, -117.5, -116.0, -118.2, -119.5, -122.5, -120.0],
    lat = [37.0, 36.5, 34.0, 33.5, 34.2, 35.0, 38.0, 35.5],
    magnitude = [3.2, 4.1, 5.5, 3.8, 4.5, 3.0, 4.8, 3.5]
)

layer = ScatterplotLayer(
    data = earthquakes,
    get_position = [:lng, :lat],
    get_radius = :magnitude,
    get_fill_color = [255, 200, 0, 200],
    radius_scale = 20000,
    radius_min_pixels = 3,
    pickable = true
)

Deck(
    layer,
    initial_view_state = ViewState(longitude=-119, latitude=36, zoom=5.5),
    map_style = "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"
)