Appearance
Your first page
An editor to draw a building, and a viewer that reports where people click.
vue
<script setup lang="ts">
import { ref } from 'vue'
import { FloorPlanEditor, FloorPlanViewer, createEmptyPlan, type PlanClickEvent } from '@jbaysolutions/floorplan-vue'
const plan = ref(createEmptyPlan('Head office')) // a building with one ground floor
function onClick(e: PlanClickEvent) {
console.log(`Clicked at ${e.x}, ${e.y} cm on ${e.floor.name}`, e.room?.name)
}
</script>
<template>
<div style="height: 600px">
<FloorPlanEditor v-model="plan" />
</div>
<div style="height: 400px">
<FloorPlanViewer :plan="plan" @plan-click="onClick" />
</div>
</template>tsx
import { useState } from 'react'
import { FloorplanEditor, FloorplanViewer, createEmptyPlan, type PlanClickEvent } from '@jbaysolutions/floorplan-react'
export function Office() {
const [plan, setPlan] = useState(() => createEmptyPlan('Head office')) // a building with one ground floor
function onClick(e: PlanClickEvent) {
console.log(`Clicked at ${e.x}, ${e.y} cm on ${e.floor.name}`, e.room?.name)
}
return (
<>
<FloorplanEditor plan={plan} onChange={setPlan} style={{ height: 600 }} />
<FloorplanViewer plan={plan} onPlanClick={onClick} style={{ height: 400 }} />
</>
)
}html
<floorplan-editor style="height: 600px"></floorplan-editor>
<floorplan-viewer style="height: 400px"></floorplan-viewer>
<script type="module">
import { createEmptyPlan } from '@jbaysolutions/floorplan-elements'
const editor = document.querySelector('floorplan-editor')
const viewer = document.querySelector('floorplan-viewer')
editor.plan = viewer.plan = createEmptyPlan('Head office') // a building with one ground floor
// the editor sends the new plan after every edit: show it in the viewer too
editor.addEventListener('change', (e) => (viewer.plan = e.detail.plan))
viewer.addEventListener('plan-click', (e) => {
const { x, y, room, floor } = e.detail
console.log(`Clicked at ${x}, ${y} cm on ${floor.name}`, room?.name)
})
</script>Give the components a height
Every component fills the box it's given (minimum 240 px). In Vue, give the parent a height; in React and on the elements, give the component itself a height (style or CSS).
Try the editor below: draw a room with the room tool, then watch the event the editor sends.
Loading the live demo…
Draw or change something: the new plan is emitted after every edit.
More than one floor?
A plan is a whole building. Add floors from the floor menu in the editor (top right), and both viewers show a floor switcher automatically. See Multi-floor buildings.
Saving and loading
The plan is plain JSON. Save it as it is, and pass it back in later through normalizePlan, which fills in anything missing and upgrades plans saved by older versions:
ts
import { normalizePlan } from '@jbaysolutions/floorplan-vue'
await api.savePlan(JSON.stringify(plan.value))
plan.value = normalizePlan(JSON.parse(await api.loadPlan()))tsx
import { normalizePlan } from '@jbaysolutions/floorplan-react'
await api.savePlan(JSON.stringify(plan))
setPlan(normalizePlan(JSON.parse(await api.loadPlan())))js
import { normalizePlan } from '@jbaysolutions/floorplan-elements'
await api.savePlan(JSON.stringify(editor.plan))
editor.plan = normalizePlan(JSON.parse(await api.loadPlan()))See Data model for the format.