@kimap/indoor-positioning-sdk-vue2 6.0.2 → 6.0.5
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 +1 -1
- package/src/core/KimapSDK.js +11 -4
- package/src/core/SceneCore.js +121 -4
package/package.json
CHANGED
package/src/core/KimapSDK.js
CHANGED
|
@@ -652,6 +652,9 @@ KimapSDK.prototype.showSingleFloor = function(floorIndex) {
|
|
|
652
652
|
if (!this.floorGroups || this.floorGroups.length === 0) return;
|
|
653
653
|
var self = this;
|
|
654
654
|
|
|
655
|
+
// 切换单楼层时移除 ALL 周边建筑物
|
|
656
|
+
this.core._removeAllModeBuildings();
|
|
657
|
+
|
|
655
658
|
var isFromAll = (this._currentMode === 'all');
|
|
656
659
|
var ANIM_DURATION = 300; // ms
|
|
657
660
|
var startTime = Date.now();
|
|
@@ -792,12 +795,15 @@ KimapSDK.prototype.showAllFloors = function() {
|
|
|
792
795
|
// 相机动画飞到 ALL 外景视角(参考正式版 _zoomToShowAllFloors)
|
|
793
796
|
this._zoomToShowAllFloors();
|
|
794
797
|
|
|
798
|
+
// 渲染 ALL 模式周边建筑物
|
|
799
|
+
this.core._addAllModeBuildings();
|
|
800
|
+
|
|
795
801
|
this._currentShowingFloorIndex = -1; // ALL 状态
|
|
796
802
|
this._currentMode = 'all';
|
|
797
803
|
};
|
|
798
804
|
|
|
799
805
|
/**
|
|
800
|
-
* 多楼层:相机动画飞到能看到所有楼层的位置(ALL
|
|
806
|
+
* 多楼层:相机动画飞到能看到所有楼层的位置(ALL 外景视角,从侧方斜俯视,俯角25°,拉远)
|
|
801
807
|
* @private
|
|
802
808
|
*/
|
|
803
809
|
KimapSDK.prototype._zoomToShowAllFloors = function() {
|
|
@@ -821,10 +827,11 @@ KimapSDK.prototype._zoomToShowAllFloors = function() {
|
|
|
821
827
|
box.getSize(size);
|
|
822
828
|
var maxSize = Math.max(size.x, size.z);
|
|
823
829
|
|
|
824
|
-
// ALL侧方斜俯视:方位角-45°,俯角
|
|
830
|
+
// ALL侧方斜俯视:方位角-45°,俯角25°(polar≈65°),模型占屏幕60%(拉远)
|
|
825
831
|
var azimuthDeg = -45;
|
|
826
|
-
var pitchDeg =
|
|
827
|
-
var
|
|
832
|
+
var pitchDeg = 25;
|
|
833
|
+
var pitchDeg = 35;
|
|
834
|
+
var screenFillFactor = 0.6;
|
|
828
835
|
var aspect = (this.core.camera && this.core.camera.aspect) || (window.innerWidth / window.innerHeight);
|
|
829
836
|
var fovRad = (this.core.camera && this.core.camera.fov) ? this.core.camera.fov * Math.PI / 180 : (60 * Math.PI / 180);
|
|
830
837
|
var hDist = maxSize / 2 / screenFillFactor / Math.tan(Math.atan(Math.tan(fovRad / 2) / aspect));
|
package/src/core/SceneCore.js
CHANGED
|
@@ -70,6 +70,7 @@ function SceneCore(config) {
|
|
|
70
70
|
this.floorOriginalY = []; // 每个楼层的原始世界Y偏移(含间隙)
|
|
71
71
|
// 楼层切换动画状态
|
|
72
72
|
this.floorAnim = null; // { running: bool, startTime: ms, duration: ms, steps: [] }
|
|
73
|
+
this._allModeBuildings = []; // ALL 模式下的周边模拟建筑物
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
/**
|
|
@@ -95,6 +96,7 @@ SceneCore.prototype.init = function() {
|
|
|
95
96
|
self.initRenderer();
|
|
96
97
|
self.initControls(OrbitControls);
|
|
97
98
|
self.setupLights();
|
|
99
|
+
self.setupGround();
|
|
98
100
|
self.addCoordinateHelper();
|
|
99
101
|
return Promise.all([loadOBJLoader(), loadMTLLoader()]);
|
|
100
102
|
})
|
|
@@ -230,6 +232,39 @@ SceneCore.prototype.setupLights = function() {
|
|
|
230
232
|
this.scene.add(hemisphereLight);
|
|
231
233
|
};
|
|
232
234
|
|
|
235
|
+
/**
|
|
236
|
+
* 设置地面(纯色 + 网格)
|
|
237
|
+
*/
|
|
238
|
+
SceneCore.prototype.setupGround = function() {
|
|
239
|
+
var origin = this.coordinateSystem.origin;
|
|
240
|
+
var maxX = this.coordinateSystem.maxX;
|
|
241
|
+
var maxZ = this.coordinateSystem.maxY;
|
|
242
|
+
|
|
243
|
+
// 地面尺寸稍大于地图,留出边距
|
|
244
|
+
var groundSize = Math.max(maxX, maxZ) * 1.6;
|
|
245
|
+
|
|
246
|
+
// 地面纯色平面(不接收阴影、不投射阴影)
|
|
247
|
+
var groundGeo = new THREE.PlaneGeometry(groundSize, groundSize);
|
|
248
|
+
var groundMat = new THREE.MeshLambertMaterial({
|
|
249
|
+
color: 0xf7f7f7,
|
|
250
|
+
side: THREE.DoubleSide
|
|
251
|
+
});
|
|
252
|
+
var ground = new THREE.Mesh(groundGeo, groundMat);
|
|
253
|
+
ground.rotation.x = -Math.PI / 2;
|
|
254
|
+
ground.position.set(origin.x + maxX / 2, -0.001, origin.z);
|
|
255
|
+
ground.receiveShadow = false;
|
|
256
|
+
this.scene.add(ground);
|
|
257
|
+
|
|
258
|
+
// 网格线(与地面颜色协调,线色 #d0d0d0,格间距 maxX/10)
|
|
259
|
+
var gridSize = Math.max(maxX, maxZ) * 1.5;
|
|
260
|
+
var gridDivisions = Math.max(10, Math.round(gridSize / (maxX / 10)));
|
|
261
|
+
var grid = new THREE.GridHelper(gridSize, gridDivisions, 0xbdbdbd, 0xd0d0d0);
|
|
262
|
+
grid.position.set(origin.x + maxX / 2, 0, origin.z);
|
|
263
|
+
grid.material.opacity = 0.5;
|
|
264
|
+
grid.material.transparent = true;
|
|
265
|
+
this.scene.add(grid);
|
|
266
|
+
};
|
|
267
|
+
|
|
233
268
|
/**
|
|
234
269
|
* 添加坐标辅助器
|
|
235
270
|
*/
|
|
@@ -510,11 +545,15 @@ SceneCore.prototype._adjustCameraToAllFloors = function() {
|
|
|
510
545
|
box.getSize(size);
|
|
511
546
|
var maxSize = Math.max(size.x, size.z);
|
|
512
547
|
|
|
513
|
-
//
|
|
514
|
-
var pitchDeg =
|
|
548
|
+
// 从侧方斜俯视:方位角-45°,俯角25°(polar≈65°),模型占屏幕60%(拉远)
|
|
549
|
+
var pitchDeg = 25;
|
|
515
550
|
var azimuthDeg = -45;
|
|
516
|
-
var
|
|
517
|
-
var
|
|
551
|
+
var screenFillFactor = 0.6;
|
|
552
|
+
var aspect = this.camera ? this.camera.aspect : (this.container.clientWidth / this.container.clientHeight);
|
|
553
|
+
var fovRad = this.camera ? this.camera.fov * Math.PI / 180 : (60 * Math.PI / 180);
|
|
554
|
+
var hDist = maxSize / 2 / screenFillFactor / Math.tan(Math.atan(Math.tan(fovRad / 2) / aspect));
|
|
555
|
+
var vDist = maxSize / 2 / screenFillFactor / Math.tan(fovRad / 2);
|
|
556
|
+
var distance = Math.max(hDist, vDist);
|
|
518
557
|
|
|
519
558
|
var pitchRad = pitchDeg * Math.PI / 180;
|
|
520
559
|
var azimuthRad = azimuthDeg * Math.PI / 180;
|
|
@@ -540,6 +579,84 @@ SceneCore.prototype._adjustCameraToAllFloors = function() {
|
|
|
540
579
|
}
|
|
541
580
|
};
|
|
542
581
|
|
|
582
|
+
/**
|
|
583
|
+
* ALL 模式:在四周渲染 4 栋模拟建筑物(淡蓝色 0.5 透明度,无光遮挡)
|
|
584
|
+
* @private
|
|
585
|
+
*/
|
|
586
|
+
SceneCore.prototype._addAllModeBuildings = function() {
|
|
587
|
+
this._removeAllModeBuildings();
|
|
588
|
+
|
|
589
|
+
try {
|
|
590
|
+
var allMeshes = [];
|
|
591
|
+
this.floorGroups.forEach(function(group) {
|
|
592
|
+
group.traverse(function(child) {
|
|
593
|
+
if (child.isMesh) allMeshes.push(child);
|
|
594
|
+
});
|
|
595
|
+
});
|
|
596
|
+
if (allMeshes.length === 0) return;
|
|
597
|
+
|
|
598
|
+
var box = new THREE.Box3();
|
|
599
|
+
allMeshes.forEach(function(mesh) { box.expandByObject(mesh); });
|
|
600
|
+
var boxMin = new THREE.Vector3();
|
|
601
|
+
var boxMax = new THREE.Vector3();
|
|
602
|
+
box.getMin(boxMin);
|
|
603
|
+
box.getMax(boxMax);
|
|
604
|
+
var centerX = (boxMin.x + boxMax.x) / 2;
|
|
605
|
+
var centerZ = (boxMin.z + boxMax.z) / 2;
|
|
606
|
+
var modelW = boxMax.x - boxMin.x;
|
|
607
|
+
var modelD = boxMax.z - boxMin.z;
|
|
608
|
+
var modelH = boxMax.y - boxMin.y;
|
|
609
|
+
|
|
610
|
+
// 建筑物高度:取模型高度的 1.5~2.5 倍,宽度为模型宽度的 0.4~0.6 倍
|
|
611
|
+
var baseW = modelW * 0.45;
|
|
612
|
+
var baseD = modelD * 0.45;
|
|
613
|
+
var heights = [modelH * 1.8, modelH * 2.2, modelH * 1.5, modelH * 2.5];
|
|
614
|
+
// 四周分布:前后左右,距模型边缘约 0.6 倍模型尺寸
|
|
615
|
+
var offsets = [
|
|
616
|
+
{ x: 0, z: -(modelD / 2 + modelD * 0.55), w: baseW * 1.1, d: baseD * 0.9 },
|
|
617
|
+
{ x: 0, z: modelD / 2 + modelD * 0.55, w: baseW, d: baseD },
|
|
618
|
+
{ x: modelW / 2 + modelW * 0.55, z: 0, w: baseW * 0.9, d: baseD * 1.1 },
|
|
619
|
+
{ x: -(modelW / 2 + modelW * 0.55), z: 0, w: baseW, d: baseD * 1.0 }
|
|
620
|
+
];
|
|
621
|
+
|
|
622
|
+
var self = this;
|
|
623
|
+
heights.forEach(function(h, i) {
|
|
624
|
+
var o = offsets[i];
|
|
625
|
+
var geo = new THREE.BoxGeometry(o.w, h, o.d);
|
|
626
|
+
var mat = new THREE.MeshBasicMaterial({
|
|
627
|
+
color: 0x9ecfef,
|
|
628
|
+
transparent: true,
|
|
629
|
+
opacity: 0.5,
|
|
630
|
+
depthWrite: false
|
|
631
|
+
});
|
|
632
|
+
var mesh = new THREE.Mesh(geo, mat);
|
|
633
|
+
mesh.position.set(centerX + o.x, h / 2, centerZ + o.z);
|
|
634
|
+
mesh.castShadow = false;
|
|
635
|
+
mesh.receiveShadow = false;
|
|
636
|
+
self.scene.add(mesh);
|
|
637
|
+
self._allModeBuildings.push(mesh);
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
console.log('ALL 模式:已添加 ' + self._allModeBuildings.length + ' 栋周边建筑物');
|
|
641
|
+
} catch (e) {
|
|
642
|
+
console.warn('添加 ALL 模式建筑物失败:', e);
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* 移除 ALL 模式的周边建筑物
|
|
648
|
+
* @private
|
|
649
|
+
*/
|
|
650
|
+
SceneCore.prototype._removeAllModeBuildings = function() {
|
|
651
|
+
var self = this;
|
|
652
|
+
this._allModeBuildings.forEach(function(mesh) {
|
|
653
|
+
self.scene.remove(mesh);
|
|
654
|
+
mesh.geometry.dispose();
|
|
655
|
+
mesh.material.dispose();
|
|
656
|
+
});
|
|
657
|
+
this._allModeBuildings = [];
|
|
658
|
+
};
|
|
659
|
+
|
|
543
660
|
/**
|
|
544
661
|
* 相机对准指定楼层(多楼层切换/ALL 时分别调用)
|
|
545
662
|
* @param {number} floorIndex - 楼层索引
|