Skip to content

Add-on packs ​

The library ships with indoor furniture and five indoor plants. Add-on packs add more items to the editor's furniture panel, the 2D viewer and the 3D viewer. Install only the packs you need: each one is its own npm package, and its 3D models load only when you use the 3D viewer.

Packs are included in your licence (free or commercial) at no extra cost. They work with all three packages: Vue, React and the HTML elements.

PackPackageContents
Garden@jbaysolutions/floorplan-pack-garden48 outdoor items: trees, shrubs and flowers, garden seating, shade and structures, garden features, pool accessories

The editor below has the garden pack registered. Click Garden in the toolbar (or press G) to open its panel, then drag a tree or a parasol into the garden.

Loading the live demo…

Using a pack ​

bash
npm install @jbaysolutions/floorplan-pack-garden

Register the pack once, before you mount your app or render the components (for example in main.ts). Import registerPack from the package you use:

ts
import { registerPack } from '@jbaysolutions/floorplan-vue'
import { garden } from '@jbaysolutions/floorplan-pack-garden'

registerPack(garden)
ts
import { registerPack } from '@jbaysolutions/floorplan-react'
import { garden } from '@jbaysolutions/floorplan-pack-garden'

registerPack(garden)
js
import { registerPack } from '@jbaysolutions/floorplan-elements'
import { garden } from '@jbaysolutions/floorplan-pack-garden'

registerPack(garden)

That's all the editor and the 2D viewer need. The editor's toolbar gets a button for the pack, below Furniture: the garden pack's is Garden (a tree icon, shortcut G). It opens the pack's own panel with its categories. Plans that contain the pack's items draw them with the pack's own symbols.

If you also use the 3D viewer, register the pack's 3D models too, with registerPack3D from the package's /3d entry:

ts
import { registerPack3D } from '@jbaysolutions/floorplan-vue/3d'
import { garden3D } from '@jbaysolutions/floorplan-pack-garden/3d'

registerPack3D(garden3D)
ts
import { registerPack3D } from '@jbaysolutions/floorplan-react/3d'
import { garden3D } from '@jbaysolutions/floorplan-pack-garden/3d'

registerPack3D(garden3D)
js
import { registerPack3D } from '@jbaysolutions/floorplan-elements/3d'
import { garden3D } from '@jbaysolutions/floorplan-pack-garden/3d'

registerPack3D(garden3D)

The 2D part (@jbaysolutions/floorplan-pack-garden) never imports three.js. Only the /3d part does.

Register with the package you render with

Each package has its own registry. Call registerPack and registerPack3D from the same package as your components: the React components and the HTML elements don't see packs registered through @jbaysolutions/floorplan-vue.

Pack items in the plan ​

A pack item is ordinary furniture whose kind is namespaced by its pack:

ts
{ id: 'f1', kind: 'garden/oak', x: 230, y: 1440, width: 420, depth: 420, rotation: 0 }

Sizes work like any other furniture. Trees, shrubs and other plants grow taller as you make them wider, and benches, sheds and other built items keep their height. As with the built-in plants, every tree and shrub is slightly different (based on its id) and always looks the same.

If a plan uses a pack you haven't registered, nothing breaks. The item keeps its place and size and shows as a placeholder: a dashed outline in 2D and a plain block in 3D. Register the pack and it appears properly.

The hotel's grounds are planted with garden-pack trees, hedges and furniture:

Loading the live demo…

The garden pack ​

Item kinds are garden/<key>. Sizes are the defaults in cm (width × depth).

Trees

KeyItemSize
oakOak650 × 650
birchBirch300 × 300
spruceSpruce550 × 550
cypressItalian cypress160 × 160
date-palmDate palm600 × 600
oliveOlive tree550 × 500
cherryCherry blossom680 × 680
willowWeeping willow640 × 640
mapleJapanese maple500 × 500
appleApple tree480 × 480

A tree's size is its crown spread. Its height follows: the default oak is about 7 m tall, and the cypress about 10 m.

Shrubs & flowers: hedge (clipped hedge, 254 × 84), topiary (topiary cone, 85 × 85), lavender (125 × 125), hydrangea (160 × 160), rose (rose bush, 90 × 90), vegetable-bed (240 × 100), tulip-planter (121 × 42).

Garden seating: park-bench (180 × 73), modern-bench (204 × 45), picnic-table (180 × 150), bistro-set (163 × 70), dining-set (teak dining set for six, 303 × 191), adirondack (adirondack chair, 89 × 97), sun-lounger (74 × 201), lounge-sofa (220 × 90), egg-chair (hanging egg chair, 90 × 101), hammock (352 × 118).

