hart-estate-widget 0.0.8 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +68 -13
  2. package/build/api/index.js +24 -0
  3. package/build/assets/img/bricks.jpeg +0 -0
  4. package/build/assets/img/door-texture.jpeg +0 -0
  5. package/build/assets/img/door.jpeg +0 -0
  6. package/build/assets/img/exterior-wall-texture.jpeg +0 -0
  7. package/build/assets/img/floor-bathroom.jpg +0 -0
  8. package/build/assets/img/floor-dark.png +0 -0
  9. package/build/assets/img/floor-white.png +0 -0
  10. package/build/assets/img/floor.jpg +0 -0
  11. package/build/assets/img/grass.png +0 -0
  12. package/build/assets/img/ground.svg +9 -0
  13. package/build/assets/img/wall-texture.jpg +0 -0
  14. package/build/assets/sass/animation.sass +5 -0
  15. package/build/assets/sass/components/loader.sass +51 -0
  16. package/build/assets/sass/components/model.sass +14 -0
  17. package/build/assets/sass/components/panorama.sass +65 -0
  18. package/build/assets/sass/components/tabs.sass +66 -0
  19. package/build/assets/sass/index.sass +3 -0
  20. package/build/components/Application.js +12 -2
  21. package/build/components/Loader.js +22 -0
  22. package/build/components/ModelTab.js +120 -0
  23. package/build/components/PanoramaTab.js +215 -0
  24. package/build/config/defaultConfig.js +4 -1
  25. package/build/config/defaultJSON.js +2432 -0
  26. package/build/index.css +1 -1
  27. package/build/index.css.map +1 -1
  28. package/build/index.js +32 -8
  29. package/build/store/houseStore.js +675 -0
  30. package/build/store/modelStore.js +196 -0
  31. package/build/utils/csg/csg-lib.js +387 -0
  32. package/build/utils/csg/csg-worker.js +94 -0
  33. package/build/utils/csg/three-csg.js +280 -0
  34. package/build/utils/modelHelpers.js +125 -0
  35. package/build/utils/panoramaHelpers.js +83 -0
  36. package/package.json +17 -3
package/README.md CHANGED
@@ -3,24 +3,79 @@
3
3
 
4
4
  ## Способ установки с помощью NPM:
5
5
 
6
- ### `npm install hart-estate-widget`
6
+ `npm install hart-estate-widget --save`
7
7
 
8
+ ## Пример использования:
8
9
 
10
+ ```js
11
+ import React, { useEffect, useState } from 'react';
12
+ import { Widget } from 'hart-estate-widget';
13
+ import 'hart-estate-widget/build/index.css';
9
14
 
10
- ## Пример использования:
15
+ const WIDGET_OPTIONS = {
16
+ tabs: ['planImage', 'topView', 'topDownView', 'rotation',],
17
+ tabPanes: true,
18
+ planImage: '/path/to/plan.jpg',
19
+ topView: '/path/to/top_view.jpg',
20
+ topDownView: '/path/to/top_down_view.jpg',
21
+ rotationImages: [
22
+ '/path/to/rotation_image_1.jpg',
23
+ '/path/to/rotation_image_2.jpg',
24
+ '/path/to/rotation_image_3.jpg',
25
+ '/path/to/rotation_image_4.jpg',
26
+ '/path/to/rotation_image_5.jpg',
27
+ ],
28
+ };
29
+
30
+ const App = () => {
31
+ const [widget, setWidget] = useState(null);
32
+
33
+ useEffect(() => {
34
+ const createdWidget = new Widget('#widget-container', WIDGET_OPTIONS);
35
+
36
+ setState(createdWidget);
37
+ }, []);
38
+
39
+ return (
40
+ <div>
41
+ <div id="#widget-container" />
42
+ </div>
43
+ );
44
+ }
45
+
46
+ export App;
47
+
48
+ ```
49
+
50
+
51
+ ## Параметры:
52
+
53
+ ```js
54
+ {
55
+ // элементы
56
+ tabs: ['planImage', 'topView', 'topDownView', 'rotation'], // включенные элементы
57
+ tabPanes: true,
11
58
 
59
+ // ширина/высота
60
+ width: 500,
61
+ height: 750,
12
62
 
13
- ### `const myWidget = new Widget('#container', options);`
63
+ // значения
64
+ planImage: '', // путь к изображению планировки
65
+ topView: '', // путь к изображению вида сверху
66
+ topDownView: '', // путь к изображению вида сверху под углом
67
+ rotationImages: [], // пути к изображениям кругового просмотра (порядок обязателен)
68
+ }
14
69
 
70
+ ```
15
71
 
