three.js项目vue转uniapp需要修改的地方 --参考记录

引入stats.js

修改图片地址:

sun.js里面的修改:

uniapp文件:(参考)

<script setup>
import * as THREE from 'three'
import { ref, computed, watch, onMounted } from 'vue'
import { basicThree } from '/core/basicThree'
import { useSun } from '/hooks/sun'
import { solarTerms } from '/help/constant'
import { useTag } from '@/hooks/useTag'
import { tweenCamera } from '@/help/animate'
import { sunFootHeight1,sunFootHeight2 } from '@/config.js';

// data()
  // 定义响应式状态
  
	const activeLoudong = ref(0);
	const activeDanyuan = ref(0);
    const isLoudongVisible = ref(false);
	const isArrowUpVisible = ref(false);
	const isArrowDownVisible = ref(false);
	const isHuVisible = ref(false);
	const isDanyuanVisible= ref(false);
	const viewHeight = ref(sunFootHeight1);
	const tableData = [
	  ['全年', '24h', '9:30-13:00,14:30-17:30'],
	  ['春季', '6h', '9:30-13:00,14:30-17:30'],
	  ['夏季', '7h', '9:30-13:00,14:30-17:30'],
	  ['秋季', '4h', '9:30-13:00,14:30-17:30'],
	  ['冬季', '2h', '9:30-13:00,14:30-17:30']
	];
	const option1 = ref([
	  { text: '全部商品', value: 0 },
	  { text: '新款商品', value: 1 },
	  { text: '活动商品', value: 2 },
	]);
	
	const option2 = ref([
	  { text: '默认排序', value: 'a' },
	  { text: '好评排序', value: 'b' },
	  { text: '销量排序', value: 'c' },
	]);
	
	const value1 = ref(0);
	const value2 = ref('a');
	
	
	
	


//、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

// 声明一个全局变量 threeObj 用于存储 Three.js 对象
let threeObj = null

// 在组件挂载时执行的函数
onMounted(() => {
  // 初始化 threeObj 为 basicThree 类的实例
  threeObj = new basicThree()
  // 设置模型的 URL
  threeObj.modelUrl = '/static/public/base.glb'
  // 初始化模型
  threeObj.initModel()
  // 初始化太阳
  initSun()

  // 延迟 1200 毫秒加载标签
  setTimeout(() => {
    // 使用 useTag 钩子创建和渲染标签
    const { createTag, renderTag } = useTag(threeObj)
    // 创建标签
    createTag()
    // 注册渲染事件
    threeObj.registRenderEvent(renderTag)
  }, 1200)

  // 初始化点击事件处理
  initClick()
})

// 使用 useSun 钩子获取太阳相关的函数和变量
const {
  initSun,
  curSolarTerms,
  onChangeTerm,
  sunlightPosition,
  progress,
  run,
  stop,
  timeInfo,
  isRunning,
} = useSun()

// 声明 showPicker 和 isShowSingle 为响应式变量
const showPicker = ref(false)
const isShowSingle = ref(false)

// 监听 sunlightPosition 的变化,并更新 threeObj 的太阳光位置
watch(sunlightPosition, (newVal) => {
  // 更新太阳光的位置
  threeObj.sunLight.position.copy(newVal)
  // 将太阳光的目标位置设置为原点
  threeObj.sunLight.target.position.set(0, 0, 0)
})

// 当日期选择器确认时,调用 onChangeTerm 并隐藏选择器
const onConfirmPicker = (value) => {
  // 改变太阳节气
  onChangeTerm(value.selectedOptions[0])
  // 隐藏日期选择器
  showPicker.value = false
}

// 开始拖拽时停止动画
const dragStart = () => {
  // 停止动画
  stop()
}

// 记录相机原始位置的响应式变量
const originalCameraPosition = ref()

