@sequent-org/ifc-viewer 1.2.4-ci.24.0 → 1.2.4-ci.26.0

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sequent-org/ifc-viewer",
3
3
  "private": false,
4
- "version": "1.2.4-ci.24.0",
4
+ "version": "1.2.4-ci.26.0",
5
5
  "type": "module",
6
6
  "description": "IFC 3D model viewer component for web applications - fully self-contained with local IFCLoader",
7
7
  "main": "src/index.js",
package/src/IfcViewer.js CHANGED
@@ -13,18 +13,8 @@
13
13
  import { Viewer } from "./viewer/Viewer.js";
14
14
  import { IfcService } from "./ifc/IfcService.js";
15
15
  import { IfcTreeView } from "./ifc/IfcTreeView.js";
16
+ import './style.css';
16
17
 
17
- // Загружаем стили при импорте IfcViewer
18
- if (typeof window !== 'undefined' && !document.querySelector('style[data-ifc-viewer]')) {
19
- import('./style.css').then(() => {
20
- // Добавляем маркер, что стили загружены
21
- const style = document.createElement('style');
22
- style.setAttribute('data-ifc-viewer', 'loaded');
23
- document.head.appendChild(style);
24
- }).catch(error => {
25
- console.warn('IfcViewer: не удалось загрузить стили:', error.message);
26
- });
27
- }
28
18
 
