The package is designed to present 2D and 3D floor plans generated by the AI service getfloorplan.com.
As a result, you will receive a website that can display various floor plans.
- Download NodeJS 18+;
- Create a new project;
- Download the required packages
npm install hart-estate-widget@2.7.5
npm install sass@1.62.1
npm install parcel@2.8.3
npm install @parcel/transformer-sass@2.8.3
- Example structure of project:
.
├── package-lock.json
├── package.json
├── src
│ ├── assets
│ │ ├── img
│ │ │ ├── logo.png
│ │ └── sass
│ │ └── index.sass
│ ├── index.html
│ └── js
└ └── index.tsx
- Copy-paste sample assets from below.
- Run with
rm -rf dist && npx parcel ./src/index.html
- Open browser at:
http://localhost:1234/?id=228ba1dd-64d3-4d33-bcd7-b4c670bed40e
The query
id
parameter accepts the UUID4 received from 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 src/index.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>katmosfera</title>
<link rel="icon" href="./assets/img/logo.png">
<script src="./js/index.tsx" type="module"></script>
</head>
<body>
<section class="widget-section">
<div class="widget" id="widget"></div> <!--must match the first attribute in 'new Widget('#widget', options);' -->
</section>
</body>
</html>
Insert the example into a file src/js/index.tsx
import { ApiStore, Widget, rotationModes } from 'hart-estate-widget';
import '../assets/sass/index.sass'; // style
import logo from '../assets/img/logo.png'; // logo
const WIDGET_API_URL = 'https://backend.estate.hart-digital.com';
const createWidget = async (logoUrl) => {
const widgetApiHandler = new ApiStore(WIDGET_API_URL)
const { searchParams } = new URL(document.location);
const planId = searchParams.get("id");
const planData = await widgetApiHandler.loadWidgetData(planId);
const options = { // the parameters you need that are described below in "Parameters"
...planData.parsed,
api_url: WIDGET_API_URL,
rotationMode: rotationModes.DEFAULT,
tabs: ['panorama', 'rotation'],
locale: 'en',
logoUrl,
logo,
}
new Widget('#widget', options); // must match the element id
}
createWidget('https://yoursite/'); // create a widget
Insert the example into a file src/sass/index.sass
*, *:before, *:after
-webkit-font-smoothing: antialiased
-moz-osx-font-smoothing: grayscale
font-family: 'Proxima Nova'
text-decoration: none
font-weight: 400
color: #fff
outline: none
padding: 0
margin: 0
box-sizing: border-box
-webkit-box-sizing: border-box
body
width: 100%
height: 100%
overflow: hidden
.widget-section
width: 100%
height: 100%
.widget
width: 100%
height: 100%
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".
type TConfig = {
/** Widget API Backend URL */
api_url: 'https://backend.example.com/';
/** Path/link to the logo */
logo: '';
/** Link opened when logo is clicked */
logoUrl: '';
/** Widget container offsetWidth */
width: 1920,
/** Widget container offsetHeight */
height: 1080,
/** Automatically resize the widget to the size of the container when the window is resized */
resizable: true;
/** Widget localization language (default: en) */
locale: 'en'
/** Use door proactive rectangle instead of door icon. */
enableDoorVisibility: false;
/** Type of images that will present in rotation tab, used as whitelist filter, defaults ['carousel', 'plan', 'topView'] */
availableRotationSteps: ['carousel', 'plan', 'topView'];
/** Available widget tabs, defaults ['rotation', 'plan', 'panorama'] */
tabs: ['rotation', 'plan', 'panorama'];
/**
* Mode of operation for plan images
* - `rotationModes.DEFAULT` - top view mode (multiple perspectives) and stylized plan view
* - `rotationModes.THREESIXTY` - image scrolling mode for circular view
* */
rotationMode: rotationModes.DEFAULT;
/** Camera persective FOV */
panoramaFov: 75;
/** Enable/disable camera rotation between panoramas (if CameraPoint.Rotation.Yaw is defined in JSON) */
enableCameraRotationBetweenPanoramas: true;
/** Enable/disable transition for camera rotation between panoramas (if CameraPoint.Rotation.Yaw is defined in JSON and enableCameraRotationBetweenPanoramas enabled) */
enableCameraTransitionBetweenPanoramas: false;
/** Override primary camera point ID over JSON */
primaryCameraPointId: 'CameraPointId12345678-12345678-12345678';
/**
* Widget color settings
* - `main`: main color of buttons, elements
* - `mainText`: text color for buttons, elements contrasting with the main color
* */
colors: {
main: '#FFA900',
mainText: '#413E3E',
};
/** Panorama icons */
panoramaIcons: {
/** Icon for camera point links in one room */
spot: 'https://images.com/image-spot.svg';
/** Icon for proactive camera point links in one room */
interactiveSpot: 'https://images.com/image-interactive-spot.svg';
/** Icon for door link */
door: 'https://images.com/image-door.png';
};
/** Overrides locale keys with custom text or translation */
dictionaryOverrides: {
'create-points': 'Create a point', // text for create point
'delete-points': 'Remove point', // text for delete point
'research-plan': 'Research plan', // text for research plan
'rotate-plan': 'Rotate plan', // text for rotate plan
'ok': 'Ok', // button text
'made-by-link': 'https://getfloorplan.com/', // watermark link
'made-by-text': 'getfloorplan.com', // watermark text
'instructions-hint-text': '', // additional text on the bottom of instruction modal
'floor': '$0 floor' // floor text
};
/** Enable/disable modal of instruction in 3D tour */
instructionVisible: true;
/** Enable/disable auto rotation in 3D tour */
autoRotate: false;
/** Array of scale keys used as filter, can be x05, x1, ... */
scales: ['x05', 'x1'];
/** Enable/disable device gyroscope for AR */
enableGyroscope: true;
/**
* Scale button type
* - `img`: legacy button with icons x05, x1, etc...
* - `text`: button with text content instead of icon x05, x1, etc...
*/
scaleButtonType: 'img';
/** Show floor number endings in floors locale translation */
floorNumberEndingsVisible: false;
/**
* Design type
* - `standard`: bottom panel without sidebar, external floors select
* - `sidebar`: all buttons in sidebar, also floors select in sidebar
* - `custom`: use `bottombarContent` and `sidebarContent` to select required buttons manually
*/
designType: 'sidebar';
/** Bottom container button types to show */
bottombarContent: [];
/** Sidebar button types to show */
sidebarContent: ['floors', 'ruler', 'scale', 'rotation', 'furniture'];
/**
* Buttons design version
* - `two`: buttons design v2.0
* - `three`: buttons design v3.0
*/
tabsButtonsDesign: 'three';
/** Proactive cursor type: 'pointer' or 'circle' */
cursor: 'pointer';
/** Enable/disable proactive cursor pulse */
enableCursorPulse: true;
/** Widget external integrations */
integrations: {
/** Configuration options for the Sentry Browser SDK. See: Sentry API BrowserOptions */
sentry: BrowserOptions;
};
/** Allows movement only within a room or between rooms, can be interroom or intraroom */
movementType: 'interroom';
/** Options for DefaultLink graphics */
default_link_options: {
/** Use perspective size for DefaultLink sprite */
use_real_size: false;
/** Perspective size */
real_size: 300;
/** Perspective size scale on mobile devices */
real_size_mobile_scale: 1;
/** Minimal distance to prevent overscale in near distances */
real_size_min_distance: 100;
/** Minimal distance scale clamp on near distances */
real_size_distance_min_scale: 0.1;
/** Enable/disable scale on hover */
hover_scale: 1.2;
};
/** Panorama fading options */
fade_options: {
/** Time for fade in (seconds) */
fade_in_time: 0.5;
/** Time for fade out (seconds) */
fade_out_time: 0.5;
};
/** Options for DefaultLink graphics */
ruler_options: {
/** Font size for ruler text */
font_size: 38;
};
/** Options for DefaultLink graphics */
link_options: {
/** Enable/disable link pulse on hover */
enable_pulse: false;
/** Pulse scale from */
pulse_from_scale: 1;
/** Pulse scale to */
pulse_to_scale: 2;
/** Pulse speed */
pulse_speed: 1;
/** Enable/disable scale on hover */
enable_point_hover_scale: false;
/** Hover scale */
point_hover_scale: 1;
};
/** Options for DefaultLink graphics */
map_options: {
/** Map type, should be 'default', 'top_view' or 'multi_floor' */
type: 'default';
/** Upscale top view resolution for better rendering */
top_view_upscale: 2;
/** Crop transparent bounds in multimap */
crop_transparent?: true;
};
/** Options for Scene camera */
camera_options: {
/** Speed of fov changing per deltaTime */
fov_change_speed?: 0;
};
/** Options for Portal link graphics */
portal_options?: {
/** Use overlay div elements instead of three.js graphics */
use_overlay?: true;
/** Generate portals from stairs */
generate_from_stairs?: true;
};
/** Options for DefaultLink graphics */
lazy_load_options: {
/** Count panoramas to lazy load after move to another panorama */
preload_count: 3;
/** Force lazy load another non-loaded panoramas instead of skipping near cached panoramas */
force_preload_non_cached: true;
/** Preload depth maps */
use_masks_preload: true;
};
/** Widget branding data */
widget_branding: {
/** Branded logo path */
logo_path: 'https://es-logos.com/logo.png';
/** Branded company name */
company_name: 'ES Company';
/** Branded company url */
company_url: 'https://es.company.com';
/** Branded widget language (See locale/*) */
widget_language: 'es';
}
/** Show/hide fullscreen button */
fullscreen_button_visible: false;
/** Show/hide room type label */
room_label_visible: false;
};
tabs: [
'rotation', // circular view images (order is mandatory)
'panorama', // 360° images
],
rotationMode: [
rotationModes.DEFAULT, // top view mode (multiple perspectives) and stylized plan view
rotationModes.THREESIXTY, // image scrolling mode for circular view
],
floors[0].rotate.type: [
'top_down', // full model
'middle_cut', // model with cut in the middle
],
floors[0].panorama.type: [
'sphere', // 360° panorama
'cube', // panorama with 6 images (top, down, left, right, front, back)
],
locale: [
'ru', // Russian language
'en', // English language
'es', // Spanish language
'de', // German language
'ja', // Japanese language
],
scales: [
'x05',
'x075',
'x1',
'x125',
'x2',
],
JSON object returned from backend
name: "", // CRM plan ID (only for CRM API)
original_plan_img: "", // deprecated, path to the original plan image
original_plans_img: [ // array of paths to the original plan images
""
],
styled_plan_img: "", // path to the styled plan image
top_view_img: "", // path to the top view image
json: { // JSON with data for 3D tour
type: "furniture", // type of JSON (furniture, neural)
value: "" // path to JSON
},
panorama: { // type of panorama and paths to 360° images
type: "sphere", // 360° panorama or 'cube' for 6 images
items: {
[
camera_id: "" // camera ID for panorama
room_id: "" // room ID for panorama
images: [ // array of paths to 360° sphere and sides of the cube if type is cube
sphere: "",
front: null,
back: null,
left: null,
right: null,
top: null,
bottom: null,
scene_depth: "", // path to EXR file for depth map if available
object_ids: "", // path to EXR file for furniture object ids if available
]
}
]
},
rotate: { // type of images and paths to circular view images
type: "top_down", // full model or model with cut in the middle ('middle_cut')
items: [ // array of paths to circular view images
""
]
}
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.
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.
Project code and documentation copyright hart-digital.com.
All renders of floor plans copyright getfloorplan.com.