SVG Loader: Change values dynamically with a button/input range

Hi,

I’m wondering how to change the value of metalness using an input range and the depth using a button click. Changing the lighting, for example, is pretty straightforward (I think), and there is an example provided below. What’s confusing me about changing the variables (in this case, metalness and depth) is that they are inside a nested for loop because of the SVGLoader.

I am grateful for answers or hints about a solution.

I tried to create a minimal demo using codepen but I didn’t know how to import a svg file.

loader.load('box.svg', function ( data ) {
  const paths = data.paths;
  group = new THREE.Group();

  for (let i = 0; i < paths.length; i++) {
    const path = paths[i];
    const shapes = path.toShapes(true);

    for (let j = 0; j < shapes.length; j++) {
      const shape = shapes[j];
      const extrudeSettings = {
        depth: 20,
      };
      const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);

      const material = new THREE.MeshStandardMaterial({
        metalness: 0.144
      });

      ...........
});

In order to change the value of the directional light, I would do it in this way:

const lightIntensityInput = document.getElementById('lightIntensity');

const updateDirectionalLightIntensity = () => {
  const intensity = parseFloat(lightIntensityInput.value);
  directionalLight.intensity = intensity;
};
      <label for="lighth">Light intensity:</label>
      <input type="range" id="lightIntensity" min="0" max="10" step="0.1" value="1">

But as I mentioned before, it’s easier to access the lightning properties because it’s not inside of a nested for loop.

There are two questions. Let me try to answer each of them:

  • Metalness: while processing the SVG paths and shapes, you can collect all materials in an array, and then, when the user wants to change the metalness, you set the metalness of the stored materials.

  • Using SVG in CodePen: for free users you can host the SVG somewhere else, or encode it as DataURI. However, a cleaner approach is to have it as text and instead of SVGLoader.load, use SVGLoader.parse.

Here is a demo for both things:

  • the rounded cube changes metalness every 2 seconds; there is OrbitControls, so the scene can be rotated;

  • the materials are stored in line 77, metalness is changed in line 96, SVG is defined in lines 41-43, and SVG parsing is in line 61:

https://codepen.io/boytchev/full/dywMqzO

image

Thank you for a quick response! But just to confirm that I have understood, since we have collected all the materials in an array, I should be able to do this:

var metalnessChangeVal = document.getElementById("metalness");
var currentMetalnessVal = parseFloat(metalnessChangeVal.value); 

metalnessChangeVal.addEventListener("input", function() {
    currentMetalnessVal = parseFloat(metalnessChangeVal.value);
});

function animationLoop() {
    for (var material of materials) {
        material.metalness = currentMetalnessVal;
    }
    
    controls.update();
    light.position.copy(camera.position);
    renderer.render(scene, camera);
}

CodePen

Does the same principle apply if I want to change extrude settings?

Also, thank you for answering how to use SVG in CodePen.

It is better to put this code:

for (var material of materials) {
        material.metalness = currentMetalnessVal;
    }

inside the event handler for metalness – in this way the materials will be updated only when needed. Something like this:

function updateMetalness( )
{
    var metalnessVal = parseFloat(metalnessChangeVal.value);

    for (var material of materials) {
        material.metalness = metalnessVal;
    }
}


var metalnessChangeVal = document.getElementById("metalness");
updateMetalness( ); 

metalnessChangeVal.addEventListener("input", updateMetalness);

function animationLoop() {
    controls.update();
    light.position.copy(camera.position);
    renderer.render(scene, camera);
}

If this code stays in the animation loop, it will be executed every frame (e.g. 60 times per second), which is unnecessary.

The extrusion settings need more work, because they affect the geometry. If they are changed, the geometries must be regenerated (and the old geometries must be disposed). If you do this, do it only in the event handler, not in the animation loop.

Thank you for your time and the good explanation.

1 Like