添加threejs
npm install three --save-dev
如果你需要three.js的其他版本,使用
npm show three versions
来确认哪些是可用的。要让npm使用正确的版本,执行如:
npm install three@0.84.0 --save
npm 安装模块
【npm install xxx】安装但不写入package.json;
【npm install -g xxx】利用npm安装全局模块xxx;
【npm install xxx --save】 安装并写入package.json的"dependencies"中;
【npm install xxx --save-dev】安装并写入package.json的"devDependencies"中。
npm 删除模块
【npm uninstall xxx】删除xxx模块;
【npm uninstall -g xxx】删除全局模块xxx;
FPS指示器
npm install stats.js --save
引用
<template>
<div>
<div id="container" style=" width: 100%; " :style="{ height: (h + 'px') }"></div>
</div>
</template>
<script>
//引入three包 最新版
import * as THREE from "three";
const windowHeight = window.innerHeight || document.body.clientHeight
export default {
data() {
return {
//一般的全景图分为两种,一种是由六张正方形的图组成,一种是由一张宽2高1的图
bigImg: require("../assets/img/earth.jpeg"), //全景图图片路径 这个是长与高2:1的图
satellites: [], //卫星(数组)
container: null, // dom节点
};
},
mounted() {
this.scene = null; // 场景
this.renderer = null; // 渲染器
this.camera = null; // 相机
this.mesh = null; //网格模型对象Mesh
this.init(); //初始的方法都放在init
this.animate();
},
//销毁页面
destroyed: function () {
this.scene = null; // 场景
this.renderer = null; // 渲染器
this.camera = null; // 相机
this.mesh = null; //网格模型对象Mesh
},
computed:{
h(){
return windowHeight - 64 - 44 - 20
},
},
methods: {
//初始化
init: function () {
this.container = document.getElementById("container"); //获取dom元素
//创建场景对象Scene
this.scene = new THREE.Scene();
let geometry = new THREE.SphereGeometry(20, 30, 30); ///创建一个立方体几何对象Geometry
//对球形几何网格进行x轴反转,使所有的面点向内,否则就是朝外
//geometry.scale(-1, 1, 1);
//纹理贴图 首先,把图片加载进来
var texture = new THREE.TextureLoader().load(this.bigImg); //加载纹理贴图
//创建材质,加入map
let sphereMaterial = new THREE.MeshBasicMaterial({ map: texture });
this.mesh = new THREE.Mesh(geometry, sphereMaterial); //网格模型对象Mesh
//给物体取个名称 后面好控制物体的动画
this.mesh.name = "box";
this.mesh.position.set(0, 0, 20); //设置偏移 地球偏移
this.scene.add(this.mesh); //网格模型添加到场景中
//添加光源
var satellite = new THREE.Sprite(
new THREE.SpriteMaterial({
map: new THREE.CanvasTexture(this.generateSprite("70,134,216")),
blending: THREE.AdditiveBlending,
})
);
satellite.scale.x = satellite.scale.y = satellite.scale.z = 80; //发光的范围
satellite.position.set(0, 0, 20); //设置发光位置
this.scene.add(satellite); //添加发光,让地球有发光的样式
//创建相机对象
//20摄像机看到的角度 1 相机看到的最近距离 1000相机看到的最远距离 剩下的就是长宽比
this.camera = new THREE.PerspectiveCamera(
20,
this.container.clientWidth / this.container.clientHeight,
1,
1000
);
this.camera.position.set(0, 0, 400); //设置相机位置
this.camera.lookAt(this.scene.position); //设置相机方向(指向的场景对象)
//取消锯齿antialias:true
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
this.renderer.setSize(
this.container.clientWidth,
this.container.clientHeight
); //设置渲染区域尺寸
this.renderer.setClearColor(0xffffff, 0.5); //设置渲染器的初始颜色 背景颜色
this.container.appendChild(this.renderer.domElement); //body元素中插入canvas对象
//添加卫星
this.satellites.push( this.initSatellite( 10, 48, { x: -Math.PI * 0.35, y: Math.PI * 0.25, z: 0 }, 0.021, this.scene,'180,0,216' ) );
this.satellites.push( this.initSatellite( 60, 145, { x: -Math.PI * 0.35, y: -Math.PI * 0.2, z: 0 }, 0.012, this.scene,'31,0,191' ) );
this.satellites.push( this.initSatellite( 45, 125, { x: -Math.PI * 0.35, y: -Math.PI * 0.1, z: 0 }, 0.022, this.scene,'28,21,57' ) );
this.satellites.push( this.initSatellite( 15, 49, { x: -Math.PI * 0.35, y: Math.PI * 0.05, z: 0 }, 0.023, this.scene ,'0,144,198') );
this.satellites.push( this.initSatellite( 25, 69, { x: -Math.PI * 0.35, y: Math.PI * 0.3, z: 0 }, 0.026, this.scene ,'167,80,0') );
this.satellites.push( this.initSatellite( 50, 130, { x: -Math.PI * 0.35, y: Math.PI * 0.15, z: 0 }, 0.016, this.scene ,'201,0,5') );
//监听窗口的变化
window.addEventListener("resize", () => this.onWindowResize());
},
//动画
animate() {
let box = this.scene.getObjectByName("box"); //获取物体的名字 就可以控制不同的物体动画了
this.renderer.render(this.scene, this.camera); //执行渲染操作
box.rotateY(0.01); //每次绕y轴旋转0.01弧度
for (var i = 0; i < this.satellites.length; i++) {
this.satellites[i].satellite.rotation.z -= this.satellites[i].speed;
}
requestAnimationFrame(this.animate); //动画效果
},
//监听窗口的大小变化 还有相机的比例
onWindowResize() {
this.camera.aspect =
this.container.clientWidth / this.container.clientHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(
this.container.clientWidth,
this.container.clientHeight
);
},
/**
* 返回一个卫星和轨道的组合体
* satelliteSize 卫星的大小
* satelliteRadius 卫星的旋转半径
* rotation 组合体的x,y,z三个方向的旋转角度
* speed 卫星运动速度
* scene 场景
* {{satellite: THREE.Mesh, speed: *}} 卫星组合对象;速度
*/
initSatellite(satelliteSize, satelliteRadius, rotation, speed, scene,color="234,0,5") {
//轨道的大小颜色 轨道的颜色
var track = new THREE.Mesh(
new THREE.RingGeometry(satelliteRadius, satelliteRadius + 0.05, 50, 1),
new THREE.MeshBasicMaterial({ color: "#d38518" })
);
var centerMesh = new THREE.Mesh(
new THREE.SphereGeometry(1, 1, 1),
new THREE.MeshLambertMaterial({
color: 0xffff00,
side: THREE.DoubleSide,
})
); //材质设定
var satellite = new THREE.Sprite(
new THREE.SpriteMaterial({
map: new THREE.CanvasTexture(this.generateSprite(color)), //发光的颜色
blending: THREE.AdditiveBlending,
})
);
satellite.scale.x = satellite.scale.y = satellite.scale.z = satelliteSize;
satellite.position.set(satelliteRadius, 0, 0);
var pivotPoint = new THREE.Object3D();
pivotPoint.add(satellite);
pivotPoint.add(track);
centerMesh.add(pivotPoint);
centerMesh.position.set(0, 0, 20); //设置旋转中心
centerMesh.rotation.set(rotation.x, rotation.y, rotation.z);
scene.add(centerMesh);
return { satellite: centerMesh, speed: speed };
},
/**
* 实现发光星星
*color 颜色的r,g和b值,比如:“123,123,123”;
* {Element} 返回canvas对象
*/
generateSprite(color) {
var canvas = document.createElement("canvas");
canvas.width = 16; //发光的范围
canvas.height = 16;
var context = canvas.getContext("2d");
var gradient = context.createRadialGradient(
canvas.width / 2,
canvas.height / 2,
0,
canvas.width / 2,
canvas.height / 2,
canvas.width / 2
);
gradient.addColorStop(0, "rgba(" + color + ",1)"); //发光的颜色和透明度
gradient.addColorStop(0.2, "rgba(" + color + ",1)");
gradient.addColorStop(0.4, "rgba(" + color + ",.6)"); //.6
gradient.addColorStop(1, "rgba(0,0,0,0)");
context.fillStyle = gradient;
context.fillRect(0, 0, canvas.width, canvas.height);
return canvas;
},
},
};
</script>
引入外部3D模型 格式gltf
npm install gsap
npm install vue-count-to -D
npm install vue-seamless-scroll --save
<template>
<div>
<div style="display: flex;justify-content: space-between;">
<div style="z-index: 13;width: 240px;height: 100px;background-color: #49944c;display: flex;align-items: center;padding: 10px;border-radius: 4px;">
<span style="color: #FFFFFF;">总数:</span>
<countTo :startVal='startVal' :endVal='endVal' :duration='3000' separator=',' style="color: #fff;font-size: 36px;"></countTo>
</div>
<div style="z-index: 13;width: 400px;height: 120px;background-color: #49944c;overflow: hidden;padding: 0 10px;border-radius: 4px;">
<table cellspacing="0" cellpadding="0" width="100%" style="table-layout: fixed;word-wrap:break-word;">
<tr
style="border: 1px dashed #ffffff;color: #fff;"
>
<td width="90" class="tab_title">时间</td>
<td width="80" class="tab_title">用户</td>
<td width="50" class="tab_title">姓名</td>
<td class="tab_title">操作</td>
</tr>
</table>
<vue-seamless-scroll :data="listData" class="seamless-warp" :class-option="defaultOption" >
<table cellspacing="0" cellpadding="0" width="100%" style="table-layout: fixed;word-wrap:break-word;">
<tr
v-for="(item, index) in listData"
:key="index"
style="border: 1px dashed #ffffff;color: #fff;"
>
<td width="90" class="tab_title">{{ item.time }}</td>
<td width="80" class="tab_title">{{ item.number }}</td>
<td width="50" class="tab_title">{{ item.name }}</td>
<td class="tab_title" :title="item.kind">{{ item.kind }}</td>
</tr>
</table>
</vue-seamless-scroll>
</div>
<div id="main" style="width: 300px;height: 120px;z-index: 13;background-color: #49944c;border-radius: 4px;"></div>
</div>
<div id="container" style="width:100%;height:100%;z-index: 11;position: absolute;right: 0;bottom: 0;top: 0;left: 0;"></div>
<div v-if="loadedData!=100" style="position: absolute;z-index: 14;top: 0;left: 0;right: 0;bottom: 0;background-color: #00243d;display: flex;align-items: center;justify-content: center;" >
<div style="width: 300px;">
<el-progress :format="format(loadedData)" :percentage="loadedData" status="warning" :text-inside="true" :stroke-width="22"></el-progress>
</div>
</div>
</div>
</template>
<script>
import gsap from "gsap";
import vueSeamlessScroll from 'vue-seamless-scroll'
//引入three包 最新版
import * as THREE from 'three'
//鼠标控制器 需要threejs高版本
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//引入模型加载器
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
//解压
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import { CSS2DObject, CSS2DRenderer } from "three/examples/jsm/renderers/CSS2DRenderer.js";
const echarts = require('echarts');
import countTo from 'vue-count-to';
export default {
components: { countTo ,vueSeamlessScroll},
data () {
return {
time:null,
startVal: 0,
endVal: 2020,
loadedData:0,
labelRenderer:null,//标签标题
container : null, // dom节点
clock:new THREE.Clock(),//时间
listData: [
{
number:'1212',
name:'xiaoming',
kind:'12213',
time:'2022-01-03',
},
{
number:'4545',
name:'xiaohuan',
kind:'432423',
time:'2022-01-04',
},
]
}
},
// 监听属性 类似于data概念
computed: {
defaultOption () {
return {
step: 0.2, // 数值越大速度滚动越快
limitMoveNum: 2, // 开始无缝滚动的数据量 this.dataList.length
hoverStop: true, // 是否开启鼠标悬停stop
direction: 1, // 0向下 1向上 2向左 3向右
openWatch: true, // 开启数据实时监控刷新dom
singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
waitTime: 1000 // 单步运动停止的时间(默认值1000ms)
}
}
},
mounted () {
this.scene = null // 场景
this.renderer = null // 渲染器
this.camera = null // 相机
this.model = null // 场景
this.light = null // 渲染器
this.controls= null // 控制器
this.init() //初始的方法都放在init
this.loadGltf()
this.animate()
this.drawLine();
},
created(){
this.setout()
},
destroyed: function () {
this.scene = null // 场景
this.renderer = null // 渲染器
this.camera = null // 相机
this.model = null // 场景
this.light = null // 渲染器
this.controls= null // 控制器
clearInterval(this.time); //清除计时器
this.time = null; //设置为null
},
methods: {
format(percentage) {
return () => {
return percentage!=100 ? '正在加载...'+percentage+'%' : percentage+'%'
}
},
setout(){
// 计时器正在进行中,退出函数
if (this.time != null) {
return;
}
// 计时器为空,操作
//需要加定时器 DOM没有那么快加载出来
this.time=setInterval(()=>{
let myChart = echarts.init(document.getElementById('main'));
myChart.clear()//清除画布
this.drawLine()
},6000)
},
drawLine () {
let myChart = echarts.init(document.getElementById('main'));
myChart.setOption({
title: {
text: '',
left: 'center',
top: '0%',
textStyle: {
fontSize: 12,
color: '#d5bb24',
fontWeight: 'normal'
}
},
// legend:{
// left:'center',
// icon:'pin',
// top:'10%',
// textStyle:{
// color:'#eaeaea'
// }
// },
tooltip: {
trigger:'axis',
axisPointer:{
type:'line'
}
},
grid: {
top:'20%',
left: '20%',
right: '6%',
bottom:'24%'
},
xAxis: {
data: ['1/1','1/2','1/3','1/4','1/5 ','1/6','1/7 '],
axisLine: {
lineStyle: {
color: 'rgba(255,255,255,0.12)'
}
},
axisLabel: {
margin: 10,
color: '#d6d6d6',
interval: 0,
// rotate:90,
textStyle: {
fontSize: 10
},
},
},
yAxis:[ {
type:'value',
//name:'次数',
splitLine: {
show: true,
lineStyle: {
color: '#00BFF3',
opacity:0.23
}
},
scale: true, //只显示有数据的那段
nameTextStyle:{
color:'#ffffff' ,
},
axisLabel:{
formatter:'{value}',
show: true,
margin: 20,
textStyle: {
color: '#ebebeb',
},
}
}],
series: [{
name: '次数',
type: 'line',
smooth: true,
data: [0,20,34,60,120,180,200,200,200,200,200,200],
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(91, 221, 217, 1.0)' // 0% 处的颜色
}, {
offset: 1,
color: 'rgba(165, 103, 218, 1.0)' // 100% 处的颜色
}], false),
barBorderRadius: [30, 30, 30, 30],
shadowColor: 'rgba(0,160,221,1)',
shadowBlur: 0,
}
},
label:{
normal:{
show:true,
formatter:function(params){
return params.value
},
position:'top',
fontSize:10,
color:'#f1f1f1'
}
}
}]
});
},
// 声明一个方法传入参数可以在不同的地方调用相机
cameraReset(position, lookAt, time = 1){
gsap.to(this.camera.position, {
x: position.x,
y: position.y,
z: position.z,
duration: time,
ease: "power4.out",
// onComplete: function () {
// 这是相机运动完成的回调,可以执行其他的方法.
// }
});
gsap.to(this.camera.lookAt, {
x: lookAt.x,
y: lookAt.y,
z: lookAt.z,
duration: time,
ease: "power4.out",
});
//控制器
gsap.to(this.controls.target, {
x: lookAt.x,
y: lookAt.y,
z: lookAt.z,
duration: time,
ease: "power4.out",
});
},
// 声明一个方法传入参数可以在不同的地方位移
objReset(obj,x,y,z, time = 1){
//时间线可以用来排列动画的播放顺序
let tl = gsap.timeline({repeat:-1});
tl.to(obj.position, {
x:0,
y: -34,
z: 0,
duration: time
},">-0.1")
.to(obj.rotation, {
z: -Math.PI/2,
duration: 0.1
},">-0.1")
.to(obj.position, {
x: -15.5,
y: -34,
z: 0,
duration: 3
},">-0.1")
.to(obj.rotation, {
z: -Math.PI,
duration: 0.1
},">-0.1")
.to(obj.position, {
x: -15.5,
y: 0,
z: 0,
duration: time
},">-0.1")
.to(obj.rotation, {
z: Math.PI/2,
duration: 0.1
},">-0.1")
.to(obj.position, {
x: 0,
y: 0,
z: 0,
duration: 3
},">-0.1")
},
//初始化
init() {
this.container = document.getElementById('container');//获取dom元素
this.scene = new THREE.Scene();
//this.scene.background = new THREE.Color(0xcccccc);
this.camera = new THREE.PerspectiveCamera(60,this.container.clientWidth/this.container.clientHeight,1,5000);
this.camera.position.set(30,30,30); //定位相机
this.camera.lookAt(0,0,0); //看向哪里
//消除锯齿{antialias: true} 透明背景alpha: true
this.renderer = new THREE.WebGLRenderer({antialias: true,alpha: true});
this.renderer.setSize(this.container.clientWidth,this.container.clientHeight);
//半球光 光源直接放置于场景之上,光照颜色从天空光线颜色颜色渐变到地面光线颜色。
//参数: 天空中发出光线的颜色 地面发出光线的颜色 光照强度
let hemiLight = new THREE.HemisphereLight(0xffffff, 0xdddddd, 1);
this.scene.add(hemiLight);
//聚光灯
this.light = new THREE.SpotLight(0xdddddd,2);
this.light.position.set(20,20,20);
this.light.castShadow = true;//此属性设置为 true 聚光灯将投射阴影
this.light.shadow.bias = -0.0001;
//设置阴影分辨率 调整阴影的分辨率来消除马赛克样式的阴影
this.light.shadow.mapSize.width = 1024*4;
this.light.shadow.mapSize.height = 1024*4;
this.scene.add( this.light );
this.container.appendChild(this.renderer.domElement);
//标签渲染器
this.labelRenderer=new CSS2DRenderer();
this.labelRenderer.setSize(this.container.clientWidth,this.container.clientHeight)
this.labelRenderer.domElement.style.position='absolute';
this.labelRenderer.domElement.style.top='0px';
//添加此属性会使标签上的交互无法点击 如果不添加会屏蔽点击事件
this.labelRenderer.domElement.style.pointerEvents = 'none';
this.container.appendChild(this.labelRenderer.domElement)
//创建controls对象 控制器 摄像机 渲染到那个元素上
this.controls=new OrbitControls(this.camera,this.renderer.domElement)
this.controls.target = new THREE.Vector3(0, 0, 0);
// 使动画循环使用时阻尼或自转 意思是否有惯性
this.controls.enableDamping = false;
// 动态阻尼系数 就是鼠标拖拽旋转灵敏度
this.controls.dampingFactor = 0.04;
// 是否可以旋转
this.controls.enableRotate = false;
// 是否可以缩放与速度
this.controls.enableZoom = false;
// 设置相机距离原点的最进距离
this.controls.minDistance = 1;
// 设置相机距离原点的最远距离
this.controls.maxDistance = 2000;
// 是否开启右键拖拽
this.controls.enablePan = true;
//监听控制器的鼠标事件,执行渲染内容
this.controls.addEventListener('change',()=>{
this.renderer.render(this.scene,this.camera);
})
//监听窗口的变化
window.addEventListener('resize',()=>this.onWindowResize());
//监听鼠标的点击事件
this.renderer.domElement.addEventListener('click',event=>{
const { offsetX,offsetY} =event
// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
const x = ( offsetX / this.container.clientWidth ) * 2 - 1;
const y = - ( offsetY / this.container.clientHeight ) * 2 + 1;
//创建2D的坐标
const mousePoint=new THREE.Vector2(x,y)
//这个类用于进行raycasting(光线投射)光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体)
const raycaster =new THREE.Raycaster()
// 通过摄像机和鼠标位置更新射线
raycaster.setFromCamera(mousePoint,this.camera)
// 计算物体和射线的焦点
const intersects= raycaster.intersectObjects(this.scene.children,true)
//筛选 不点击网格 [0] 只取离鼠标最近的那个 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
const intersect=intersects.filter(intersect=>!(intersect.object instanceof THREE.GridHelper) && intersect.object.name !== 'plane' && !(intersect.object instanceof THREE.AxesHelper))[0]
//判断是否有点击的东西
if(intersect && this.isClickSoldier(intersect.object,'node_Lo-_01_-22946')){
//this.objReset(intersect.object,0,0,0 ,6)
console.log(intersect.object)
}
})
},
//递归点击模型 使用递归判断
isClickSoldier(object,name){
if(object.name===name){
return object;
}else if(object.parent){
return this.isClickSoldier(object.parent)
}else{
return null;
}
},
//监听窗口的大小变化 还有相机的比例
onWindowResize(){
this.camera.aspect=this.container.clientWidth/this.container.clientHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(this.container.clientWidth,this.container.clientHeight)
this.labelRenderer.setSize(this.container.clientWidth,this.container.clientHeight)
},
//递归实现
//@leafName 查找的name,
//@nodes 原始Json数据
//@path 供递归使用
findPathByLeafId(leafName, nodes,path){
if(path === undefined) {
path = {};
}
for(let i = 0; i < nodes.length; i++) {
let tmpPath= path;
// tmpPath.push(nodes[i].id);
if(leafName == nodes[i].name) {
tmpPath=nodes[i];
return tmpPath;
}
if(nodes[i].children) {
let findResult = this.findPathByLeafId(leafName, nodes[i].children,tmpPath);
if(findResult) {
return findResult;
}
}
}
},
// 外部模型加载函数
loadGltf(){
//加载模型
let loader =new GLTFLoader();
let dracoLoader = new DRACOLoader(); //解压
dracoLoader.setDecoderPath( 'draco/gltf/' );//设置解压库文件路径
dracoLoader.setDecoderConfig({type: 'js'}) //使用js方式解压
dracoLoader.preload() //初始化_initDecoder 解码器
loader.setDRACOLoader(dracoLoader) //gltfloader使用dracoLoader
//这里一点要注意目录结构 这里的只能加载静态文件里的
loader.load('test/model.glb',(gltf)=>{ //放入压缩的文件glb
//写一个递归找到对象
let chend=this.findPathByLeafId('node_Lo-_01_-22946',gltf.scene.children)
if(chend!==undefined){
this.objReset(chend,0,0,0 ,6)
//创建地球标签
let earthDiv=document.createElement('div');
earthDiv.className='label';
earthDiv.textContent='扫地车:发货看得开范德萨夸大事实';
let earthLable=new CSS2DObject(earthDiv)
//设置位置
earthLable.position.set(0,0,-6)
chend.add(earthLable)
}
// console.log(gltf.scene) //打印这个找到动画的属性 名称 name 命名
this.model=gltf.scene //获取模型对象
//设置模型位置
this.model.position.set(0,0,10);
if(this.scene) this.scene.add(this.model)
// 首页进入相机的视角,这个视角可以在三维模型中建立一个摄像机获取摄像机的坐标,如C4D,非常准确.
const cameraPosition = {
x: 20,
y: 20,
z: 20,
};
const cameraLookat = {
x: 10,
y: 0,
z: 0,
};
// 模型加载完,进行相机的初始化,传入设置的参数,模型加载为异步
if(this.scene) this.cameraReset(cameraPosition, cameraLookat,10);
},( xhr )=> {
this.loadedData=0
//console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
//进度条 进度
this.loadedData = Math.floor(xhr.loaded/xhr.total*100)
}, ( error )=> {
console.log( 'An error happened' );
})
},
//动画
animate() {
const delta = this.clock.getDelta();
//模型旋转动画
// if ( this.model ) this.model.rotation.y -= 0.04 * delta;
if(this.renderer){
this.renderer.render( this.scene, this.camera);
this.labelRenderer.render(this.scene,this.camera)
}
requestAnimationFrame( this.animate);
},
}
}
</script>
<style>
.seamless-warp {
overflow: hidden;
}
/* //溢出内容隐藏 //强制文本在一行内显示 //当对象内文本溢出时显示省略标*/
.tab_title{
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 10px;
}
.label{
color:#ffffff;
font-size:10px;
padding: 2px;
opacity: 0.8;
width: 80px;
overflow: hidden;
text-overflow: ellipsis;
border-radius: 2px;
background-color: #0187E6;
}
</style>