hart-estate-widget
Version:
HART Estate widget
487 lines (427 loc) • 16.8 kB
Markdown
The package is designed to present 2D and 3D floor plans generated by the AI service [getfloorplan.com](https://getfloorplan.com).
- [Quick Start](
- [Example vite.config.ts](
- [Example index.html](
- [Example index.js](
- [Example index.sass](
- [Docs](
- [Parameters](
- [REST API Object](
- [Versioning](
- [Copyright and License](
As a result, you will receive a website that can display various floor plans.

- Download NodeJS 18+
- Create a new project
```shell
npm init
```
- Download the required packages
```shell
npm install -S hart-estate-widget@4.0.0
npm install -S -D vite
npm install -S -D sass-embedded
```
- Example structure of project
```
.
├── src
│ ├── index.html
│ ├── index.js
│ ├── index.sass
│ └── logo.png
├── package.json
└── package-lock.json
```
- Copy-paste sample assets from below.
- Run with `rm -rf dist && npx vite`
- Open browser at:
http://localhost:1234/?id=73b833c3-072a-4ac2-9f5d-7f7ac3d1fc9c
> The query `id` parameter accepts the UUID4 received from [getfloorplan.com](https://getfloorplan.com)
> You can use these UUID4 for test purposes:
> - Scandy style: `228ba1dd-64d3-4d33-bcd7-b4c670bed40e`
> - Boho style: `f9032373-bb2c-416e-b0ab-20b8fd24d482`
> - England style: `b21871a2-2d5b-4beb-817b-ed750eebab9a`
> - Neutral style: `e8553134-0457-488c-8d3e-611b0e2be4d4`
> - Modern style: `73b833c3-072a-4ac2-9f5d-7f7ac3d1fc9c`
Insert the example into a file `vite.config.ts`
```ts
import { defineConfig } from 'vite';
export default defineConfig({
root: 'src',
build: { outDir: '../dist' },
server: { port: 1234, open: true },
});
```
Insert the example into a file `src/index.html`
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
<title>HART Estate Widget</title>
<script type="module" src="./index.js"></script>
<link rel="icon" href="./logo.png">
</head>
<body>
<div id="widget"></div>
</body>
</html>
```
Insert the example into a file `src/index.js`
```js
import { Api } from 'hart-estate-widget/build/api.js'
const searchParams = new URLSearchParams(document.location.search);
const planId = searchParams.get('id');
const crmPlanId = searchParams.get('crmPlanId');
const baseUrl = 'https://backend.estate.hart-digital.com';
const loadData = async () => {
const {loadCrmWidgetData, loadWidgetData} = new Api(baseUrl);
return crmPlanId ? loadCrmWidgetData(crmPlanId) : loadWidgetData(planId);
};
const loadCreateWidget = async () => (await import('hart-estate-widget/build/createWidget.js')).createWidget;
const loadFovPlugin = async () => (await import('hart-estate-widget/build/plugins/FovPlugin.js')).FovPlugin;
const loadLogoUrl = async () => (await import('./logo.png')).default;
const loadStyle = async () => (await import('./index.sass')).default;
const loadDocument = async () => new Promise((resolve) => (window.onload = resolve));
const queue = [
loadData(),
loadCreateWidget(),
loadFovPlugin(),
loadLogoUrl(),
loadStyle(),
loadDocument(),
];
Promise.all(queue).then(([data, createWidget, FovPlugin, logoUrl]) => {
const options = {
baseUrl,
logoUrl,
logoLinkUrl: 'https://getfloorplan.com',
};
const plugins = [
new FovPlugin(2),
];
createWidget('#widget', data, options, plugins);
});
```
Insert the example into a file `src/index.sass`
```sass
*, *:before, *:after
-webkit-font-smoothing: antialiased
-moz-osx-font-smoothing: grayscale
font-family: 'Proxima Nova', sans-serif
text-decoration: none
font-weight: 400
color:
outline: none
padding: 0
margin: 0
box-sizing: border-box
-webkit-box-sizing: border-box
html, body
width: 100%
height: 100%
width: 100%
height: 100%
overflow: hidden
```
Here you can see a list of accessible options and examples of usage. There are accessible values for each option below in the block "Types of Elements".
```json
{
// Widget API base URL
"baseUrl": "https://backend.estate.hart-digital.com",
// Widget locale can be one of
// "en" - English language
// "ru" - Russian language
// "de" - German language
// "es" - Spanish language
// "ja" - Japanese language
// "nl" - Dutch language
"locale": "en",
// Overrides locale keys with custom text or translation
"localeOverrides": {
"rotate-plan": "Rotate plan",
"research-plan": "Research plan",
"create-points": "Create a point",
"delete-points": "Remove point",
"instructions-hint-text": "",
"ok": "Ok",
"ruler-ok": "Ok",
"made-by-template": "$0 $1",
"made-by-prefix": "made by",
"made-by-link": "https://getfloorplan.com/",
"made-by-text": "getfloorplan.com",
"style": "Style",
"floor": "$0 floor",
"floorNumberEndings": {
"1": "$0st",
"2": "$0nd",
"3": "$0d",
"rest": "$0th"
}
},
// Path/link to the logo
"logoUrl": "https://getfloorplan.com/img/logo.58f6cd11.svg",
// Link opened when logo is clicked
"logoLinkUrl": "https://getfloorplan.com",
// Widget color settings in CSS color formal like: "rgba(255, 255, 255, 0)", "#ABCDEF", etc...
// "main" - main color of buttons, elements
// "mainText" - text color for buttons, elements contrasting with the main color
"colors": {
"main": "#FFA900",
"mainText": "#413E3E"
},
// First opened tab
"primaryTab": "panorama",
// Available widget tabs array with order:
// "panorama" - Panorama 360 tab
// "rotation" - Isometric plan rotation tab
// "plan" - Original plan tab
"tabs": ["plan", "rotation", "panorama"],
// Controls in bottom bar, can be:
// "ruler" - Ruler enable/disable button (panorama tab only)
// "scale" - Scale x1, x2, x0.5 button (panorama tab only)
// "autoRotate" - Auto rotate enable/disable button (panorama tab only)
// "minusScale" - Scale minus button (panorama tab only)
// "plusScale" - Scale plus button (panorama tab only)
// "furnished" - Furnished / bareshell button (panorama tab only)
// "prevPanorama" - Prev panorama button (panorama tab only)
// "nextPanorama" - Next panorama button (panorama tab only)
// "2d" - 2D tab button
// "3d" - 3D tab button
// "360" - 360 tab button
// "isometry" - Isometry rotation arrows (rotation tab only)
// "floors" - Floors select with reverse order inside application frame
"controls": ["ruler", "scale", "autoRotate"],
// Enable/disable modal of instruction in 3D tour
"isInstructionsVisible": true,
// Enable/disable auto rotation in 3D tour
"isAutoRotate": false,
// Enable/disable device gyroscope for AR
"isGyroscopeEnabled": true,
// Show/hide fullscreen button
"isFullscreenButtonVisible": true,
// Show/hide current room type top label
"isRoomLabelVisible": false,
// Show next scale text or current
// true: next (current: 0.5, shows: 1x)
// false: current (current: 0.5, shows: 0.5x)
"isShowNextScaleText": false,
// Enable InteractiveRotationTab
// true: InteractiveRotationTab will show on interactive_top_view capability
// false: always use default RotationTab
"isInteractiveTabAvailable": true,
// Use multifloor map instead of default or topView
"isMultifloorMap": false,
// Automatic crop transparent part of images by rasterizer (may lag a bit)
"isNeedCropMultifloorMap": true,
// Precision of multifloor map crop
"multiFloorMapCropPrecision": 100,
// Move panorama control buttons to the application context
"isAbsolutePanoramaControls": false,
// Show prev/next room type labels on prev/next panorama buttons
"isShowLabelsOnPrevNext": true,
// Render links as div elements in UI layer
"isOverrideLinks": false,
// Enable room indexer button in rotation tab
"isRoomIndexerVisible": false,
// Enable room indexer button to rotate middle cuts
"isRoomIndexerRotate": false,
// Direction of rotation of rooms
"indexerButtonDirection": false,
// Show top view on rotation tab
"isShowTopViewOnRotationTab": true,
// Show left and right arrows in room scroll container
"isInteractiveScrollArrowsVisible": true,
// 'original' - use original_plan_img
// 'miniplan' - use miniplan_img
"2DTabBehavior": "miniplan",
// Show the "hide furniture" button with a separate switch
"isHiddenFurnitureSwitchVisible": true,
// Apply scale offset in 2D/3D
"isTransformScaleWithOffset": true,
// Apply transform offset in 2D/3D
"isTransformEnabled": true,
// Apply scale offset from screen center instead of cursor
"isTransformAlongScreenCenter": false,
/** Resolve zero angle in middle cuts to rotate from top view more angle-seamlessly */
"isNeedMiddleCutZeroAngle": false,
// Ruler font settings
"rulerFontSettings": {
"fontSize": "38px",
"fontWeight": "Bold",
"lineHeight": "1",
"fontFamily": "Roboto Flex",
"textAlign": "center",
"borderRadius": 55,
"scale": 1.5,
"width": 256,
"height": 128,
"textFillColor": "#0008",
"textHoverColor": "#000f",
"fillColor": "#fff8",
"hoverColor": "#fffa",
"feetsPositionY": 100,
"feetsPrecision": 2,
"feetsFormat": "$0 ft",
"useFeetsComma": true,
"metersPositionY": 50,
"metersPrecision": 2,
"metersFormat": "$0 m",
},
// Base camera persective FOV
"cameraFov": 75,
// Custom camera fovs by base FOV Scale
"cameraFovs": [
{ "text": "1x", "value": 1 },
{ "text": "2x", "value": 0.5 },
{ "text": "4x", "value": 0.25 },
{ "text": "0.5x", "value": 1.35 },
],
// Legacy camera fovs by scale texts (available: 0.5x, 1x, 2x)
"scales": ["1x", "2x", "0.5x"],
// Custom link icons
"linkIcons": {
"door": "https://site.com/door.png",
"doorHover": "https://site.com/door-hover.png",
"spot": "https://site.com/spot.png",
"spotHover": "https://site.com/spot-hover.png",
"stairUp": "https://site.com/stairUp.png",
"stairUpHover": "https://site.com/stairUp-hover.png",
"stairDown": "https://site.com/stairDown.png",
"stairDownHover": "https://site.com/stairDown-hover.png",
},
// Custom UI icons
"uiIcons": {
"tabs.2D": "https://site.com/2D.png",
"tabs.3D": "https://site.com/3D.png",
"tabs.360": "https://site.com/360.png",
"tabs.roomIndexer": "https://site.com/roomIndexer.png",
"room.kidroom": "https://site.com/kidroom.png",
"room.balcony": "https://site.com/balcony.png",
"room.gym": "https://site.com/gym.png",
"room.bathroom": "https://site.com/bathroom.png",
"room.bedroom": "https://site.com/bedroom.png",
"room.garage": "https://site.com/garage.png",
"room.hallway": "https://site.com/hallway.png",
"room.kitchen": "https://site.com/kitchen.png",
"room.office": "https://site.com/office.png",
"room.living": "https://site.com/living.png",
"room.storage": "https://site.com/storage.png",
"room.terrace": "https://site.com/terrace.png",
"room.toilet": "https://site.com/toilet.png",
"float.close": "https://site.com/close.png",
"float.extend": "https://site.com/extend.png",
"float.multiMap": "https://site.com/multiMap.png",
"float.shrink": "https://site.com/shrink.png",
"float.fullscreen": "https://site.com/fullscreen.png",
"instructions.move": "https://site.com/move.png",
"instructions.research": "https://site.com/research.png",
"instructions.createPoints": "https://site.com/createPoints.png",
"instructions.deletePoints": "https://site.com/deletePoints.png",
"controls.rulerOn": "https://site.com/rulerOn.png",
"controls.rulerOff": "https://site.com/rulerOff.png",
"controls.prevPanorama": "https://site.com/prevPanorama.png",
"controls.nextPanorama": "https://site.com/nextPanorama.png",
"controls.minusScale": "https://site.com/minusScale.png",
"controls.plusScale": "https://site.com/plusScale.png",
"controls.autoRotateOn": "https://site.com/autoRotateOn.png",
"controls.autoRotateOff": "https://site.com/autoRotateOff.png",
"controls.arrowLeft": "https://site.com/arrowLeft.png"
},
// Panorama fade time in seconds
"panoramaFadeTime": 0.5,
// Panorama miniplan type, use svg or original
"panoramaMiniplanType": "svg",
// Overrides for interactive opacity
"interactiveHoverOpacity": 0.65,
"interactiveActiveOpacity": 0.8,
// Camera sensitivity
"cameraHorizontalSensitivity": 1,
"cameraVerticalSensitivity": 1,
"mobileCameraHorizontalSensitivity": 2,
"mobileCameraVerticalSensitivity": 2,
// Widget external integrations
"integrations": {
// https://docs.sentry.io/platforms/javascript/configuration/options/
"sentry": {
"dsn": "https://1234567890abcdef@sentry.com/12345"
}
}
}
```
JSON object returned from backend
```js
export default {
primary_variant: "<id>", // primary variant to open
variants: [ // all plan variants
{
variant_info: {
style_name: "<name>", // the name of the variant style
is_renovation: true, // is there a renovation in the plan
},
plan_id: "<uuid>", // variant service plan uuid
json: "<url>", // json url for additional plan data
assets_path: "<path>", // plan assets base url
capabilities: { /*...*/ }, // plan capabilities
rendering_settings: { /*...*/ }, // plan rendering settings
primary_floor: 0, // primary plan floor index
floors: [ // plan floors
{
original_plan_img: "<url>", // absolute path to original plan image
miniplan_img: "<url>", // absolute path to miniplan image
top_view: {
image_template: "<template>", // template for top view decoding
room_ids_template: "<template>", // template for top view mask decoding
items: ["<filename>"], // top view image names
},
isometric_view: {
image_template: "<template>", // template for isometric images decoding
room_ids_template: "<template>", // template for isometric images masks decoding
items: ["<filename>"], // isometric images names
},
panorama_view: {
template: "<template>", // template for panorama image decoding
scene_depth_template: "<template>", // template for panorama depth image decoding
primary_camera_point_id: "<id>", // primary plan camera id
},
location: { X: 0, Y: 0, Z: 0 }, // floor location
height: 280, // floor height
vertices: [ /*...*/ ], // plan vertices data
rooms: [ /*...*/ ], // plan rooms data
camera_points: [ /*...*/ ], // plan camera points data
walls: [ /*...*/ ], // plan walls data
doors: [ /*...*/ ], // plan doors data
stairs: [ /*...*/ ], // plan stairs data
portals: [ /*...*/ ], // plan portals data
apertures: [ /*...*/ ], // plan apertures data
decors: [ /*...*/ ], // plan decors data
object_pairs: [], // color pairs for furniture data
room_pairs: [], // color pairs for room data
plan_meta: { /*...*/ }, // plan metadata
},
],
},
],
};
```
For the latest stable version refer to the latest up-to-date version in [Quick Start](
This project is maintained under the [Semantic Versioning guidelines](https://semver.org).
However, some versions are being developed for specific clients. **We do not recommend using them**, as changes in these versions are not documented and may affect your functionality.
The project code is licensed under the [GPLv3 license](https://www.gnu.org/licenses/gpl-3.0-standalone.html).
Project code and documentation copyright [hart-digital.com](https://hart-digital.com).
All renders of floor plans copyright [getfloorplan.com](https://getfloorplan.com).