首页 > 解决方案 > 在threejs中更改饼图切片的位置

问题描述

我使用 3js ExtrudeGeometry 创建了一个饼图对象。我的要求是从饼图对象中移出一个切片,如下图所示。

在此处输入图像描述

这是我尝试过的代码。

<!DOCTYPE html>
<html lang="en">
<head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no,    minimum-scale=1.0, maximum-scale=1.0">
    <style>
        body {
            font-family: Monospace;
            background-color: #f0f0f0;
            margin: 0px;
            overflow: hidden;
        }
    </style>
</head>
<body>

   <script src="js/three.js"></script>
   <script src="js/libs/stats.min.js"></script>
    <script src="js/Detector.js" type="text/javascript"></script>
    <script src="js/renderers/CanvasRenderer.js"></script>
    <script src="js/renderers/Projector.js"></script>
    <script src="https://threejs.org/examples/js/controls/OrbitControls.js">     </script>

    <script>
        var container, scene, camera, renderer, controls;
        var segments = [];
        init();
        animate();



    function init() {
       scene = new THREE.Scene();
       camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
       camera.position.set(5, 10, -10);

       scene.add(camera);

       var dirLight = new THREE.DirectionalLight(0xffffff, 1);
       dirLight.position.set(100, 100, 100);
       camera.add(dirLight);

      renderer = new THREE.WebGLRenderer({antialias: true});
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(renderer.domElement);

      controls = new THREE.OrbitControls(camera, renderer.domElement);

     var i;
     var startAngle=0;
     var color="blue";
     for(i=0;i<4;i++){  
     var smallSegment=createSegment(1, THREE.Math.degToRad(startAngle) ,THREE.Math.degToRad(startAngle+90), color);
    if(color=="blue"){
        color="red"
    }else{
        color="blue"
    }
    startAngle=startAngle+90;
    scene.add(smallSegment);
    segments.push(smallSegment);
  }

    //segments[0].position.x=segments[0].position.x+0.5;
   //segments[1].position.x=segments[1].position.x+0.5;
   //segments[2].position.x=segments[2].position.x+0.5;
   segments[3].position.x=segments[3].position.x+0.5;

}

function createSegment(radius, angleStart, angleEnd, color) {
    var extrOpt = {
    curveSegments: 32,
    steps: 1,
    amount: 0.1,
    bevelEnabled: false,
  };

  var Shape = new THREE.Shape();
  Shape.moveTo(0, 0);
  Shape.absarc(0, 0, radius, angleStart, angleEnd, false);
  Shape.lineTo(0, 0);

  var SegmentGeom = new THREE.ExtrudeGeometry( Shape, extrOpt );
  SegmentGeom.rotateX(-Math.PI / 2);
  var SegmentMat = new THREE.MeshLambertMaterial({
    color: color
  });
  var Segment = new THREE.Mesh(SegmentGeom, SegmentMat);
    return Segment;
}

function animate() {
    var time = new Date() * 0.001;
    requestAnimationFrame(animate);
    render();
}

function render() {
  renderer.render(scene, camera);
}


</script>

 </body>
 </html>

我试图更改需要移出的切片的 x 位置。但这并没有锻炼。当我更改 x 位置时,一些切片相互重叠。

在此处输入图像描述

在此处输入图像描述

有什么解决方案可以使这项工作正常工作吗?

标签: javascriptthree.js

解决方案


要将切片向外移动,您需要计算出要移动方向的弧度角。

var renderer = new THREE.WebGLRenderer();
var w = 300;
var h = 200;
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
  45, // Field of view
  w / h, // Aspect ratio
  0.1, // Near
  10000 // Far
);
camera.position.set(15, 10, 15);
camera.lookAt(scene.position);
controls = new THREE.OrbitControls(camera, renderer.domElement);

var light = new THREE.PointLight(0xFFFF00);
light.position.set(20, 20, 20);
scene.add(light);
var light1 = new THREE.AmbientLight(0x808080);
light1.position.set(20, 20, 20);
scene.add(light1);

var i;
var startAngle = 0;
var rnd = (rng) => {
  return Math.random() * rng
}
var color = "blue";
//Make a random pie chart...
for (startAngle = 0; startAngle < 360;) {
  var ang = rnd(40) + 5;
  if (ang + startAngle > 360) ang = 360 - startAngle;
  var smallSegment = createSegment(1, THREE.Math.degToRad(startAngle), THREE.Math.degToRad(startAngle + ang), color);
  if (color == "blue") {
    color = "red"
  } else {
    color = "blue"
  }
  scene.add(smallSegment);
  startAngle += ang;
}

console.log("start!")

var time = 0;

function createSegment(radius, angleStart, angleEnd, color) {
  var extrOpt = {
    curveSegments: 32,
    steps: 1,
    depth: 0.1,
    bevelEnabled: false,
  };

  var Shape = new THREE.Shape();
  Shape.moveTo(0, 0);
  Shape.absarc(0, 0, radius, angleStart, angleEnd, false);
  Shape.lineTo(0, 0);

  var SegmentGeom = new THREE.ExtrudeGeometry(Shape, extrOpt);
  SegmentGeom.rotateX(-Math.PI / 2);
  var SegmentMat = new THREE.MeshLambertMaterial({
    color: color
  });
  var Segment = new THREE.Mesh(SegmentGeom, SegmentMat);
  Segment.userData.angleStart = angleStart;
  Segment.userData.angleEnd = angleEnd;


  Segment.onBeforeRender = function() {

    //degrees is the angle of the direction you want to move the slice
    //We do the average of startAngle+endAngle to get the center angle of the slice
    var radians = (this.userData.angleEnd + this.userData.angleStart) * 0.5; //45;
    var vx = Math.cos(radians);
    var vz = -Math.sin(radians);

    //This is just some values I fake up to make it animate
    var tmp = this.userData.angleStart * 0.2;
    var sinTime = Math.abs(Math.sin(tmp + (time * 0.001)));


    //Move the actual piece
    this.position.x = sinTime * vx;
    this.position.z = sinTime * vz;
  }


  return Segment;
}


renderer.setClearColor(0xdddddd, 1);


(function animate(dt) {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
  time = dt;

})();
<script src="https://threejs.org/build/three.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>


推荐阅读