16
- ## Параметры по умолчанию:
72
+ ## Типы элементов
73
+ ```js
74
+ tabs: [
75
+ 'planImage', // изображение планировки
76
+ 'topView', // изображение вида сверху
77
+ 'topDownView', // изображение вида сверху под углом
78
+ 'rotation', // изображения кругового просмотра (порядок обязателен)
79
+ ]
80
+ ```
17
81
 
18
- #### `tabs: ['planImage', 'topView', 'topDownView', 'rotation', 'panorama', 'model']` - Элементы, которые необходимо активировать
19
- #### `tabPanes: true` - Показывать / Скрывать навигационную панель
20
- #### `width: null` - Ширина компонента (по умолчанию 100%)
21
- #### `height: null` - Высота компонента (по умолчанию 100vh)
22
- #### `planImage: ''` - Путь к изображению планировки
23
- #### `topView: ''` - Путь к изображению модели сверху
24
- #### `topDownView: ''` - Путь к изображению модели сверху под углом
25
- #### `rotationImages: []` - Массив изображений для 360 визуализатора
26
- #### `panoramaImages: []` - Массив изображений сфер для виртуальной панорамы
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.loadFurnitureData = exports.STAGE_API_URL = exports.API_URL = void 0;
7
+
8
+ require("core-js/modules/es.promise.js");
9
+
10
+ require("core-js/modules/es.array.reduce.js");
11
+
12
+ const API_URL = 'https://backend.estate.myhart.ru';
13
+ exports.API_URL = API_URL;
14
+ const STAGE_API_URL = 'https://backend-stage.estate.myhart.ru';
15
+ exports.STAGE_API_URL = STAGE_API_URL;
16
+
17
+ const loadFurnitureData = async furniture => {
18
+ const furnitureQuery = furniture.reduce((acc, item, i) => acc += "".concat(i === 0 ? '' : ',').concat(item.Model), '');
19
+ const path = "".concat(API_URL, "/api/furniture?only=").concat(furnitureQuery);
20
+ const response = await fetch(path);
21
+ return await response.json();
22
+ };
23
+
24
+ exports.loadFurnitureData = loadFurnitureData;
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,9 @@
1
+ <svg width="250" height="250" viewBox="0 0 250 250" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="125" height="125" fill="white"/>
3
+ <rect x="125" y="125" width="125" height="125" fill="white"/>
4
+ <rect y="125" width="125" height="125" fill="black"/>
5
+ <rect x="125" width="125" height="125" fill="black"/>
6
+ <rect x="124" width="2" height="250" fill="#00A3FF"/>
7
+ <rect y="126" width="2" height="250" transform="rotate(-90 0 126)" fill="#00A3FF"/>
8
+ <rect x="0.5" y="0.5" width="249" height="249" stroke="#00A3FF"/>
9
+ </svg>
@@ -0,0 +1,5 @@
1
+ @keyframes fadeIn
2
+ 0%
3
+ opacity: 0
4
+ 100%
5
+ opacity: 1
@@ -0,0 +1,51 @@
1
+ @import '../vars'
2
+
3
+ .widget-loader
4
+ display: block
5
+ position: relative
6
+ width: 80px
7
+ height: 80px
8
+ &--absolute
9
+ position: absolute
10
+ left: 50%
11
+ top: 50%
12
+ transform: translate(-50%, -50%)
13
+ div
14
+ position: absolute
15
+ top: 33px
16
+ width: 13px
17
+ height: 13px
18
+ border-radius: 50%
19
+ background: $mainColor
20
+ animation-timing-function: cubic-bezier(0, 1, 1, 0)
21
+ &:nth-child(1)
22
+ left: 8px
23
+ animation: widget-loader-1 0.6s infinite
24
+ &:nth-child(2)
25
+ left: 8px
26
+ animation: widget-loader-2 0.6s infinite
27
+ &:nth-child(3)
28
+ left: 32px
29
+ animation: widget-loader-2 0.6s infinite
30
+ &:nth-child(4)
31
+ left: 56px
32
+ animation: widget-loader-3 0.6s infinite
33
+
34
+ @keyframes widget-loader-1
35
+ 0%
36
+ transform: scale(0)
37
+ 100%
38
+ transform: scale(1)
39
+
40
+ @keyframes widget-loader-3
41
+ 0%
42
+ transform: scale(1)
43
+ 100%
44
+ transform: scale(0)
45
+
46
+ @keyframes widget-loader-2
47
+ 0%
48
+ transform: translate(0, 0)
49
+
50
+ 100%
51
+ transform: translate(24px, 0)
@@ -0,0 +1,14 @@
1
+ @import '../vars'
2
+
3
+ .widget-application
4
+ .widget-tab
5
+ &__model
6
+ width: 100%
7
+ height: 100%
8
+ position: absolute
9
+ left: 0
10
+ top: 0
11
+ &-scene
12
+ width: 100%
13
+ height: 100%
14
+ display: block
@@ -0,0 +1,65 @@
1
+ @import '../vars'
2
+
3
+ .widget-application
4
+ .widget-tab
5
+ &__panorama
6
+ width: 100%
7
+ height: 100%
8
+ position: absolute
9
+ left: 0
10
+ top: 0
11
+ &-overlay
12
+ width: 100%
13
+ height: 100%
14
+ overflow: hidden
15
+ &-mode,
16
+ &-standart
17
+ position: absolute
18
+ right: 15px
19
+ bottom: 20px
20
+ color: $black
21
+ background-color: $mainColor
22
+ padding: 5px 15px
23
+ border-radius: 10px
24
+ font-size: 1rem
25
+ font-weight: bold
26
+ border: none
27
+ cursor: pointer
28
+ @include noSelect
29
+ &:hover
30
+ box-shadow: 1px 1px 10px rgba(0, 0, 0, .15)
31
+ &-standart
32
+ right: 100px
33
+ &-map
34
+ position: absolute
35
+ right: 15px
36
+ bottom: 70px
37
+ z-index: 10000
38
+ &--hidden
39
+ display: none !important
40
+ img
41
+ width: 100px
42
+ border-radius: 10px
43
+ &.active
44
+ width: 240px
45
+ &:hover
46
+ box-shadow: 1px 1px 10px rgba(0,0,0,0.15)
47
+ &__dot
48
+ position: absolute
49
+ left: 0
50
+ top: 0
51
+ transform: translate(-50%, -50%)
52
+ width: 5px
53
+ height: 5px
54
+ background-color: $mainColor
55
+ border-radius: 50%
56
+ cursor: pointer
57
+ z-index: 10
58
+ &--big
59
+ border: 2px solid $mainColor
60
+ box-shadow: inset 0 0 0 2px #ffffff
61
+ width: 15px
62
+ height: 15px
63
+ &--active
64
+ background-color: red
65
+ border: 2px solid red
@@ -48,6 +48,72 @@
48
48
  height: 100%