// 初始化点击事件处理
const initClick = () => {
  // 创建一个射线投射器
  const raycaster = new THREE.Raycaster()
  // 创建一个二维向量用于存储鼠标位置
  const mouse = new THREE.Vector2()

  // 声明一个变量用于存储是否正在拖拽
  let isDragging = false
  // 监听鼠标按下事件,重置拖拽状态
  document.addEventListener('mousedown', () => {
    isDragging = false
  })

  // 监听鼠标移动事件,更新拖拽状态
  document.addEventListener('mousemove', () => {
    isDragging = true
  })

  // 鼠标抬起时的事件处理
  document.addEventListener('mouseup', (event) => {
    // 如果没有发生拖拽
    if (!isDragging) {
      // 如果已经显示单个物体,则返回
      if (isShowSingle.value) {
        return
      }
      // 阻止默认事件
      event.preventDefault()

      // 计算鼠标点击位置
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1
      mouse.y = -(event.clientY / window.innerHeight) * 2 + 1

      // 从相机位置投射一条射线
      raycaster.setFromCamera(mouse, threeObj.camera)
      // 获取射线与场景中物体的交点
      const intersects = raycaster.intersectObjects(threeObj.scene.children)

      console.log('intersects', intersects)

      // 如果有交点,并且交点物体的名称包含 'New_object'
      if (intersects.length > 0 && intersects[0]?.object.name.includes('New_object')) {
        // 获取被点击的最近的物体的父级
        const clickedObject = intersects[0].object?.parent

        // 如果没有获取到物体,则返回
        if (!clickedObject) {
          return
        }

        console.log('clickedObject', clickedObject)
        // 显示单个物体
        isShowSingle.value = true
        // 显示楼栋表格
        isLoudongVisible.value = true
		isDanyuanVisible.value=true
        // 显示向下箭头图标
        isArrowUpVisible.value=true
		isArrowDownVisible.value=false
		viewHeight.value=sunFootHeight1

        // 隐藏其他模型
        for (let i = threeObj.scene.children.length - 1; i >= 0; i--) {
          const object = threeObj.scene.children[i]

          // 寻找其它楼栋,楼栋放在 group 中,楼栋由多个 mesh 组成
          // 修改 mesh 的材质的透明度
          if (object.isGroup) {
            object.children.forEach((mesh) => {
              if (mesh.uuid !== clickedObject.uuid) {
                mesh.children.forEach(childMesh => {
                  childMesh.material.transparent = true
                  childMesh.material.opacity = 0.08
                })
              }
            })
          }
          // 如果是 CSS2D 对象
          if (object.isCSS2DObject) {
            if (object.name !== clickedObject.name) {
              object.element.style.opacity = 0.5
            } else {
              object.element.style.opacity = 1
            }
          }
        }

        // 记录相机的原始位置
        originalCameraPosition.value = threeObj.camera.position.clone()

        // 获取点击物体的位置
        const toPosition = clickedObject.position.clone()
		
console.log(clickedObject.position)
        // 调整相机位置和角度
        tweenCamera(
          threeObj.camera,
          threeObj.camera.position,
          toPosition,
          666,
          -160,
          () => {
            // 设置相机控件的目标位置为点击物体的位置
            threeObj.controls.target.copy(clickedObject.position)
          },
          threeObj.controls,
        )
      }
    }

    // 重置拖拽状态
    isDragging = false
  })
}


//、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
/* 方法汇总 */
/* methods */

// 点击单元
const showDanyuan = (danyuan) => {
	activeDanyuan.value=danyuan;//切换按钮
}
	