Shade & structures: parasol (300 × 300), cantilever-parasol (360 × 300), pergola (pergola with wisteria, 390 × 360), gazebo (416 × 480), shed (garden shed, 274 × 213), greenhouse (303 × 223).

Garden features: fountain (250 × 250), bird-bath (72 × 72), fire-pit (143 × 143), barbecue (kettle barbecue, 67 × 76), lamp-post (48 × 48), bollard (bollard light, 20 × 20), stepping-stones (445 × 140), swing-set (310 × 166), trampoline (368 × 368), bike-rack (75 × 245).

Pool: pool-ladder (68 × 71), diving-board (70 × 405), hot-tub (224 × 264), outdoor-shower (90 × 90), pool-lounger (76 × 173). The ladder and diving board stand on the edge with their back on the deck (−y at rotation 0) and reach over the water. Pools themselves are areas: see swimming pools.

Like all furniture, an item's back faces −y (the top of the plan) at rotation 0: the back of a bench, the head of a sun lounger, the door of the shed faces +y.

Making your own pack ​

You can register your own items in the same way, for example your company's products or equipment. A pack is plain data and functions, so the same pack works with every package. Only the imports change:

ts
import { registerPack, type FurniturePack } from '@jbaysolutions/floorplan-vue'
import { registerPack3D, type FurniturePack3D } from '@jbaysolutions/floorplan-vue/3d'
ts
import { registerPack, type FurniturePack } from '@jbaysolutions/floorplan-react'
import { registerPack3D, type FurniturePack3D } from '@jbaysolutions/floorplan-react/3d'
ts
import { registerPack, type FurniturePack } from '@jbaysolutions/floorplan-elements'
import { registerPack3D, type FurniturePack3D } from '@jbaysolutions/floorplan-elements/3d'

2D: catalogue entries and symbols ​

ts
const acme: FurniturePack = {
  name: 'acme', // namespace: kinds start with 'acme/'
  label: 'Acme', // the editor's button and panel
  icon: 'M4 4h16v16H4z M9 9h6v6H9z', // 24 × 24 path data, drawn as a line icon
  key: 'A', // optional shortcut; avoid V H W R D N F E, which the editor uses
  items: [
    {
      kind: 'acme/charger',
      label: 'EV charger',
      category: 'Acme',
      width: 40,
      depth: 30,
      // SVG markup centred on (0, 0), back towards −y, for an item of this width × depth
      symbol: (w, d) => `<rect class="fp-f" x="${-w / 2}" y="${-d / 2}" width="${w}" height="${d}" rx="4"/>
                         <circle class="fp-fire" r="${Math.min(w, d) / 5}"/>`,
    },
  ],
}

registerPack(acme)

Use the library's classes in symbols so they follow the theme: fp-f and fp-f2 (furniture fills), fp-fl (detail lines), fp-leaf, fp-leaf2, fp-leaf3, fp-leaf-line, fp-blade (plants), fp-canopy (see-through tree crowns), fp-flower, fp-flower-2, fp-bloom, fp-autumn, fp-fruit, fp-water, fp-fire, fp-glow, fp-soil, fp-tv (dark solid).

3D: models ​

ts
import * as THREE from 'three'

const acme3D: FurniturePack3D = {
  name: 'acme',
  models: [
    {
      kind: 'acme/charger',
      width: 40, // the size the model is built at
      depth: 30,
      build(group, ctx) {
        const body = new THREE.Mesh(new THREE.BoxGeometry(40, 120, 30), ctx.color('#2f3a4a'))
        body.position.y = 60
        group.add(body)
      },
    },
  ],
}

registerPack3D(acme3D)
  • Build in cm, with y up and the item's back towards −z.
  • Use ctx.color(hex, options) or ctx.theme(key) for materials. They adapt to the theme: darker in dark, x-ray in blueprint. options covers roughness, metalness, emissive, foliage, glass, water and opacity.
  • ctx.rnd() gives random numbers seeded by the item's id.
  • ctx.modelling has the library's geometry helpers (arc, ribbon, leafWidth, curve, tube…). Using them through ctx keeps a pack free of any runtime dependency on a framework package.
  • Meshes are merged per material afterwards, and items are scaled from width × depth to their actual size. Set height: 'scale' for plants, which should grow taller when they're made bigger.
  • modelling (exported from each package's /3d entry, e.g. @jbaysolutions/floorplan-vue/3d) has the helpers the built-in plants use: arc, ribbon, leafWidth, curve, tube, seeded and more.

JBay Floorplan is free for open source and companies under €1M yearly revenue. Licensing and pricing