49
49
  object-fit: cover
50
50
 
51
+ &-menu
52
+ position: absolute
53
+ z-index: 3
54
+ left: 15px
55
+ top: 15px
56
+ max-height: 100%
57
+ overflow-y: auto
58
+ padding-bottom: 30px
59
+ &__wallpapers
60
+ display: flex
61
+ flex-wrap: wrap
62
+ align-items: flex-start
63
+ margin-top: 10px
64
+ width: 100%
65
+ img
66
+ width: 30px
67
+ height: 30px
68
+ display: block
69
+ object-fit: cover
70
+ cursor: pointer
71
+ margin-right: 10px
72
+ margin-block-end: 10px
73
+ ul
74
+ list-style-type: none
75
+ li
76
+ color: $black
77
+ background-color: $mainColor
78
+ padding: 5px 15px
79
+ border-radius: 10px
80
+ font-size: .8rem
81
+ border: none
82
+ cursor: pointer
83
+ margin-bottom: 15px
84
+ width: 200px
85
+ @include noSelect
86
+ label
87
+ display: flex
88
+ cursor: inherit
89
+ width: 100%
90
+ input
91
+ &[type=color]
92
+ cursor: pointer
93
+ margin-left: auto
94
+ width: 50px
95
+ height: 20px
96
+ border: 0
97
+ border-radius: 5px
98
+ &::-webkit-color-swatch-wrapper
99
+ display: none !important
100
+ &[type=file]
101
+ display: none
102
+ &:hover
103
+ box-shadow: 1px 1px 10px rgba(0, 0, 0, .15)
104
+ &:nth-child(1)
105
+ position: relative
106
+ &::after
107
+ content: '|||'
108
+ transform: translateY(-50%) rotate(90deg)
109
+ font-size: 20px
110
+ line-height: 20px
111
+ margin-left: 10px
112
+ display: block
113
+ position: absolute
114
+ right: 10px
115
+ top: 50%
116
+
51
117
  .widget-tab-panes