// 点击楼栋的时候,出现楼栋的表格 和 foot的箭头图标
const showLoudong = (loudong) => {
	/* 某些图标的显示隐藏 */
		
		activeLoudong.value=loudong;//切换按钮
	  
	  isArrowUpVisible.value=true;
	  isArrowDownVisible.value=false;
	  isLoudongVisible.value =true;
	  isDanyuanVisible.value =true;
	  isHuVisible.value =false; 
	  
	  isShowSingle.value=false;//一开始未单栋。方法末尾加上。
	  
	  
	  /* 3d图的定位 */
	
	  // 创建一个射线投射器
	  const raycaster = new THREE.Raycaster()
	
	  // 创建一个二维向量用于存储鼠标位置
	  const mouse = new THREE.Vector2()
	 
	  // 声明一个变量用于存储是否正在拖拽
	  let isDragging = false
	  
	  // 点击某一幢
	  // 如果没有发生拖拽
	  if (!isDragging) {
		
	    // 如果已经显示单个物体,则返回
		
	    if (isShowSingle.value) {
		
	      return
	    }
		
	    // 阻止默认事件
	   // event.preventDefault()
	  
	    // 计算鼠标点击位置
	  //   mouse.x = (event.clientX / window.innerWidth) * 2 - 1
	  //   mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
	  
	  mouse.x = 0.17948717948717952
	  mouse.y = 0.22037914691943128
	  	  
		  
	    // 从相机位置投射一条射线
	    raycaster.setFromCamera(mouse, threeObj.camera)
	    // 获取射线与场景中物体的交点
	    const intersects = raycaster.intersectObjects(threeObj.scene.children)
	  
	 
		console.log('intersects', intersects)
	  
	    // 如果有交点,并且交点物体的名称包含 'New_object'
	// 随机数 new_object
		// const n = 100; // 例如 n 为 10
		// const randomInt = Math.floor(Math.random() * n);
		//console.log(randomInt)
	// 	intersects[0].object.name='New_object11';//模拟设置
	// console.log(intersects)
	
	
	    if (intersects.length > 0 && intersects[0]?.object.name.includes('New_object')) {
		
			
	      // 获取被点击的最近的物体的父级
	      const clickedObject = intersects[0].object?.parent
	  
	      // 如果没有获取到物体,则返回
	      if (!clickedObject) {
	        return
	      }
	  
	      console.log('clickedObject', clickedObject)
	      // 显示单个物体
	      isShowSingle.value = true
	      // 显示楼栋表格
	      isLoudongVisible.value = true
	  	isDanyuanVisible.value=true
	      // 显示向下箭头图标
	      isArrowUpVisible.value=true
	  	isArrowDownVisible.value=false
	  	viewHeight.value=sunFootHeight1
	  
	  
	  
	 
	  
	      // 隐藏其他模型
	      for (let i = threeObj.scene.children.length - 1; i >= 0; i--) {
	        const object = threeObj.scene.children[i]
	  
	        // 寻找其它楼栋,楼栋放在 group 中,楼栋由多个 mesh 组成
	        // 修改 mesh 的材质的透明度
	        if (object.isGroup) {
	          object.children.forEach((mesh) => {
	            if (mesh.uuid !== clickedObject.uuid) {
	              mesh.children.forEach(childMesh => {
	                childMesh.material.transparent = true
	                childMesh.material.opacity = 0.08
	              })
	            }
	          })
	        }
	        // 如果是 CSS2D 对象
	        if (object.isCSS2DObject) {
	          if (object.name !== clickedObject.name) {
	            object.element.style.opacity = 0.5
	          } else {
	            object.element.style.opacity = 1
	          }
	        }
	      }
	  
	      // 记录相机的原始位置
	      originalCameraPosition.value = threeObj.camera.position.clone()
	  
	      // 获取点击物体的位置
	      const toPosition = clickedObject.position.clone()
	 
	
	  
	  
	      // 调整相机位置和角度
	      tweenCamera(
	        threeObj.camera,
	        threeObj.camera.position,
	        toPosition,
	        666,
	        -160,
	        () => {
	          // 设置相机控件的目标位置为点击物体的位置
	          threeObj.controls.target.copy(clickedObject.position)
	        },
	        threeObj.controls,
	      )
	    }
	  }
	  
	  // 重置拖拽状态
	  isDragging = false
	  
	  
	  isShowSingle.value=true;//一开始未单栋。方法末尾加上。
	  
	  
	  
	  //、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
	  
	  
	  
	  
}
//  点击箭头的时候,隐藏楼栋表格和箭头图标
const arrowUpAction = () => {
	isArrowUpVisible.value=false;
	isArrowDownVisible.value=true;
	viewHeight.value=sunFootHeight2;
	 
	  
}
const arrowDownAction = () => {
	isArrowUpVisible.value=true;
	isArrowDownVisible.value=false;
	viewHeight.value=sunFootHeight1;
	  
}
// 点击 楼栋中的某一个户  显示 户型列表
const showHuTable = () => {
	
	 isLoudongVisible.value =false; 
	  isHuVisible.value =true; 
	  
	 
}





