一个展示百分比的动态可视化组件(three.js实战11)
Posted 点燃火柴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个展示百分比的动态可视化组件(three.js实战11)相关的知识,希望对你有一定的参考价值。
一个展示百分比的动态可视化组件
1. demo效果
可视化组件百分比
2. demo代码js
为了方便后期使用,把demo效果抽成组件,写在component.js中,下面是这个文件内容
var CirclePercent = function () {
var self = this
this.percentNum = 0
this.circlePercent = new THREE.Group();
this.materialColor = new THREE.Color().setStyle('#0782F5')
this.lightMaterialColor = new THREE.Color().setStyle('#24FFFF')
this.circleGroup = new THREE.Group();
this.circlePointsPositions = null;
this.circlePointOne = null;
this.circlePointTwo = null;
this.circlePointThree = null;
this.currentAngle = 0;
const circleRadius = 5;
const circlePointMoveSpeed = 0.03;
this.centerText = null;
this.font = null;
//外侧梯形组成的圈
this.trapezoidsCircleGroup = new THREE.Group();
this.trapezoidPositions = null;
this.trapezoidTopPoints = null;
this.trapezoidBottomPoints = null;
this.trapezoidLightLineIndex = 10;
function getPointsFromOneCircle(circleRadius, pointNum) {
const curve = new THREE.EllipseCurve(
0, 0,
circleRadius, circleRadius,
Math.PI / 2, 5 * Math.PI / 2,
false,
0
);
return curve.getPoints(pointNum);
}
function createTrapezoid() {
const topWidth = 2;
const bottomWidth = 1.4;
const height = 2.2;
const path = new THREE.Shape();
path.moveTo(-topWidth / 2, height / 2);
path.lineTo(topWidth / 2, height / 2);
path.lineTo(bottomWidth / 2, -height / 2);
path.lineTo(-bottomWidth / 2, -height / 2);
path.moveTo(-topWidth / 2, height / 2);
path.closePath()
const material = new THREE.LineBasicMaterial({
color: 0x0782F5
});
// 拉伸几何体配置项说明
/* curveSegments — int,曲线上点的数量,默认值是12。
steps — int,用于沿着挤出样条的深度细分的点的数量,默认值为1。
depth — float,挤出的形状的深度,默认值为100。
bevelEnabled — bool,对挤出的形状应用是否斜角,默认值为true。
bevelThickness — float,设置原始形状上斜角的厚度。默认值为6。
bevelSize — float。斜角与原始形状轮廓之间的延伸距离,默认值为bevelThickness-2。
bevelSegments — int。斜角的分段层数,默认值为3。
extrudePath — THREE.CurvePath对象。一条沿着被挤出形状的三维样条线。
UVGenerator — Object。提供了UV生成器函数的对象。 */
// 拉伸几何体配置项
const options = {
depth: 0.1, //厚度
bevelEnabled: false, //是否要斜角
curveSegments: 1,
steps: 1
}
// 创建拉伸几何体
const geometry = new THREE.ExtrudeGeometry(path, options)
const trapezoid = new THREE.Mesh(geometry, material);
return trapezoid
}
this.initTrapezoidsCircle = (() => {
//绘制外层圆用来获取坐标
this.trapezoidPositions = getPointsFromOneCircle(circleRadius + 2, 20);
this.trapezoidPositions.forEach((position, index) => {
let trapezoid = createTrapezoid(index)
trapezoid.position.set(position.x, position.y, 0)
trapezoid.rotation.z = index * 2 * Math.PI / 20
this.trapezoidsCircleGroup.add(trapezoid);
})
this.circlePercent.add(this.trapezoidsCircleGroup)
})()
this.initCircle = (() => {
this.circlePointsPositions = getPointsFromOneCircle(circleRadius, 200);
const geometry = new THREE.BufferGeometry().setFromPoints(this.circlePointsPositions);
const material = new THREE.LineBasicMaterial({
color: this.lightMaterialColor
});
const circle = new THREE.Line(geometry, material);
this.circleGroup.add(circle);
const smallPointGeom = new THREE.SphereBufferGeometry(0.2, 32, 32);
this.circlePointOne = new THREE.Mesh(smallPointGeom, material)
this.circlePointOne.position.set(this.circlePointsPositions[0].x, this.circlePointsPositions[0].y, 0)
this.circleGroup.add(this.circlePointOne)
this.circlePointTwo = this.circlePointOne.clone()
this.circlePointTwo.position.set(this.circlePointsPositions[67].x, this.circlePointsPositions[67].y, 0)
this.circleGroup.add(this.circlePointTwo)
this.circlePointThree = this.circlePointOne.clone()
this.circlePointThree.position.set(this.circlePointsPositions[133].x, this.circlePointsPositions[133].y, 0)
this.circleGroup.add(this.circlePointThree)
this.circlePercent.add(this.circleGroup)
})()
this.circleTwoPointsAnimation = () => {
const angle = this.percentNum / 100 * (2 * Math.PI)
if (angle > this.currentAngle) {
this.currentAngle += 0.01
} else {
this.currentAngle -= 0.01
}
this.circlePointOne.position.x = Math.cos(this.currentAngle) * circleRadius
this.circlePointOne.position.y = Math.sin(this.currentAngle) * circleRadius
this.circlePointTwo.position.x = Math.cos(this.currentAngle + 2 * Math.PI / 3) * circleRadius
this.circlePointTwo.position.y = Math.sin(this.currentAngle + 2 * Math.PI / 3) * circleRadius
this.circlePointThree.position.x = Math.cos(this.currentAngle + 4 * Math.PI / 3) * circleRadius
this.circlePointThree.position.y = Math.sin(this.currentAngle + 4 * Math.PI / 3) * circleRadius
}
this.trapezoidsAnimation = () => {
//根据新值计算梯形块的索引
const lightLineIndex = parseInt(this.percentNum / 5)
if (lightLineIndex < this.trapezoidLightLineIndex) {
for (let i = this.trapezoidLightLineIndex; i > lightLineIndex; i -= 0.01) {
const index = 20 - parseInt(i)
this.trapezoidsCircleGroup.children[index].material.color = this.materialColor
}
} else {
for (let i = 0; i < lightLineIndex; i += 0.01) {
const index = 20 - parseInt(i)
this.trapezoidsCircleGroup.children[index].material.color = this.lightMaterialColor
}
}
this.trapezoidLightLineIndex = lightLineIndex
}
this.circlePercent.updatePercent = (percentNum) => {
this.percentNum = percentNum
this.circleTwoPointsAnimation()
this.trapezoidsAnimation()
}
return this.circlePercent
}
3. demo代码html
<!DOCTYPE html>
<html>
<head>
<title>可视化小元素</title>
<script type="text/javascript" src="../three/build/three.js"></script>
<script type="text/javascript" src="../three/examples/js/controls/OrbitControls.js"></script>
<script type="text/javascript" src="../three/examples/js/renderers/CSS2DRenderer.js"></script>
<script type="text/javascript" src="../three/examples/js/libs/stats.min.js"></script>
<!-- EffectComposer要先于其他后期处理文件引入,否则其他文件无法正确引入 -->
<script type="text/javascript" src="../three/examples/js/postprocessing/EffectComposer.js"></script>
<script type="text/javascript" src="../three/examples/js/postprocessing/RenderPass.js"></script>
<script type="text/javascript" src="../three/examples/js/postprocessing/ShaderPass.js"></script>
<script type="text/javascript" src="../three/examples/js/postprocessing/UnrealBloomPass.js"></script>
<script type="text/javascript" src="../three/examples/js/shaders/LuminosityHighPassShader.js"></script>
<script type="text/javascript" src="../three/examples/js/shaders/CopyShader.js"></script>
<script type="text/javascript" src="./js/components.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
.label {
color: #FFF;
font-family: sans-serif;
font-size: 50px;
padding: 2px;
background: rgba(0, 0, 0, .6);
}
</style>
</head>
<body>
<div id="Stats-output"></div>
<div id="WebGL-output"></div>
<script type="text/javascript">
var scene, camera, renderer, labelRenderer, labelDiv, stats, controls, clock;
var composer, unrealBloomPass;
var circlePercentComponent = null;
var currentNum = 20;
function initScene() {
scene = new THREE.Scene();
//用一张图加载为纹理作为场景背景
//scene.background = new THREE.TextureLoader().load("../assets/textures/starry-deep-outer-space-galaxy.jpg");
}
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 50);
camera.lookAt(new THREE.Vector3(0, 0, 0));
}
function initLight() {
//添加环境光
const ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight('#fff')
directionalLight.position.set(20, 30, 50)
scene.add(directionalLight)
//添加聚光灯
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40, 60, -10);
spotLight.castShadow = true;
scene.add(spotLight);
}
function initModel() {
initPlane();
circlePercentComponent = new CirclePercent()
scene.add(circlePercentComponent)
}
//创建底面
function initPlane() {
const planeGeometry = new THREE.PlaneGeometry(1, 1, 1, 1); //创建一个平面几何对象
//材质
const planeMaterial = new THREE.MeshLambertMaterial({
transparent: true,
opacity: 0.0
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
//平面添加到场景中
scene.add(plane);
//添加label
labelDiv = document.createElement('div');
labelDiv.className = 'label';
//labelDiv.textContent = currentNum+' %';
labelDiv.style.background = 'none';
const label = new THREE.CSS2DObject(labelDiv);
label.position.set(0, 0, -1);
plane.add(label);
}
//初始化渲染器
function initRender() {
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setClearColor(0x111111, 1); //设置背景颜色
renderer.setSize(window.innerWidth, window.innerHeight);
//renderer.shadowMap.enabled = true; //显示阴影
document.getElementById("WebGL-output").appendChild(renderer.domElement);
//创建CSS2DRenderer渲染器
labelRenderer = new THREE.CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '0px';
document.getElementById("WebGL-output").appendChild(labelRenderer.domElement);
}
//初始化轨道控制器
function initControls() {
clock = new THREE.Clock(); //创建THREE.Clock对象,用于计算上次调用经过的时间
controls = new THREE.OrbitControls(camera, renderer4行代码就可以完成一个Web版的3D地球可视化展示——Gio.js
开源Gio.js:一个基于 Three.js 的 Web3D 地球数据可视化库
基于Echarts+百度地图+Three.js的数据可视化系统
javascript 3d网页 简单几行代码创建一个动态水潭, 湖面 示例 ( three.js r114 初探 四)
javascript 3d网页 简单的 可视化编辑 图形界面 搭建几何体 带导出物体 示例 ( three.js r114 初探 六)