52
118
  position: absolute
53
119
  z-index: 3
@@ -46,3 +46,6 @@ html, body
46
46
 
47
47
  @import './components/tabs'
48
48
  @import './components/instructions'
49
+ @import './components/panorama'
50
+ @import './components/loader'
51
+ @import './components/model'
@@ -19,6 +19,10 @@ var _ImageTab = _interopRequireDefault(require("./ImageTab"));
19
19
 
20
20
  var _RotationTab = _interopRequireDefault(require("./RotationTab"));
21
21
 
22
+ var _PanoramaTab = _interopRequireDefault(require("./PanoramaTab"));
23
+
24
+ var _ModelTab = _interopRequireDefault(require("./ModelTab"));
25
+
22
26
  var _TabWrapper = _interopRequireDefault(require("./TabWrapper"));
23
27
 
24
28
  var _D = _interopRequireDefault(require("../assets/img/3D.jpg"));
@@ -69,14 +73,20 @@ const Application = (0, _mobxReactLite.observer)(_ref => {
69
73
  title: "Panoramic tour",
70
74
  text: ['Use mouse to rotate', 'To move through the rooms, click on the layout thumbnail'],
71
75
  onStart: hideTabPanes
72
- }, /*#__PURE__*/_react.default.createElement("p", null, "Work in progress")),
76
+ }, /*#__PURE__*/_react.default.createElement(_PanoramaTab.default, {
77
+ json: config.json,
78
+ planImage: config.planImage,
79
+ images: config.panoramaImages
80
+ })),
73
81
  'model': /*#__PURE__*/_react.default.createElement(_TabWrapper.default, {
74
82
  isActive: !isTabPanesVisible,
75
83
  image: _D.default,
76
84
  title: "3D Model",
77
85
  text: ['Use mouse to rotate', 'Use the right mouse button to move'],
78
86
  onStart: hideTabPanes
79
- }, /*#__PURE__*/_react.default.createElement("p", null, "Work in progress"))
87
+ }, /*#__PURE__*/_react.default.createElement(_ModelTab.default, {
88
+ json: config.json
89
+ }))
80
90
  };