// 返回楼栋
const backSandbox = () => {
  isShowSingle.value = false
  isArrowUpVisible.value=false
  isArrowDownVisible.value=false
  isLoudongVisible.value=false
  isDanyuanVisible.value =false;
  isHuVisible.value=false
  viewHeight.value=sunFootHeight1

  tweenCamera(
    threeObj.camera,
    threeObj.camera.position,
    originalCameraPosition.value,
    666,
    0,
    () => {
      // threeObj.controls.target.copy(threeObj.originalTarget)
    },
  )

  threeObj.scene.children.forEach((child) => {
    if (child.isGroup) {
      child.children.forEach((mesh) => {
        mesh.children.forEach(childMesh => {
          childMesh.material.opacity = 1
        })
      })
    }
  })
}

// 日照效果 日照时长 的methods
const changeModelColor = (isDefault) => {
  const { scene } = threeObj
  
  const targetGroups = scene.children.find(child => child.isGroup).children

  targetGroups.forEach(group => {
    group.children.forEach(mesh => {
      if (isDefault) {
        mesh.material.color.setHex(0xfffff0)
      } else {
        mesh.material.color.copy(mesh.material.originColor)
      }
    })
  })
}

const tabStatus = ref('effect')
const isEffect = computed(() => {
  return tabStatus.value === 'effect'
})
const onChangeStatus = () => {
  if (isEffect.value) {
    changeModelColor(true)
  } else {
    changeModelColor()
  }
}

const colorTips = [
	{ title: '强', color: '#f2a43f' },
	{ title: '', color: '#f8c181' },
	{ title: '', color: '#fbd29e' },
	{ title: '', color: '#fbd9ac' },
	{ title: '', color: '#fce2c1' },
  { title: '弱', color: '#fbe9d3' },
]



