Преглед изворни кода

Merge branch 'master' of http://git.fmode.cn:3000/0225273/APPmy

0225268 пре 4 месеци
родитељ
комит
8814404b4f

+ 4 - 0
src/app/app-routing.module.ts

@@ -68,6 +68,10 @@ const routes: Routes = [
   {
     path: 'consult',
     loadChildren: () => import('./consult/consult.module').then( m => m.ConsultPageModule)
+  },
+  {
+    path: 'babylon',
+    loadChildren: () => import('./babylon/babylon.module').then( m => m.BabylonPageModule)
   }
 
 

+ 17 - 0
src/app/babylon/babylon-routing.module.ts

@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+import { BabylonPage } from './babylon.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: BabylonPage
+  }
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule],
+})
+export class BabylonPageRoutingModule {}

+ 20 - 0
src/app/babylon/babylon.module.ts

@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { IonicModule } from '@ionic/angular';
+
+import { BabylonPageRoutingModule } from './babylon-routing.module';
+
+import { BabylonPage } from './babylon.page';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    BabylonPageRoutingModule
+  ],
+  declarations: [BabylonPage]
+})
+export class BabylonPageModule {}

+ 6 - 0
src/app/babylon/babylon.page.html

@@ -0,0 +1,6 @@
+<div class="list">
+  <div (click)="showCharacter(item?.name)" class="character" *ngFor="let item of CharacterMeshList">
+    <h1>{{item?.name}}</h1>
+  </div>
+</div>
+<canvas id="renderCanvas" touch-action="none"></canvas>

+ 43 - 0
src/app/babylon/babylon.page.scss

@@ -0,0 +1,43 @@
+// 调试面板
+#scene-explorer-host {
+    position: absolute !important;
+}
+#sceneExplorer{
+    position:absolute!important;
+    height:100vh!important;
+}
+.babylonDebugLayer {
+    position: absolute;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    width: 300px; /* 调试层的宽度 */
+    background-color: rgba(255, 255, 255, 0.8); /* 背景颜色和透明度 */
+    z-index: 20; /* 确保调试层在最顶层 */
+    overflow: auto; /* 如果内容过多,添加滚动条 */
+  }
+  
+  .babylonDebugLayer .content {
+    padding: 10px;
+  }
+
+// 展示区
+#renderCanvas {
+    width: 100vw;
+    height: 100vh;
+    display: block;
+    font-size: 0;
+    z-index: 1;
+}
+
+.list{
+    position: absolute;
+    top:20px;
+    z-index: 10;
+    width: 100vw;
+    display: flex;
+    justify-content: center;
+    .character{
+        
+    }
+}

+ 17 - 0
src/app/babylon/babylon.page.spec.ts