81
91
  const appStyle = {
82
92
  width,
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _react = _interopRequireDefault(require("react"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+
12
+ const Loader = _ref => {
13
+ let {
14
+ absolute
15
+ } = _ref;
16
+ return /*#__PURE__*/_react.default.createElement("div", {
17
+ className: "widget-loader ".concat(absolute ? 'widget-loader--absolute' : '')
18
+ }, /*#__PURE__*/_react.default.createElement("div", null), /*#__PURE__*/_react.default.createElement("div", null), /*#__PURE__*/_react.default.createElement("div", null), /*#__PURE__*/_react.default.createElement("div", null));
19
+ };
20
+
21
+ var _default = Loader;
22
+ exports.default = _default;
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ require("core-js/modules/web.dom-collections.iterator.js");
9
+
10
+ var _react = _interopRequireWildcard(require("react"));
11
+
12
+ var _mobxReactLite = require("mobx-react-lite");
13
+
14
+ var _modelStore = _interopRequireDefault(require("../store/modelStore"));
15
+
16
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
+
18
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
+
20
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
21
+
22
+ const ModelTab = (0, _mobxReactLite.observer)(_ref => {
23
+ let {
24
+ json
25
+ } = _ref;
26
+ const [menuState, setMenuState] = (0, _react.useState)(false);
27
+ const {
28
+ houseStore
29
+ } = _modelStore.default;
30
+ (0, _react.useEffect)(() => {
31
+ const container = document.querySelector('.widget-tab__model-scene');
32
+ container.appendChild(_modelStore.default.renderer.domElement);
33
+
34
+ _modelStore.default.setCurrentControlsType('orbit');
35
+
36
+ if (_modelStore.default.initialized) {
37
+ _modelStore.default.houseStore.setDoorsVisibility(true);
38
+
39
+ _modelStore.default.houseStore.setFullBuildingVisibility(true);
40
+
41
+ _modelStore.default.houseStore.setCurrentWallsMaterialType('texture');
42
+
43
+ return;
44
+ }
45
+
46
+ _modelStore.default.init(json);
47
+ }, [json]);
48
+
49
+ const getNextWallsMaterialType = () => {
50
+ if (houseStore.wallsMaterialType === 'texture') return 'color';
51
+ return 'texture';
52
+ };
53
+
54
+ const onImageUploaded = _ref2 => {
55
+ let {
56
+ target
57
+ } = _ref2;
58
+ if (!target.files.length) return;
59
+ const reader = new FileReader();
60
+
61
+ reader.onload = e => houseStore.addWallTexture(e.target.result);
62
+
63
+ reader.readAsDataURL(target.files[0]);
64
+ };
65
+
66
+ return /*#__PURE__*/_react.default.createElement("div", {
67
+ className: "widget-tab__model"
68
+ }, /*#__PURE__*/_react.default.createElement("div", {
69
+ className: "widget-tab__model-scene"
70
+ }), /*#__PURE__*/_react.default.createElement("div", {
71
+ className: "widget-tab-menu"
72
+ }, /*#__PURE__*/_react.default.createElement("ul", null, /*#__PURE__*/_react.default.createElement("li", {
73
+ onClick: () => setMenuState(!menuState)
74
+ }, "Menu"), menuState && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("li", {
75
+ onClick: () => _modelStore.default.setCurrentControlsType('wasd')
76
+ }, "WASD"), /*#__PURE__*/_react.default.createElement("li", {
77
+ onClick: () => _modelStore.default.setCurrentControlsType('plan')
78
+ }, "View from above"), /*#__PURE__*/_react.default.createElement("li", {
79
+ onClick: () => _modelStore.default.setCurrentControlsType('orbit')
80
+ }, "Free camera"), /*#__PURE__*/_react.default.createElement("li", {
81
+ onClick: () => houseStore.setPlanMode()
82
+ }, "Plan"), /*#__PURE__*/_react.default.createElement("li", {
83
+ onClick: () => houseStore.setFullBuildingVisibility(!houseStore.isFullBuildingVisible)
84
+ }, houseStore.isFullBuildingVisible ? 'Hide walls' : 'Show walls'), /*#__PURE__*/_react.default.createElement("li", {
85
+ onClick: () => houseStore.setDoorsVisibility(!houseStore.isDoorsVisible)
86
+ }, houseStore.isDoorsVisible ? 'Hide doors' : 'Show doors'), /*#__PURE__*/_react.default.createElement("li", {
87
+ onClick: () => houseStore.setCurrentWallsMaterialType(getNextWallsMaterialType())
88
+ }, "Material: ", houseStore.wallsMaterialType === 'texture' ? 'Texture' : 'Color'), /*#__PURE__*/_react.default.createElement("li", null, /*#__PURE__*/_react.default.createElement("label", null, "Wall color:", /*#__PURE__*/_react.default.createElement("input", {
89
+ type: "color",
90
+ onChange: _ref3 => {
91
+ let {
92
+ target
93
+ } = _ref3;
94
+ return houseStore.setCurrentWallColor(target.value);
95
+ },
96
+ style: {
97
+ background: houseStore.wallsColor
98
+ },
99
+ value: houseStore.wallsColor
100
+ }))), /*#__PURE__*/_react.default.createElement("li", null, "Wall texture:", /*#__PURE__*/_react.default.createElement("div", {
101
+ className: "widget-tab-menu__wallpapers"
102
+ }, houseStore && houseStore.wallsTextures.map((_ref4, index) => {
103
+ let {
104
+ image,
105
+ texture
106
+ } = _ref4;
107
+ return /*#__PURE__*/_react.default.createElement("img", {
108
+ key: index,
109
+ src: image,
110
+ onClick: () => houseStore.setCurrentWallTexture(texture),
111
+ alt: "texture=".concat(index)
112
+ });
113
+ }))), /*#__PURE__*/_react.default.createElement("li", null, /*#__PURE__*/_react.default.createElement("label", null, "Upload wall texture", /*#__PURE__*/_react.default.createElement("input", {
114
+ onChange: onImageUploaded,
115
+ type: "file",
116
+ accept: ".jpg, .jpeg, .png"
117
+ })))))));
118
+ });
119
+ var _default = ModelTab;
120
+ exports.default = _default;