</script>
<template>
  <div id="sunshine">
    
	<!-- 日照效果日照时长 暂时隐藏 -->
	<!-- <header>
      <div class="nav">
        <van-tabs v-model:active="tabStatus" @change="onChangeStatus" line-width="16px" title-inactive-color="#969696"
          title-active-color="#0059f0">
          <van-tab title="日照效果" name="effect"></van-tab>
          <van-tab title="日照时长" name="duration"></van-tab>
        </van-tabs>
      </div>
    </header> -->
	
	<header>
		<van-dropdown-menu>
		  <van-dropdown-item value="{{ value1 }}" options="{{ option1 }}" />
		  <van-dropdown-item value="{{ value2 }}" options="{{ option2 }}" />
		</van-dropdown-menu>
	</header>
	

    <footer class="ctrl-wrapper" style="border-top-left-radius: 10px;border-top-right-radius: 10px;">
		
		<view v-if="isArrowUpVisible" style="display: flex;justify-content: center;"><van-icon name="arrow-up" size="12" @tap="arrowUpAction" /></view>
		<view v-if="isArrowDownVisible" style="display: flex;justify-content: center;"><van-icon name="arrow-down" size="12" @tap="arrowDownAction" /></view>
		
		

		
		
		<!-- 在3d图中 显示 “返回” 字样 -->
     <view  v-if="isShowSingle" @click="backSandbox" style="top:-40px;left:0;background-color: white;position: absolute;padding:5px 5px 5px 2px;border-radius: 5px;
     border-top-left-radius: 0;
     border-bottom-left-radius: 0;
     font-size: 11px;
	 display:flex;
	 align-items: center;
     ">
     		<image src="/static/sun/exit.png" style="width:15px;height:15px"></image>
     		<span style="margin-left:2px">返回全部楼栋</span>
     	</view>
		
		
	  <!-- 由强到弱  第一处显示-->
   <!--   <div v-if="!isEffect" class="gauge-container">
        <div v-for="(color, index) in colorTips" :key="index" :style="{ backgroundColor: color.color }">{{ color.title
          }}
        </div>
      </div> -->
	  
	  
	  <!-- 当点击3d图中的某一幢的时候  在foot 中 显示 “返回” 字样 -->
     <!-- <div class="title" >
        <div v-if="isShowSingle" class="back" @click="backSandbox">
          <van-icon name="arrow-left" />
          <span>返回</span>
        </div>
        <span class="project-name">楼栋日照模拟</span>
      </div> -->
	  
	  
	  
	  
	  <view style="display: flex;margin-top: 0px;justify-content: space-between">
		  <view style="font-weight: bold;font-size: 15px;">中环置地中心·润府</view>
		 
			  	  <!-- 由强到弱  第二处显示-->
			  <view  class="gauge-container">
			    <div v-for="(color, index) in colorTips" :key="index" :style="{ backgroundColor: color.color }">{{ color.title
			      }}
			    </div>
			  </view>
			  
			  
		
	  </view>
	  
	
	  <view style="margin-top: 10px;display: flex;width:100%;display: flex;align-items: center;">
		  
		  <div class="btn-show-picker" @click="showPicker = true" style="color:#4dac8f;font-size: 14px;font-weight: bold">
		    全部批次
		    
			<van-icon name="arrow-down" size="12"/>
		  </div> 
		  
		  
		  <view style="flex:1;justify-content: space-around;display: flex;font-size: 13px;">
			  <view :class="activeLoudong=='A8' ?'loudonngClass':''"   @tap="showLoudong('A8')" >A8幢</view>
			  <view  :class="activeLoudong=='A7'?'loudonngClass':''"   @tap="showLoudong('A7')">A7幢</view>
			  <view  :class="activeLoudong=='A6'?'loudonngClass':''"   @tap="showLoudong('A6')">A6幢</view>
			  <view   :class="activeLoudong=='A5'?'loudonngClass':''"  @tap="showLoudong('A5')">A5幢</view>
			  <view  :class="activeLoudong=='A4'?'loudonngClass':''"   @tap="showLoudong('A4')">A4幢</view>
		  </view>
		  
		 
			 
		
		  
	  </view>
	  
	  
	  <view v-if="isDanyuanVisible" style="display: flex; justify-content: flex-start;font-size: 11px;margin-top: 10px; ">
	      <view :class="(activeDanyuan=='1'||activeDanyuan=='0') ?'danyuan-active':'danyuan-unactive'"  @tap="showDanyuan('1')" type="primary">1单元</view>
	      <view :class="activeDanyuan=='2' ?'danyuan-active':'danyuan-unactive'" @tap="showDanyuan('2')" type="primary" >2单元</view>
	  </view>
	
	  
	  
      <div class="sun-ctrl">
		  	<!-- 下拉框 小寒 -->
        <!-- <div class="btn-show-picker" @click="showPicker = true">
          {{ curSolarTerms.text }}
          <van-icon name="play" />
        </div> -->
		
		<!-- 停止按钮 -->
				<div style="margin: 0;" class="ctrl-btn" @click="isRunning ? stop() : run()">
		   <van-icon v-if="isRunning" size="12" color="#4dac8f" name="pause" style="margin-right: 5px;" />
		   <van-icon v-else color="#4dac8f" size="12" name="play"   style="margin-right: 5px;"/>
		   <div style="font-size: 10px;color:#999">{{ timeInfo.curHour + ':' + timeInfo.curMin }}</div>
		 </div>
		 
		 
		
        <div class="slider" style="flex:1;margin:0">
		<!-- 开始时间 8:00 -->
          <span class="time">{{ timeInfo.startTime }}</span>
		  <!-- 进度条 -->
          <van-slider v-model="progress" style="width: 70%" :step="5" :min="0" active-color="#eaedee"
            inactive-color="#eaedee" bar-height="5px" :max="480" @drag-start="dragStart">
            <template #button>
              <div class="custom-sun-slider">
                <div>{{ timeInfo.curHour + ':' + timeInfo.curMin }}</div>
                <img src="/static/sun/sun.png" ondragstart="return false" alt="" />
              </div>
            </template>
          </van-slider>
		  <!-- 结束时间 -->
          <span class="time">{{ timeInfo.endTime }}</span>
        </div>
       
	   
      </div>
	  
	  
	  
	
	  
	  
	  
	  <view style="display: flex;justify-content:space-between;margin:10px 0 10px 0;font-size: 12px;">
		  <view style="padding:5px 10px;background-color: #e7f6f3; color:#4dac8f;font-weight: bold;">大寒</view>
		  <view style="padding:5px 10px;background-color: #f6f6f6; color:#353535">春风</view>
		  <view style="padding:5px 10px;background-color: #f6f6f6; color:#353535">夏至</view>
		  
		  <view style="padding:5px 10px;background-color: #f6f6f6; color:#353535">秋分</view>
		  <view style="padding:5px 10px;background-color: #f6f6f6; color:#353535">立冬</view>
		  <view style="padding:5px 10px;background-color: #f6f6f6; color:#353535">冬至</view>
		  
	  </view>
	  
	  
	  <!-- 楼栋 具体信息   楼栋表格-->
	  
		  
		<view v-if="isLoudongVisible" :style="{ marginTop: '10px', height: viewHeight + 'px', overflowY: 'scroll' }">
		    <!-- 内容 -->  
		  
		  
		  
	  	<view class="louceng" @tap="showHuTable">
	  	    <view class="louceng-left">14层</view>
	  	
	  	    <view class="louceng-right">
	  	        <p>-1402-</p>
	  	        <p>8.0<span>h</span></p>
	  	    </view>
	  	
	  	    <view class="louceng-right">
	  	        <p>-1402-</p>
	  	        <p>8.0<span>h</span></p>
	  	    </view>
	  	</view>
	  	<view class="louceng">
	  	    <view class="louceng-left">13层</view>
	  	
	  	    <view class="louceng-right">
	  	        <p>-1402-</p>
	  	        <p>8.0<span>h</span></p>
	  	    </view>
	  	
	  	    <view class="louceng-right">
	  	        <p>-1402-</p>
	  	        <p>8.0<span>h</span></p>
	  	    </view>
	  	</view>
	  	<view class="louceng">
	  	    <view class="louceng-left">12层</view>
	  	
	  	    <view class="louceng-right">
	  	        <p>-1402-</p>
	  	        <p>8.0<span>h</span></p>
	  	    </view>
	  	
	  	    <view class="louceng-right">
	  	        <p>-1402-</p>
	  	        <p>8.0<span>h</span></p>
	  	    </view>
	  	</view>
	  	<view class="louceng">
	  	    <view class="louceng-left">11层</view>
	  	
	  	    <view class="louceng-right">
	  	        <p>-1402-</p>
	  	        <p>8.0<span>h</span></p>
	  	    </view>
	  	
	  	    <view class="louceng-right">
	  	        <p>-1402-</p>
	  	        <p>8.0<span>h</span></p>
	  	    </view>
	  	</view>
	  	<view class="louceng">
	  	    <view class="louceng-left">11层</view>
	  	
	  	    <view class="louceng-right">
	  	        <p>-1402-</p>
	  	        <p>8.0<span>h</span></p>
	  	    </view>
	  	
	  	    <view class="louceng-right">
	  	        <p>-1402-</p>
	  	        <p>8.0<span>h</span></p>
	  	    </view>
	  	</view>
	  	<view class="louceng">
	  	    <view class="louceng-left">11层</view>
	  	
	  	    <view class="louceng-right">
	  	        <p>-1402-</p>
	  	        <p>8.0<span>h</span></p>
	  	    </view>
	  	
	  	    <view class="louceng-right">
	  	        <p>-1402-</p>
	  	        <p>8.0<span>h</span></p>
	  	    </view>
	  	</view>
	  </view>
	  
	  
	  
	  
	  <!-- 户型表格 -->
	  
	 <view v-if="isHuVisible" :style="{ marginTop: '10px', height: viewHeight + 'px', overflowY: 'scroll' }">
	 			
			
			 <view class="table">
			    <!-- 表头 -->
			    <view class="table-header">
			      <view class="table-header-item">时间</view>
			      <view class="table-header-item">总时长</view>
			      <view class="table-header-item">时段</view>
			    </view>
			    <!-- 表内容 -->
			    <view class="table-content">
			      <!-- 使用 v-for 循环生成表格行 -->
			      <view class="table-row" v-for="(row, index) in tableData" :key="index">
			        <!-- 使用 v-for 循环生成表格列 -->
			  
					
					  <view class="table-cell" v-for="(cell, idx) in row" :key="idx" :class="{ 'bold-text': idx === 0 }">
					          {{ cell }}
					        </view>
					
					
			      </view>
			    </view>
			  </view>
			  
			
			
			</view>
	  
	  
	  

    </footer>


