<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
*{
margin: 0;
padding: 0;
}
canvas {
display: block;
margin: auto;
}
</style>
</head>
<body>
<div id="webgl"></div>
<script src="three.js"></script>
<script src="OrbitControls.js"></script>
<script>
window.onload = function() {
/*
参数
option: {
color: [];// 每个扇形体的颜色,非必需
data: [{
heightValue: 30%,// 高度百分比
sector: 20%,// 扇形百分比
}],
width: 400,// 窗口宽
height: 400,// 窗口高
antialias: true,// 抗锯齿,性能不好的情况请设置为false
alpha: true,// 背景透明
content: domObject, // 渲染视图的dom对象
itemStyle:{
radius: 20,// 扇形体上下底面的半径,默认20,
height: 100,// 扇形体最大高度,默认100
}
}
*/
function draw3DPieByThreeJS(option){
let _color = [0xc23531,0x2f4554,0x61a0a8,0xd48265,0x91c7ae,0x749f83,0xca8622,0xbda29a,0x6e7074,0x546570,0xc4ccd3];
let color = option.color || _color;
let data = option.data;
let radius = option.itemStyle.radius || 20;
let height = option.itemStyle.height || 100;
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(75, option.width / option.height, 1, 1000);
camera.position.x = 100;
camera.position.y = 100;
camera.position.z = 100;
camera.lookAt(new THREE.Vector3(0, 0, 0));
let renderer = new THREE.WebGLRenderer({
antialias: option.antialias || true,// 抗锯齿
alpha: option.alpha || true,// 背景透明
});
renderer.setSize(option.width, option.height);
let container = option.content;
let controls = new THREE.OrbitControls( camera, container );
container.appendChild(renderer.domElement);
let ambientLight = new THREE.AmbientLight(0xffffff, 0.8);// 环境灯
scene.add(ambientLight);
let directionalLight1 = new THREE.DirectionalLight( 0xffffff, 0.3);// 右后侧灯
directionalLight1.position.set( 1, 1, 1 );
let directionalLight2 = new THREE.DirectionalLight( 0xffffff, 0.3);// 左后侧灯
directionalLight2.position.set( -1, 1, -1 );
let directionalLight3 = new THREE.DirectionalLight( 0xffffff, 0.2);// 顶灯
directionalLight3.position.set( 0, 1, 0 );
scene.add(directionalLight1);
scene.add(directionalLight2);
scene.add(directionalLight3);
let currentAngle = 0;
option.data.forEach((item,index) => {
let heightValue = toFloat(item.heightValue);
let sector = toFloat(item.sector);
let group = new THREE.Group();
let geometry = new THREE.CylinderGeometry(radius, radius, height*heightValue, 64, 64, false, 0, (2*Math.PI)*sector);
let material = new THREE.MeshPhongMaterial({'color': color[index], side: THREE.DoubleSide});
let cylinder = new THREE.Mesh(geometry, material);
let bottomPosition = (height-height*heightValue)/2*-1;// 位置贴底
cylinder.position.set(0, bottomPosition, 0);
cylinder.rotation.y = currentAngle;
group.add(cylinder);
let planeGeometry = new THREE.PlaneGeometry(radius, height*heightValue);
let planeMaterial = new THREE.MeshLambertMaterial({color: color[index], side: THREE.DoubleSide});
let plane_A = new THREE.Mesh(planeGeometry, planeMaterial);// 两侧封口
let plane_B = new THREE.Mesh(planeGeometry, planeMaterial);// 两侧封口
let rotateObjA = changePivot(radius/2, bottomPosition*-1, 0, plane_A);
let rotateObjB = changePivot(radius/2, bottomPosition*-1, 0, plane_B);
rotateObjA.rotation.y = currentAngle + 0.5*Math.PI;
rotateObjB.rotation.y = currentAngle + 0.5*Math.PI + (2*Math.PI)*sector;
rotateObjA.position.set(0,0,0);
rotateObjB.position.set(0,0,0);
group.add(rotateObjA);
group.add(rotateObjB);
scene.add( group );
currentAngle += (2*Math.PI)*sector;// 记录已占角度
})
function animate() {
requestAnimationFrame( animate );
renderer.render(scene, camera);
}
//通过x,y,z指定旋转中心,obj是要旋转的对象
function changePivot(x,y,z,obj){
let wrapper = new THREE.Object3D();
wrapper.position.set(x,y,z);
wrapper.add(obj);
obj.position.set(-x,-y,-z);
return wrapper;
}
function toFloat(percent){
let weishu = parseFloat(percent).toString().includes('.')?parseFloat(percent).toString().split(".")[1].length:0;
return (parseFloat(percent)*0.01).toFixed(weishu+2);
}
animate();
}
// 调用
draw3DPieByThreeJS({
"data": [{
"heightValue": "20%",// 高度百分比
"sector": "10%",// 扇形百分比
},{
"heightValue": "30%",// 高度百分比
"sector": "20%",// 扇形百分比
},{
"heightValue": "50%",// 高度百分比
"sector": "25%",// 扇形百分比
},{
"heightValue": "60%",// 高度百分比
"sector": "25%",// 扇形百分比
},{
"heightValue": "40%",// 高度百分比
"sector": "20%",// 扇形百分比
}],
"width": 1000,// 窗口宽
"height": 600,// 窗口高
"content": document.getElementById('webgl'), // 渲染视图的dom对象
"itemStyle":{
"radius": 60,// 扇形体上下底面的半径,默认20,
"height": 100,// 扇形体最大高度,默认100
}
})
}
</script>
</body>
</html>
评论0
最新资源