Move the placement of a slice on a pie chart using Three.js

I have successfully created a pie chart object using 3js ExtrudeGeometry. However, my current goal is to move out a slice from the piechart object, similar to the illustration in the image below.

https://i.sstatic.net/DRx7M.jpg

Below is the code snippet that I have implemented for this task.

<!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>

In my attempts to modify the x-position of the slices for movement, I encountered issues with overlapping when translating them. As illustrated in the images linked below:

https://i.sstatic.net/zC0XZ.jpg

https://i.sstatic.net/U59n6.jpg

I am seeking solutions or advice on how to achieve the desired slice movement without encountering overlap problems. Any help would be greatly appreciated!

Answer №1

Calculating the angle in radians is crucial when moving a slice outward in a specified direction.

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";
//Randomly generate a 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("Lets go!")

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() {

    //Calculate the angle for the slice movement direction
    var radians = (this.userData.angleEnd + this.userData.angleStart) * 0.5; //45;
    var vx = Math.cos(radians);
    var vz = -Math.sin(radians);

    //Imitating animation with fake values
    var tmp = this.userData.angleStart * 0.2;
    var sinTime = Math.abs(Math.sin(tmp + (time * 0.001)));

    //Move the slice accordingly
    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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the possibilities of ThreeJS: Fine-tuning projections and refining raycasting

In the ThreeJS sketch, there is a cube at Vector3(0.0, 0.0, 0.0) that is rotated with one edge facing the viewer. The code extracts some screen points from the left and right edges, transforms them to 3D world coordinates, and further projects them onto th ...

What is the mechanism behind range traversal in Javascript?

Exploring the createRange() function and related constructs in Javascript has sparked my curiosity about its practical applications. During my search, I stumbled upon an interesting application called "" that allows users to highlight text with mouse clic ...

Is my front-end JavaScript fetch request mistakenly being sent as a GET instead of a POST?

On clicking the submit button, a fetch request is triggered. Strangely, in the developer tools, it shows up as a GET request. I tested the request using Insomnia and it returned the handlebars site to me without any of my console logs appearing on either ...

What advantages does $sce or Strict Contextual Escaping provide in AngularJS, and why is it unnecessary for React?

I find it perplexing that I am unable to fully grasp the true value of utilizing SCE in AngularJS (even after reviewing the documentation) when it comes to security benefits. It leaves me wondering why React does not require SCE. So, to summarize my quest ...

"Encountering an issue when trying to choose a value from a select list using jQuery and the

What am I missing here or what is the correct approach to solve this? Take a look at the following code snippet: code snippet $(document).ready(function() { $(".metric_div").hide(); $("#solid_radio").click(function() { $("#solid").show(); ...

Securing Email and Password Data in Cypress Tests

Greetings! I trust everyone is in good spirits. My dilemma lies in the fact that I am hesitant to include email and passwords in version control. I am considering using environment variables in my cypress tests and utilizing secrets for runtime value pro ...

Steps to implement an image zoom function triggered by a button click

I'm working on a school project that requires me to use only html, css, and javascript for creating a website. Currently, I'm designing a landing page with a button that will navigate the user to another page. My goal is to have the background im ...

Exploring how to alter state in a child component using a function within the parent component in React

class ParentComponent extends Component { state = { isDialogOpen: false, setStyle: false } handleClose = () => { this.setState({ isDialogOpen: false, setStyle: false }) } handleOpen = () => { this.setState({ isDialogOpen: true ...

Enliven the character limit reaction by incorporating a thrilling shake animation when it reaches

I have implemented a feature in my component where if a user reaches the character limit, the component should shake. However, despite my efforts, the shaking effect is not working in the current code. const useStyles = makeStyles(() => ({ shake ...

The destroy method of Chart.js does not appear to have any impact on the

Hello, I've come across this issue in my react app that I need help with: this.chart = new Chart(node, options); // adding data to the chart ... this.chart.destroy(); this.chart = null; this.chart = new Chart(node, options); // adding data to the cha ...

What could be the reason the server actions in nextjs 13 are not functioning correctly?

I am currently working on a project to retrieve data from mockapi.io, a mock API. However, I am encountering an issue where the fetched data is not displaying in the browser. There are no visible errors, and the browser window remains blank. Interestingly, ...

Challenges with JavaScript and JQuery - Extracting and Displaying YouTube Information on Website

While I have some experience with Javascript and JQuery, my latest project on FirstPersonTheater.net is not going as planned. I am using PHP to generate a video ID in javascript code to retrieve information about YouTube videos such as title, uploader, vie ...

Issues with rendering of triangles in WebGL

My current project involves creating a webGL application for rendering randomly generated terrains. While the terrain rendering works smoothly, I've encountered an issue with rendering a simple quad to represent water - the triangles of the water are ...

Every time I attempt to insert a button from Semantic UI into my code, I consistently encounter an error message that reads: "Error: Unable to locate node on an unmounted

Struggling with a side project utilizing a MERNG stack. Can't seem to successfully add a button from semantic UI react documents into my code, sourced from here. Despite multiple attempts, encountering an error without clarity on the root cause. GitHu ...

Tips for establishing a universal onkeydown listener for all frames within a webpage?

Working with a complex legacy multi-frame webpage that needs to be compatible with IE-11 and responsive to hotkey events has brought up some challenges. It appears I can't simply declare a JavaScript method in the parent page. Rather, it seems that e ...

Effective ways to resolve the ajax problem of not appearing in the console

I am facing an issue with my simple ajax call in a Java spring boot application. The call is made to a controller method and the returned value should be displayed in the front-end console. However, after running the code, it shows a status of 400 but noth ...

Having an issue with my JavaScript burger menu not functioning properly

I'm really struggling to figure out why my code isn't working. I've checked and rechecked all the links, and everything seems correct. Could it possibly be because the code is outdated? I've been stuck on this for two days now and can&a ...

Await that's locked within a solo asynchronous function

async function submitForm(e){ e.preventDefault() console.log(e.target) try { const response = await axios.post('/api/<PATH>', {username, password}); console.log(response.data); const token = response.data.token if (t ...

I need help getting my Vue.JS project to function properly when it is deployed on a server

After creating a new VueJS project using the Vue UI, I noticed that everything runs smoothly locally at http://localhost:8080/ with no errors. However, when I build the project and upload the files from the dist folder to my hosting package via FTP, I end ...

Change the orientation of the HDR map using three.js

I've configured the x-axis as the up axis in my three.js scene, but now all HDR environment maps are incorrectly oriented. I've attempted to rotate the HDR file, but that hasn't resolved the issue. How can I fix this? this.pmremGenerator = n ...