<!-- 背景 -->
    <div class="compass">
      <div class="bg"></div>
      <img src="/static/sun/compass-point.jpg">
    </div>

<!-- 点击小寒后 弹出的框 -->
    <van-popup v-model:show="showPicker" round position="bottom">
      <van-picker :columns="solarTerms()" title="节气" @cancel="showPicker = false" @confirm="onConfirmPicker" />
    </van-popup>
	
  </div>
</template>

<style scoped lang="less">
.ctrl-wrapper {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  max-width: 520px;
  background-color: #fff;
  padding: 10px;

  .back-btn {
    position: absolute;
    left: 0;
    right: 0;
    margin: auto;
    top: -40px;
    font-size: 12px;
	
    color: #333;
    border-radius: 5px;
	border-top-left-radius: 0;
	border-bottom-left-radius: 0;
    background-color: white;
    
    width:auto;
    padding: 4px;
    
    align-items: center;
    cursor: pointer;

    >span {
      font-size: 14px;
      margin-left: 0px;
      margin-right: 4px;
    }
  }

  .gauge-container {
    display: flex;
    
  
   

    >div {
      width: calc(100% / 6);
      height: 16px;
      color: #000;
      font-size: 12px;
      display: flex;
      align-items: center;
      justify-content: center;
	  width:20px;
    }
  }

  .sun-ctrl {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 10px;

    .btn-show-picker {
      font-size: 12px;
      color: #565656;
      padding: 5px 10px;
      background-color: #f4f4f4;
      border-radius: 20px;
      cursor: pointer;

      >i {
        transform: rotate(90deg);
        color: #b6b6b6;
      }
    }

    .slider {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 70%;
    }

    .time {
      font-size: 14px;
      color: #000;
      margin: 0 4px;
    }
  }

  .ctrl-btn {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 26px;
    height: 10px;
	padding:4px 15px;
    border-radius: 10px;
    background-color: #f6f6f6;
    margin-right: 0px;
  }

  .title {
    display: flex;
    align-items: center;
    justify-content: space-between;

    .back {
      cursor: pointer;
      font-size: 14px;
      color: #0059F0;
    }

    .project-name {
      color: #252525;
      font-size: 14px;
      font-weight: 500;
    }
  }
}