29
19
  export class IfcViewer {
30
20
  /**
@@ -302,7 +292,7 @@ export class IfcViewer {
302
292
  </div>
303
293
 
304
294
  <!-- Верхняя панель управления -->
305
- <div id="ifcToolbar" class="d-flex px-4" style="border:0px red solid; width: 250px; position: absolute; z-index: 1000; justify-content:space-between; bottom: 10px; left: calc(50% - 125px); ">
295
+ <div id="ifcToolbar" class="d-flex px-4" style="border:0px red solid; width: 250px; position: absolute; z-index: 60; justify-content:space-between; bottom: 10px; left: calc(50% - 125px); ">
306
296
 
307
297
  <div class="navbar-end flex gap-2">
308
298
 
@@ -315,7 +305,7 @@ export class IfcViewer {
315
305
  <div class="join">
316
306
  <button class="btn btn-sm join-item" id="ifcClipX" style="margin-right:2px"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="MuiSvgIcon-root MuiSvgIcon-fontSizeLarge" focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M9.6 3v9.07l3.87-1.72a2 2 0 01.81-.17 2.08 2.08 0 011.77 3.09 1.09 1.09 0 01-.56.56l-4.36 1.94L21.6 21V9z"></path><path d="M4.74 15.33l9.14-4.07a1 1 0 011.32.51 1 1 0 01-.51 1.32l-9.14 4.07 4 1.52L9 20l-6.6-2.53 2.53-6.6 1.32.51z"></path></svg></button>
317
307
  <button class="btn btn-sm join-item" id="ifcClipZ" style="margin-right:2px"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="MuiSvgIcon-root MuiSvgIcon-fontSizeLarge" focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M8 13.82a1.09 1.09 0 01-.56-.56 2.08 2.08 0 011.78-3.09 2 2 0 01.81.17l3.87 1.72V3l-11 6v12l9.54-5.2z"></path><path d="M17.24 11.37l1.32-.51 2.53 6.6L14.5 20l-.5-1.32 4-1.52-9.18-4.07a1 1 0 01-.51-1.32 1 1 0 011.32-.51l9.14 4.07z"></path></svg></button>
318
- <button class="btn btn-sm join-item" id="ifcClipY" style="margin-right:2px"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="MuiSvgIcon-root MuiSvgIcon-fontSizeLarge" focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M14.25 11.18v3.52A1.87 1.87 0 0111 15.88a1 1 0 01-.32-.72V11.1l-9 4.5L12.45 21l9.9-5.4z"></path><path d="M8.85 8.4L8 7.5 12.45 3 17 7.5l-.9.9-2.7-2.7v9a.9.9 0 01-.9.9.9.9 0 01-.9-.9v-9z"></path></svg></button>
308
+ <button class="btn btn-sm join-item" id="ifcClipY" style="margin-right:0px"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="MuiSvgIcon-root MuiSvgIcon-fontSizeLarge" focusable="false" viewBox="0 0 24 24" aria-hidden="true"><path d="M14.25 11.18v3.52A1.87 1.87 0 0111 15.88a1 1 0 01-.32-.72V11.1l-9 4.5L12.45 21l9.9-5.4z"></path><path d="M8.85 8.4L8 7.5 12.45 3 17 7.5l-.9.9-2.7-2.7v9a.9.9 0 01-.9.9.9.9 0 01-.9-.9v-9z"></path></svg></button>
319
309
  </div>
320
310
 
321
311
  </div>
@@ -16,8 +16,8 @@
16
16
 
17
17
  /* === CSS VARIABLES (THEME COLORS) === */
18
18
  .ifc-viewer-container {
19
- --color-primary: #3b82f6;
20
- --color-primary-hover: #2563eb;
19
+ --color-primary: #80D8FF;
20
+ --color-primary-hover: #80D8FF;
21
21
  --color-secondary: #64748b;
22
22
  --color-secondary-hover: #475569;
23
23
  --color-neutral: #374151;
@@ -412,3 +412,63 @@
412
412
  .text-orange-600 { color: #ea580c; }
413
413
  .text-gray-600 { color: #4b5563; }
414
414
  .text-gray-500 { color: #6b7280; }
415
+
416
+ /* === TOOLBAR BUTTONS SHADOWS === */
417
+ #ifcToolbar .join {
418
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.25) !important;
419
+ transition: box-shadow 0.2s ease !important;
420
+
421
+ }
422
+
423
+ /* #ifcToolbar .btn:hover {
424
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3) !important;
425
+ }
426
+
427
+ #ifcToolbar .btn:active {
428
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2) !important;
429
+ } */
430
+
431
+ /* === HOME BUTTON === */
432
+ .nav-cube-home-btn {
433
+ /* Позиционирование */
434
+ position: absolute;
435
+ z-index: 40;
436
+
437
+ /* Стили как у .btn .btn-sm */
438
+ display: inline-flex;
439
+ align-items: center;
440
+ justify-content: center;
441
+ border-radius: var(--border-radius);
442
+ height: 2rem;
443
+ min-height: 2rem;
444
+ width: 2rem;
445
+ padding: 0;
446
+ font-size: 0.75rem;
447
+ font-weight: 600;
448
+ text-decoration: none;
449
+ border: 1px solid transparent;
450
+ cursor: pointer;
451
+ user-select: none;
452
+ transition-property: color, background-color, border-color, box-shadow;
453
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
454
+ transition-duration: 200ms;
455
+ background-color: var(--color-base-200);
456
+ color: var(--color-neutral);
457
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
458
+ }
459
+
460
+ .nav-cube-home-btn:hover {
461
+ background-color: var(--color-base-300);
462
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
463
+ }
464
+
465
+ .nav-cube-home-btn:active {
466
+ background-color: var(--color-base-300);
467
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
468
+ }
469
+
470
+ .nav-cube-home-btn svg {
471
+ fill: #000000;
472
+ width: 18px;
473
+ height: 18px;
474
+ }
@@ -30,12 +30,12 @@ export class NavCube {
30
30
  // Полупрозрачный куб с окрашенными сторонами (+X/-X, +Y/-Y, +Z/-Z)
31
31
  const geom = new THREE.BoxGeometry(1, 1, 1);
32
32
  const mats = [
33
- new THREE.MeshBasicMaterial({ color: 0xd32f2f, transparent: true, opacity: this.faceOpacity }), // +X (red)
34
- new THREE.MeshBasicMaterial({ color: 0x7f0000, transparent: true, opacity: this.faceOpacity }), // -X (dark red)
35
- new THREE.MeshBasicMaterial({ color: 0x388e3c, transparent: true, opacity: this.faceOpacity }), // +Y (green)
36
- new THREE.MeshBasicMaterial({ color: 0x1b5e20, transparent: true, opacity: this.faceOpacity }), // -Y (dark green)
37
- new THREE.MeshBasicMaterial({ color: 0x1976d2, transparent: true, opacity: this.faceOpacity }), // +Z (blue)
38
- new THREE.MeshBasicMaterial({ color: 0x0d47a1, transparent: true, opacity: this.faceOpacity }), // -Z (dark blue)
33
+ new THREE.MeshBasicMaterial({ color: 0x80CBC4, transparent: true, opacity: this.faceOpacity }), // +X (сзади - зеленый)
34
+ new THREE.MeshBasicMaterial({ color: 0xA5D6A7, transparent: true, opacity: this.faceOpacity }), // -X (спереди - зеленый)
35
+ new THREE.MeshBasicMaterial({ color: 0xFF8A65, transparent: true, opacity: this.faceOpacity }), // +Y (верх - красный )
36
+ new THREE.MeshBasicMaterial({ color: 0xEF9A9A, transparent: true, opacity: this.faceOpacity }), // -Y (низ - красный)
37
+ new THREE.MeshBasicMaterial({ color: 0x90CAF9, transparent: true, opacity: this.faceOpacity }), // +Z (справа - синий)
38
+ new THREE.MeshBasicMaterial({ color: 0x9FA8DA, transparent: true, opacity: this.faceOpacity }), // -Z (слева - синий)
39
39
  ];
40
40
  this.cube = new THREE.Mesh(geom, mats);
41
41
  this.cube.name = "nav-cube";
@@ -53,7 +53,7 @@ export class NavCube {
53
53
 
54
54
  // Рёбра для читабельности
55
55
  const edges = new THREE.EdgesGeometry(geom, 1);
56
- const lineMat = new THREE.LineBasicMaterial({ color: 0x111111, depthTest: true });
56
+ const lineMat = new THREE.LineBasicMaterial({ color: 0xEEEEEE, depthTest: true });
57
57
  this.cubeEdges = new THREE.LineSegments(edges, lineMat);
58
58
  this.cubeEdges.renderOrder = 999;
59
59
  this.cube.add(this.cubeEdges);
@@ -90,20 +90,12 @@ export class NavCube {
90
90
  this.homeBtn = document.createElement('button');
91
91
  this.homeBtn.type = 'button';
92
92
  this.homeBtn.title = 'Home';
93
- this.homeBtn.textContent = '';
94
- this.homeBtn.style.position = 'absolute';
95
- this.homeBtn.style.zIndex = '40';
96
- this.homeBtn.style.width = '28px';
97
- this.homeBtn.style.height = '28px';
98
- this.homeBtn.style.lineHeight = '28px';
99
- this.homeBtn.style.textAlign = 'center';
100
- this.homeBtn.style.borderRadius = '6px';
101
- this.homeBtn.style.border = '1px solid rgba(255,255,255,0.4)';
102
- this.homeBtn.style.background = 'rgba(0,0,0,0.45)';
103
- this.homeBtn.style.color = '#fff';
104
- this.homeBtn.style.cursor = 'pointer';
105
- this.homeBtn.style.userSelect = 'none';
106
- this.homeBtn.style.font = '14px/28px system-ui, sans-serif';
93
+ this.homeBtn.className = 'nav-cube-home-btn';
94
+ this.homeBtn.innerHTML = `
95
+ <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="icon">
96
+ <path d="M946.5 505L534.6 93.4a31.93 31.93 0 0 0-45.2 0L77.5 505c-12 12-18.8 28.3-18.8 45.3 0 35.3 28.7 64 64 64h43.4V908c0 17.7 14.3 32 32 32H448V716h112v224h265.9c17.7 0 32-14.3 32-32V614.3h43.4c17 0 33.3-6.7 45.3-18.8 24.9-25 24.9-65.5-.1-90.5z"/>
97
+ </svg>
98
+ `;
107
99
  // Позиция задаётся в renderOverlay относительно текущего размера
108
100
  this.homeBtn.addEventListener('click', () => { try { this.onHome && this.onHome(); } catch(_) {} });
109
101
  try { this.container.appendChild(this.homeBtn); } catch(_) {}
@@ -177,15 +169,15 @@ export class NavCube {
177
169
 
178
170
  // Позиционируем кнопку Home слева от куба
179
171
  if (this.homeBtn) {
180
- this.homeBtn.style.top = `${this.marginPx + 2}px`;
181
- this.homeBtn.style.left = `${Math.max(2, fullW - this.marginPx - vpSize - 32)}px`;
172
+ this.homeBtn.style.top = `${this.marginPx + 20}px`;
173
+ this.homeBtn.style.left = `${Math.max(2, fullW - this.marginPx - vpSize - 60)}px`;
182
174
  }
183
175
  }
184
176
 
185
177
  // ================= Подписи граней =================
186
178
  #addFaceLabels() {
187
179
  const makeFaceTexture = (text) => {
188
- const size = 512; // квадрат для равномерности
180
+ const size = Math.floor(512 / 0.98); // квадрат для равномерности
189
181
  const canvas = document.createElement('canvas');
190
182
  canvas.width = size; canvas.height = size;
191
183
  const ctx = canvas.getContext('2d');
@@ -193,12 +185,13 @@ export class NavCube {
193
185
  ctx.clearRect(0, 0, size, size);
194
186
  // Чёрный крупный текст по центру
195
187
  ctx.fillStyle = '#000';
196
- // Уменьшаем шрифт примерно в 1.2 раза относительно прошлого (0.42 -> ~0.35)
197
- const fontPx = Math.floor(size * 0.35);
188
+ // Уменьшаем шрифт для лучшего размещения длинных слов
189
+ const fontPx = Math.floor(size * 0.2); // было 0.35, стало 0.25
198
190
  ctx.font = `bold ${fontPx}px sans-serif`;
199
191
  ctx.textAlign = 'center';
200
192
  ctx.textBaseline = 'middle';
201
193
  ctx.fillText(text.toUpperCase(), size / 2, size / 2);
194
+
202
195
  const tex = new THREE.CanvasTexture(canvas);
203
196
  tex.minFilter = THREE.LinearFilter;
204
197
  tex.magFilter = THREE.LinearFilter;
@@ -209,8 +202,8 @@ export class NavCube {
209
202
  const tex = makeFaceTexture(text);
210
203
  if (!tex) return null;
211
204
  const mat = new THREE.MeshBasicMaterial({ map: tex, transparent: true, depthTest: true, depthWrite: false });
212
- // Уменьшаем паддинги плашки: максимально приближаем к размеру грани
213
- const plane = new THREE.Mesh(new THREE.PlaneGeometry(0.995, 0.995), mat);
205
+ // Уменьшаем размер плашки для лучшего размещения текста
206
+ const plane = new THREE.Mesh(new THREE.PlaneGeometry(0.98, 0.98), mat);
214
207
  // Ориентируем плоскость, чтобы нормаль смотрела как normal
215
208
  const q = new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 0, 1), normal);
216
209
  plane.setRotationFromQuaternion(q);