@@ -0,0 +1,17 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { BabylonPage } from './babylon.page';
+
+describe('BabylonPage', () => {
+  let component: BabylonPage;
+  let fixture: ComponentFixture<BabylonPage>;
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(BabylonPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 174 - 0
src/app/babylon/babylon.page.ts

@@ -0,0 +1,174 @@
+import { Component, OnInit } from '@angular/core';
+import * as BABYLON from "@babylonjs/core/Legacy/legacy";
+import { Engine, Scene } from "@babylonjs/core";
+import { FreeCamera } from "@babylonjs/core/Cameras/freeCamera";
+import { HemisphericLight } from "@babylonjs/core/Lights/hemisphericLight";
+import { Vector3 } from "@babylonjs/core/Maths/math.vector";
+import { CreateGround } from "@babylonjs/core/Meshes/Builders/groundBuilder";
+import { CreateSphere } from "@babylonjs/core/Meshes/Builders/sphereBuilder";
+import { GridMaterial } from "@babylonjs/materials/grid/gridMaterial";
+
+import "@babylonjs/loaders/glTF";
+
+@Component({
+  selector: 'app-babylon',
+  templateUrl: './babylon.page.html',
+  styleUrls: ['./babylon.page.scss'],
+})
+export class BabylonPage implements OnInit {
+
+  private engine: BABYLON.Engine|undefined;
+  private scene: BABYLON.Scene|undefined;
+
+  CharacterMap:any = {}
+  CharacterMeshList = [
+    {name:"古风少女",
+    dirPath:"https://nova-cloud.obs.cn-south-1.myhuaweicloud.com/storage/3d/model/ancient-chinese-woman/gltf/",
+    filePath:"scene.gltf"},
+    {name:"中国象棋",
+    dirPath:"https://nova-cloud.obs.cn-south-1.myhuaweicloud.com/storage/3d/model/chinese-chess/gltf/",
+    filePath:"scene.gltf"},
+    {name:"卡通异瞳少女",
+    dirPath:"https://nova-cloud.obs.cn-south-1.myhuaweicloud.com/storage/3d/model/vtuber-selen/gltf/",
+    filePath:"scene.gltf"},
+    {name:"中国老杯子",
+    dirPath:"https://nova-cloud.obs.cn-south-1.myhuaweicloud.com/storage/3d/model/chinese-iron-cup/",
+    filePath:"scene.gltf"},
+    {name:"中国城市lowpoly",
+    dirPath:"https://nova-cloud.obs.cn-south-1.myhuaweicloud.com/storage/3d/model/chinese-city-lowpoly/gltf/",
+    filePath:"scene.gltf"},
+
+  ]
+  constructor() { }
+
+  ngOnInit() {
+    this.initBabylon()
+  }
+
+  initBabylon(){
+    // Get the canvas element from the DOM.
+    const canvas:any = document.getElementById("renderCanvas");
+    // Set the canvas size to match the device pixel ratio
+    const devicePixelRatio = window.devicePixelRatio || 1;
+    canvas.width = window.innerWidth * devicePixelRatio;
+    canvas.height = window.innerHeight * devicePixelRatio;
+    this.engine = new BABYLON.Engine(canvas, true);
+    this.scene = new BABYLON.Scene(this.engine);
+
+    // Create a basic light, aiming 0,1,0 - meaning, to the sky.
+    const light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), this.scene);
+
+    // 加载粒子效果覆盖地面
+    this.loadGroundParticle()
+    
+    // 设置初始相机
+    // Add an ArcRotateCamera to the scene and attach it to the canvas
+    // let initPositon = new BABYLON.Vector3(0,12,0)
+    let initPositon = new BABYLON.Vector3(0,0,0)
+    let beta = Math.PI / 2.5 // 镜头初始 纬度 Math.PI / 3 斜下45度
+    let radius = 20 // 镜头初始半径
+    const camera = new BABYLON.ArcRotateCamera('camera1', Math.PI / 2, beta, radius, initPositon, this.scene);
+    camera.attachControl(canvas, true);
+
+    // Load the FBX model
+
+    this.CharacterMeshList.forEach(character=>{
+      BABYLON.SceneLoader.ImportMesh('', character.dirPath, character.filePath, this.scene, (meshes, particleSystems, skeletons) => {
+        console.log(meshes)
+        // characterMesh.isVisible
+        meshes.forEach(mesh=>mesh.isVisible=false)
+        this.CharacterMap[character?.name] = {
+          meshes:meshes,
+          particleSystems:particleSystems,
+          skeletons:skeletons
+        }
+        if (skeletons.length > 0) {
+          this.scene?.beginAnimation(skeletons[0], 0, 100, true);
+        }
+      });
+    })
+    setTimeout(() => {
+      this.showCharacter("机器人")
+    }, 3000);
+    
+
+    // Register a render loop to repeatedly render the scene.
+    this.engine.runRenderLoop(() => {
+      this.scene?.render();
+    });
+
+    // 开启调试层,用于抓取角度
+    this.scene.debugLayer.show();
+
+    // Watch for browser/canvas resize events
+    window.addEventListener('resize', () => {
+      this.engine?.resize();
+    });
+  }
+
+  showCharacter(name?:string){
+    if(!name) return
+
+    Object.keys(this.CharacterMap).forEach(tempname=>{
+      let character = this.CharacterMap[tempname];
+      if(tempname==name){
+        if(character.meshes?.length){
+          character.meshes.forEach((mesh:any)=>mesh.isVisible=true)
+        }
+      }else{
+        if(character.meshes?.length){
+          character.meshes.forEach((mesh:any)=>mesh.isVisible=false)
+        }
+      }
+    })
+
+   
+  }
+  loadGroundParticle(){
+      if(!this.scene) return
+      // 创建粒子系统
+      const particleSystem = new BABYLON.ParticleSystem("particles", 2000, this.scene);
+
+      // 纹理
+      particleSystem.particleTexture = new BABYLON.Texture("textures/flare.png", this.scene);
+
+      // 发射器
+      particleSystem.emitter = new BABYLON.Vector3(0, 0, 0); // 发射器位置
+      particleSystem.minEmitBox = new BABYLON.Vector3(-300, 0, -300); // 最小发射范围
+      particleSystem.maxEmitBox = new BABYLON.Vector3(300, 0, 300); // 最大发射范围
+
+      // 粒子颜色
+      particleSystem.color1 = new BABYLON.Color4(1, 1, 1, 1);
+      particleSystem.color2 = new BABYLON.Color4(0.5, 0.5, 1, 1);
+      particleSystem.colorDead = new BABYLON.Color4(0, 0, 0.2, 0.5);
+
+      // 粒子大小
+      particleSystem.minSize = 0.1;
+      particleSystem.maxSize = 0.5;
+
+      // 粒子生命周期
+      particleSystem.minLifeTime = 0.3;
+      particleSystem.maxLifeTime = 1.5;
+
+      // 发射速率
+      particleSystem.emitRate = 1000;
+
+      // 粒子方向
+      particleSystem.direction1 = new BABYLON.Vector3(-1, 1, -1);
+      particleSystem.direction2 = new BABYLON.Vector3(1, 1, 1);
+
+      // 重力
+      particleSystem.gravity = new BABYLON.Vector3(0, -9.81, 0);
+
+      // 粒子速度
+      particleSystem.minEmitPower = 0.5;
+      particleSystem.maxEmitPower = 1.5;
+      particleSystem.updateSpeed = 0.01;
+
+      // 开始粒子系统
+      particleSystem.start();
+  }
+
+}
+
+

+ 3 - 0
src/app/consult/consult.page.html

@@ -1,3 +1,6 @@
+<ion-buttons expand="full" fill="clear">
+  <ion-back-button defaultHref="/tabs/tab2"></ion-back-button>
+</ion-buttons>
 <ion-header [translucent]="true">
   <ion-toolbar>
     <ion-title>consult</ion-title>

+ 145 - 33
src/app/tab1/tab1.page.html

@@ -90,7 +90,7 @@
       <ion-icon name="heart-circle"></ion-icon>
       风格测试
     </ion-segment-button>
-    <ion-segment-button value="home">
+    <ion-segment-button (click)="gotoD()">
       <ion-icon name="home"></ion-icon>
       设计我家
     </ion-segment-button>
@@ -554,37 +554,7 @@
   <!-- 软装搭配页 -->
   <div *ngIf="selectedSegment === 'soft'">
     <!-- 软装搭配内容 -->
-    <img src="example3.jpg" alt="Example 4">
-  </div>
-
-  <!-- 户型诊断页 -->
-  <div *ngIf="selectedSegment === 'diagnosis'">
-    <!-- 户型诊断内容 -->
-    <img src="example3.jpg" alt="Example 5">
-  </div>
-
-  <!-- 全屋定制页 -->
-  <div *ngIf="selectedSegment === 'customization'">
-    <!-- 全屋定制内容 -->
-    <img src="example3.jpg" alt="Example 6">
-  </div>
-
-  <!-- 干货百科页 -->
-  <div *ngIf="selectedSegment === 'encyclopedia'">
-    <!-- 干货百科内容 -->
-    <img src="example3.jpg" alt="Example 7">
-  </div>
-
-  <!-- 风格测试页 -->
-  <div *ngIf="selectedSegment === 'style'">
-    <!-- 风格测试内容 -->
-    <img src="example3.jpg" alt="Example 8">
-  </div>
-
-  <!-- 设计我家页 -->
-  <div *ngIf="selectedSegment === 'home'">
-    <!-- 设计我家内容 -->
-    <!-- Swiper轮播图 手动创建 -->
+        <!-- Swiper轮播图 手动创建 -->
     <!-- Slider main container -->
     <button (click)="slide1?.slideNext()">next</button>
     <div #slide1Comp class="swiper">
@@ -669,7 +639,149 @@
         </div>
       </div>
     </div>
-    <img src="example3.jpg" alt="Example 9">
+    <img src="example3.jpg" alt="Example 4">
+  </div>
+
+  <!-- 户型诊断页 -->
+  <div *ngIf="selectedSegment === 'diagnosis'">
+    <!-- 户型诊断内容 -->
+    <img src="example3.jpg" alt="Example 5">
+  </div>
+
+  <!-- 全屋定制页 -->
+  <div *ngIf="selectedSegment === 'customization'">
+    <!-- 全屋定制内容 -->
+    <img src="example3.jpg" alt="Example 6">
+  </div>
+
+  <!-- 干货百科页 -->
+  <div *ngIf="selectedSegment === 'encyclopedia'">
+    <!-- 干货百科内容 -->
+    <img src="example3.jpg" alt="Example 7">
+  </div>
+
+  <!-- 风格测试页 -->
+  <div *ngIf="selectedSegment === 'style'">
+    <!-- 风格测试内容 -->
+    <div class="flex items-center gap-2">
+      <button
+        class="relative inline-flex items-center justify-center gap-2 text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-white hover:bg-[#F5F5F5] h-9 rounded-md px-3 group"
+      >
+        <svg
+          class="lucide lucide-arrow-left"
+          stroke-linejoin="round"
+          stroke-linecap="round"
+          stroke-width="2"
+          stroke="currentColor"
+          fill="none"
+          viewBox="0 0 24 24"
+          height="22"
+          width="22"
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <path d="m12 19-7-7 7-7"></path>
+          <path d="M19 12H5"></path>
+        </svg>
+        <span class="origin-left scale-0 transition-transform group-hover:scale-100"
+          >Back</span
+        >
+      </button>
+      <button
+        class="cursor-pointer bg-white relative inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 hover:bg-[#F5F5F5] hover:text-[#06B6D4] h-9 rounded-md px-3"
+      >
+        <svg
+          class="lucide lucide-rocket text-cyan-500 dark:text-cyan-400"
+          stroke-linejoin="round"
+          stroke-linecap="round"
+          stroke-width="2"
+          stroke="#06B6D4"
+          fill="none"
+          viewBox="0 0 24 24"
+          height="22"
+          width="22"
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <path
+            d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"
+          ></path>
+          <path
+            d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"
+          ></path>
+          <path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0"></path>
+          <path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"></path>
+        </svg>
+        Dashboard
+      </button>
+      <button
+        class="cursor-pointer bg-white relative inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 hover:bg-[#F5F5F5] hover:text-[#60A5FA] h-9 rounded-md px-3"
+      >
+        <svg
+          class="lucide lucide-newspaper text-blue-400 dark:text-blue-600"
+          stroke-linejoin="round"
+          stroke-linecap="round"
+          stroke-width="2"
+          stroke="#60A5FA"
+          fill="none"
+          viewBox="0 0 24 24"
+          height="22"
+          width="22"
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <path
+            d="M4 22h16a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v16a2 2 0 0 1-2 2Zm0 0a2 2 0 0 1-2-2v-9c0-1.1.9-2 2-2h2"
+          ></path>
+          <path d="M18 14h-8"></path>
+          <path d="M15 18h-5"></path>
+          <path d="M10 6h8v4h-8V6Z"></path>
+        </svg>
+        Articles
+      </button>
+      <button
+        class="cursor-pointer bg-white relative inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 hover:bg-[#F5F5F5] hover:text-[#FACC14] h-9 rounded-md px-3"
+      >
+        <svg
+          class="lucide lucide-sticky-note text-yellow-400 dark:text-yellow-600"
+          stroke-linejoin="round"
+          stroke-linecap="round"
+          stroke-width="2"
+          stroke="#FACC14"
+          fill="none"
+          viewBox="0 0 24 24"
+          height="22"
+          width="22"
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <path
+            d="M15.5 3H5a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2V8.5L15.5 3Z"
+          ></path>
+          <path d="M15 3v6h6"></path>
+        </svg>
+        Notes
+      </button>
+      <button
+        class="cursor-pointer bg-white relative inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 hover:bg-[#F5F5F5] hover:text-[#FB923C] h-9 rounded-md px-3"
+      >
+        <svg
+          class="lucide lucide-star text-orange-400 dark:text-orange-600"
+          stroke-linejoin="round"
+          stroke-linecap="round"
+          stroke-width="2"
+          stroke="#FB923C"
+          fill="#FB923C"
+          viewBox="0 0 24 24"
+          height="22"
+          width="22"
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <polygon
+            points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"
+          ></polygon>
+        </svg>
+        Reviews
+      </button>
+    </div>
+    
+    <img src="example3.jpg" alt="Example 8">
   </div>
 
   <!-- 智能预算页 -->

+ 6 - 2
src/app/tab1/tab1.page.ts

@@ -1,7 +1,8 @@
 import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
 
 import Swiper from 'swiper';
-
+import { NavController } from '@ionic/angular';
+import { Router } from '@angular/router';
 
 @Component({
   selector: 'app-tab1',
@@ -21,7 +22,7 @@ export class Tab1Page implements OnInit {
   selectedPackageCategory: string = 'top-listed-package'; // 默认选中上榜套餐
   selectedMaterialsCategory: string = 'decoration-materials'; // 默认选中装修建材
   
-  constructor() {}
+  constructor(private navCtrl: NavController,private router: Router) {}
 
   ngOnInit() {
     // 延迟500毫秒加载
@@ -30,6 +31,9 @@ export class Tab1Page implements OnInit {
     }, 500);
   }
   
+  gotoD(){
+    this.router.navigate(['/babylon']);
+  }
   // 初始化轮播图
   slide1:Swiper|undefined
   initSwiper(){

+ 1 - 1
src/app/tab2/tab2.page.html

@@ -251,7 +251,7 @@
       </ion-card-content>
   
       <!-- 底部 -->
-      <ion-button expand="full" fill="clear">咨询</ion-button>
+      <ion-button expand="full" fill="clear" (click)="openConsultPage()">咨询</ion-button>
       <ion-button expand="full" fill="clear">电话</ion-button>
       <ion-button expand="full" fill="clear">在线预约</ion-button>
       <ion-button expand="full" fill="clear">查看案例</ion-button>

+ 5 - 2
src/app/tab2/tab2.page.ts

@@ -1,6 +1,6 @@
 import { Component } from '@angular/core';
 import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
-
+import { NavController } from '@ionic/angular';
 @Component({
   selector: 'app-tab2',
   templateUrl: 'tab2.page.html',
@@ -359,7 +359,7 @@ export class Tab2Page {
   selectedDesignerSegment: string = 'designer';
   isFollowing: boolean = false;
   
-  constructor(private sanitizer: DomSanitizer) {}
+  constructor(private sanitizer: DomSanitizer,private navCtrl: NavController) {}
   selectedCompany: any;
 
 toggleDetails(company: any) {
@@ -369,6 +369,9 @@ toggleDetails(company: any) {
     this.selectedCompany = company;
   }
 }
+openConsultPage(){
+  this.navCtrl.navigateForward('/consult');
+}
 // 在组件类中实现一个方法来切换关注状态
 toggleFollow() {
   this.isFollowing = !this.isFollowing;