header {
  /deep/ .nav {
    position: absolute;
    left: 0;
    right: 0;
    top: 18px;
    margin: auto;
    width: 174px;
    height: 36px;
    border-radius: 18px;
    background: #fff;
    box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .2);
    overflow: hidden;
    z-index: 100;

    .van-tabs--line .van-tabs__wrap {
      height: 36px;
    }

    .van-tabs__line {
      background-color: #0059F0;
    }

    .van-tabs__nav--line {
      padding-bottom: 10px;
    }
  }
}

.compass {
  left: 50px;
  top: 50px;
  touch-action: none;
  position: absolute;
  -webkit-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);

  >div {
    width: 80px;
    height: 80px;
    background-size: contain;
    background-image: url('../assets/compass-bg.png');
  }

  >img {
    position: absolute;
    width: 24px;
    left: 50%;
    top: 50%;
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
  }
}
</style>

<style lang="less">
.custom-sun-slider {
  display: flex;
  justify-content: center;
  flex-direction: column;
  align-items: center;
  margin-bottom: 12px;

  >div {
    width: 20px;
    color: #fff;
    font-size: 12px;
    text-align: center;
    border-radius: 100px;
  }

  >img {
    width: 20px;
    height: 20px;
  }
}
</style>

<style less>
.tag2,
.tag {
  box-shadow: 0 0 2px #00ffff inset;
  background: #00ffff;
  background-repeat: no-repeat;
  background-size:
    1px 6px,
    6px 1px;
  background-color: rgba(0, 0, 0, 0.4);
  color: #ffffff;
  font-size: 12px;
  padding: 2px 10px;
  border-radius: 10px;
  user-select: auto !important;
  pointer-events: all;
  cursor: pointer;
}

.tag2 {
  color: pink;
}
</style>
../core/basicThree


