npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@deck.gl-community/three

v9.4.2

Published

Three.js-powered layers for deck.gl

Readme

@deck.gl-community/three

NPM Version NPM Downloads WebGPU supported

A collection of deck.gl layers powered by Three.js, giving access to Three.js geometry primitives and scene graph tooling directly inside deck.gl visualisations.

TreeLayer is the first layer in this module — a fully parametric 3D tree renderer backed by Three.js BufferGeometry and rendered via deck.gl's SimpleMeshLayer.

Layers

| Layer | Description | |-------|-------------| | TreeLayer | Procedural 3D trees with 5 species silhouettes, season colours, and crop/fruit visualisation |


TreeLayer

Renders richly configurable 3D trees at geographic positions using procedural geometry generated with Three.js BufferGeometry primitives.

Features

  • 5 tree species / silhouettes: pine (tiered cones), oak (sphere), palm (ring-scarred trunk and pinnate fronds), birch (narrow oval), cherry (round sphere)
  • Organic canopy geometry: smooth low-frequency vertex jitter baked into each species mesh at init time — no runtime cost, no mesh gaps
  • Per-tree variety: position-derived random bearing and asymmetric XY scale give every instance a unique silhouette with zero extra draw calls
  • Parametric geometry: per-instance height, trunk-to-canopy ratio, trunk radius, canopy radius
  • Season-driven colours: spring / summer / autumn / winter palettes with species-specific defaults
  • Explicit colour overrides: getTrunkColor and getCanopyColor accessors for full control
  • Pine tier density: getBranchLevels (1–5) controls the number of overlapping cone tiers; each tier drifts progressively for a windswept look
  • Crop / fruit / flower visualisation: getCrop places coloured spheres in the outer canopy volume and scattered on the ground beneath the tree
  • Global scale factor: sizeScale multiplier for easy zoom-level adjustment

Install

npm install @deck.gl-community/three
# or
yarn add @deck.gl-community/three

Three.js is a peer dependency pulled in automatically.

Usage

import {TreeLayer} from '@deck.gl-community/three';
import type {CropConfig} from '@deck.gl-community/three';

const layer = new TreeLayer({
  id: 'trees',
  data: myForestData,
  getPosition: d => d.coordinates,
  getTreeType: d => d.species,        // 'pine' | 'oak' | 'palm' | 'birch' | 'cherry'
  getHeight: d => d.heightMetres,
  getTrunkRadius: d => d.trunkRadius,
  getCanopyRadius: d => d.canopyRadius,
  getTrunkHeightFraction: d => 0.35,
  getSeason: d => 'autumn',
  getCrop: d => d.crop,               // CropConfig | null
  sizeScale: 1,
  pickable: true,
});

Crop / fruit / flower example

import type {CropConfig} from '@deck.gl-community/three';

// Orange orchard
const citrusCrop: CropConfig = {
  color: [255, 140, 0, 255],  // orange
  count: 30,                  // live fruits in canopy
  droppedCount: 10,           // fallen fruits on ground (rendered at 45% opacity)
  radius: 0.12,               // metres per fruit sphere (scaled by sizeScale)
};

// Cherry blossom (flowering stage — just use flower colour)
const blossomCrop: CropConfig = {
  color: [255, 200, 220, 200],
  count: 25,
  droppedCount: 8,
  radius: 0.07,
};

Crop positions are seeded deterministically from each tree's geographic coordinates, so they are stable across re-renders and sizeScale changes.


TreeLayer Props

Geometry

| Prop | Type | Default | Description | |------|------|---------|-------------| | getPosition | accessor → [lon, lat] | d.position | Tree base position | | getElevation | accessor → number | 0 | Base elevation in metres | | getTreeType | accessor → TreeType | 'pine' | Silhouette variant | | getHeight | accessor → number | 10 | Total height (metres) | | getTrunkHeightFraction | accessor → number | 0.35 | Fraction of total height occupied by trunk (0–1) | | getTrunkRadius | accessor → number | 0.5 | Trunk base radius (metres) | | getCanopyRadius | accessor → number | 3 | Canopy horizontal radius (metres) | | getBranchLevels | accessor → number | 3 | Pine tier count (1–5) | | sizeScale | number | 1 | Global size multiplier applied to all dimensions |

Colour

| Prop | Type | Default | Description | |------|------|---------|-------------| | getTrunkColor | accessor → Color\|null | null | Explicit trunk RGBA; null uses species default | | getCanopyColor | accessor → Color\|null | null | Explicit canopy RGBA; null uses season default | | getSeason | accessor → Season | 'summer' | Drives default canopy colour when no explicit colour is given |

Crops

| Prop | Type | Default | Description | |------|------|---------|-------------| | getCrop | accessor → CropConfig\|null | null | Crop configuration per tree. null renders no crops |


Types

TreeType

type TreeType = 'pine' | 'oak' | 'palm' | 'birch' | 'cherry';

Season

type Season = 'spring' | 'summer' | 'autumn' | 'winter';

CropConfig

Configuration for crop/fruit/flower visualisation on a single tree.

type CropConfig = {
  /** Colour of each crop sphere [r, g, b, a]. */
  color: Color;

  /** Number of crop spheres placed in the outer canopy volume (live / in-tree). */
  count: number;

  /**
   * Number of crop spheres scattered on the ground within the canopy footprint
   * (dropped / fallen). Rendered at ~45 % opacity relative to `color`.
   * @default 0
   */
  droppedCount?: number;

  /**
   * Radius of each individual crop sphere in metres (scaled by `sizeScale`).
   * Typical values: 0.06–0.15 m for fruit, 0.05–0.10 m for nuts/blossoms.
   */
  radius: number;
};

Crop placement details

  • Live crops are placed on the outer 90–102 % of the canopy ellipsoid surface (equatorial band only — never on the crown or base) so they appear nestled into the canopy with tips just visible.
  • Dropped crops are scattered uniformly across the ground disk within the canopy footprint at a fixed slight elevation (0.05 m), rendered semi-transparent.
  • All positions are derived deterministically from the tree's geographic coordinates via a seeded PRNG, so they are stable across re-renders and sizeScale changes.

Default canopy colours

| Species | Spring | Summer | Autumn | Winter | |---------|--------|--------|--------|--------| | pine | [34, 100, 34] | [0, 64, 0] | [0, 64, 0] | [0, 55, 0] | | oak | [100, 180, 80] | [34, 120, 15] | [180, 85, 20] | [100, 80, 60] (α 160) | | palm | [50, 160, 50] | [20, 145, 20] | [55, 150, 30] | [40, 130, 30] | | birch | [150, 210, 110] | [80, 160, 60] | [230, 185, 40] | [180, 180, 170] (α 90) | | cherry | [255, 180, 205] | [50, 140, 50] | [200, 60, 40] | [120, 90, 80] (α 110) |


Seasonal Farm example

Explore seven labelled plots with seasonal trees and hover details in the Seasonal Farm demo. See the example README for setup and data details.