<style>
	/* 楼层 */
	  .louceng {
	        display: flex;
	        justify-content: flex-start;
	        
	    }
	
	    .louceng-left {
	        background-color: #f6f6f6;
	        padding: 10px 20px;
	        display: flex;
	        align-items: center;
	        font-size: 16px;
	        margin: 1px 1px 1px 0;
	    }
	
	    .louceng-right {
	        margin: 1px 1px 1px 0;
	        background-color: #f2a43f;
	        padding: 10px 30px;
	        display: flex;
	        flex-direction: column;
	        justify-content: center;
	        align-items: center;
	        text-align: center;
	    }
	
	    .louceng-right p {
	        font-size: 16px;
	        margin: 0;
			font-weight: bold;
	    }
	
	    .louceng-right p:first-child {
	        font-size: 12px;
	        font-weight:normal;
	    }
	
	    .louceng-right span {
	        font-size: 10px;
			font-weight:normal;
	    }
		
		
		/* 样式可以根据实际需要进行调整 */
		.table {
		  width: 99%;
		  border: 1px solid #ccc;
		  margin-top: 10px;
		  font-size:12px;
		}
		
		.table-header {
		  display: flex;
		  border-bottom: 1px solid #ccc;
		  font-size:14px;
		  background-color: #f2a43f; /* 橙色背景 */
		  
		}
		
		.table-header-item {
		  flex: 1;
		  padding: 5px;
		  text-align: center;
		  font-weight: bold;
		  color:white;
		  border-right: 1px solid #ffffff; /* 单元格右侧边框 */
		}
		/* 最后一列不添加右侧边框 */
		.table-header-item:last-child {
		  border-right: none;
		}
		
		.table-content {
		  padding: 2px;
		}
		
		.table-row {
		  display: flex;
		  border-bottom: 1px solid #ccc;
		}
		
		.table-cell {
		  flex: 1;
		  padding: 2px;
		  text-align: center;
		   border-right: 1px solid #ccc; /* 单元格右侧边框 */
		}
		/* 第一列字体加粗 */
		.bold-text {
		  font-weight: bold;
		  font-size:14px;
		}
		/* 最后一列不添加右侧边框 */
		.table-cell:last-child {
		  border-right: none;
		}
		
		/* A8楼栋 */
		.loudonngClass{
			color:#4dac8f;
			font-weight: bold;
			cursor: pointer;
			border-bottom:2px solid #4dac8f
		}
		
		/* 单元 */
		.danyuan-active{
			padding:2px 8px;margin-right: 5px;background-color: white; color:#4dac8f;border:1px solid #4dac8f;border-radius: 30px;
		}
		.danyuan-unactive{
			padding:2px 8px;margin-right: 5px; background-color: #f6f6f6; color: #353535;border:0;border-radius: 30px
		}
	
</style>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您的问题是如何在uniapp框架vue2项目中使用组件canvas来实现3D模型渲染,是吗? 首先,需要uniapp项目中安装three.js和three.weapp.js。您可以使用npm来安装它们,命令如下: ``` npm install three npm install three.weapp.js ``` 然后,在您的vue组件中,可以使用以下代码来创建一个canvas元素: ``` <canvas id="canvas"></canvas> ``` 接下来,在您的vue组件中,可以使用以下代码来创建一个3D场景并进行渲染: ``` import * as THREE from 'three' import { WechatPlatform } from 'three-platformize' export default { mounted() { const canvas = document.getElementById('canvas') const renderer = new THREE.WebGLRenderer({ canvas: canvas, context: canvas.getContext('webgl', { preserveDrawingBuffer: true }), antialias: true }) const platform = new WechatPlatform(canvas) const scene = new THREE.Scene() const camera = new THREE.PerspectiveCamera(75, canvas.width / canvas.height, 0.1, 1000) camera.position.set(0, 0, 10) const geometry = new THREE.BoxGeometry() const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }) const cube = new THREE.Mesh(geometry, material) scene.add(cube) const animate = () => { requestAnimationFrame(animate) cube.rotation.x += 0.01 cube.rotation.y += 0.01 renderer.render(scene, camera) } animate() } } ``` 在上面的代码中,我们首先获取了canvas元素,然后创建了一个WebGLRenderer对象,并将canvas元素传递给它。接下来,我们创建了一个WechatPlatform对象,并将canvas元素传递给它。然后,我们创建了一个场景、相机、几何体、材质和一个网格,并将它们添加到场景中。最后,我们创建了一个动画函数,在其中更新网格的旋并渲染场景。 这样,您就可以在uniapp框架vue2项目中使用组件canvas和three.weapp.js来实现3D模型渲染了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值