Introducing camera update within the JavaScript SDK

Reading time: ~28min
Share

Introducing On-the-Fly Camera Update in the Apviz JavaScript SDK

We are pleased to announce a new feature in the Apviz JavaScript SDK: the ability to programmatically update the camera in real time.

This functionality is especially valuable for highlighting specific parts of your product, such as when using the marking feature. For more details, see Marking text or marking image.

Your Apviz release starts with the camera you have initially set up in your 3D editor. With this new feature, you now have the capability to adjust the camera settings programmatically while the release is live on your website.

Orbital camera overview

The Apviz orbital camera always points towards a given target position and can be rotated around it with touch screen and mouse.

The camera's location in relation to its target (the center of rotation) is determined by three key parameters: yaw, pitch, and distance:

Apvid 3D engine orbital camera diagram

Camera update

You can pass a camera object to the update function at any time like that:

await viewer.update({
  camera : {
    type : "ORBITAL_SMART",
    focalLength : 80,
    yaw : 0,
    pitch : 0
  }
});

The camera object is described by the following properties:

Property Description
type

Camera type as a string:

"ORBITAL_FIXED_TARGET" The target position is fixed and must be explicitly defined. No matter what brick is currently visible or not.
"ORBITAL_SMART"

The target position and the distance are automatically defined depending on what brick are currently visible.

At each update when the bricks are changing:

  • Target is automatically re-positioned to the centroid of all bricks on the scene.
  • The distance also may adapt in order to always have all bricks visible (with a 10% tolerance with the previous state).

focalLength Lens focal length as an integer ranging between 10 mm (inclusive) and 1000 mm (inclusive).
yaw

Initial longitudinal rotation of the camera around Y axis with the target as the center of rotation. The value is an angle in degrees ranging between 0° (inclusive) and 359.9° (inclusive), with 1 decimal precision.

Rotation is counterclockwise.

pitch

Initial latitudinal rotation of the camera around Z axis with the target as the center of rotation. The value is an angle in degrees ranging between -180° (inclusive) and 179.9° (inclusive), with 1 decimal precision.

Positive rotation is counterclockwise.

distance

Initial distance from camera to target in meters up to 5 decimal precision.

Depending on your camera type:

  • "ORBITAL_FIXED_TARGET": The property is mandatory.
  • "ORBITAL_SMART": The property is optional. When omitted, the distance will be automatically determined in order to fit all bricks in the div.

target

Only when using "ORBITAL_FIXED_TARGET".

Target position object with the following properties:

x X coordinate in meters up to 5 decimal precision.
y Y coordinate in meters up to 5 decimal precision.
z Z coordinate in meters up to 5 decimal precision.

If you wish to prevent viewing certain areas of your product that may be unsuitable, you can configure camera restrictions with the following optional properties:

Property Description
yawRestriction

Optional yaw restriction object with the following properties:

center The central yaw angle around which the camera is free to orbit. The camera's yaw will be restricted within the range center - size / 2 (inclusive) to center + size / 2 (inclusive). The value is expressed in degrees ranging between 0° (inclusive) and 359.9° (inclusive), with 1 decimal precision.
size

The angular size that defines the allowed yaw range around the center yaw. The camera's yaw will be restricted within the range center - size / 2 (inclusive) to center + size / 2 (inclusive). The value is expressed in degrees ranging between 0° (inclusive) and 359.9° (inclusive), with 1 decimal precision.

A value of 0° will completely lock the yaw to the center position.

Note that initial yaw MUST respect the provided restriction.

pitchRestriction

Optional pitch restriction object with the following properties:

center The central pitch angle around which the camera is free to orbit. The camera's pitch will be restricted within the range center - size / 2 (inclusive) to center + size / 2 (inclusive). The value is expressed in degrees ranging between -180° (inclusive) and 179.9° (inclusive), with 1 decimal precision.
size

The angular size that defines the allowed pitch range around the center pitch. The camera's pitch will be restricted within the range center - size / 2 (inclusive) to center + size / 2 (inclusive). The value is expressed in degrees ranging between 0° (inclusive) and 359.9° (inclusive), with 1 decimal precision.

A value of 0° will completely lock the pitch to the center position.

Note that initial pitch MUST respect the provided restriction.

distanceRestrictionMin

Optional minimum distance from camera to target in meters up to 5 decimal precision.

A value equal to distanceRestrictionMax completely locks the distance.

distanceRestrictionMax

Optional maximum distance from camera to target in meters up to 5 decimal precision.

A value equal to distanceRestrictionMin completely locks the distance.

Example:

<!doctype html>
<html>
  <head>
    <title>Apviz - Camera switch</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      #my-camera-menu { position: absolute; top: 10px; left: 10px; }
    </style>
  </head>
  <body>
    <!-- Container for the Apviz 3D viewer. -->
    <div id="apviz-3d-viewer" style="width: 100%; height:100vh"></div>

    <!-- Your camera radio buttons. -->
    <div id="my-camera-menu">
      <input type="radio" name="camera" id="marking" value="marking" />
      <label for="marking">Engraving zone</label>
      <input type="radio" name="camera" id="gem" value="gem" />
      <label for="gem">Gem</label>
      <input type="radio" name="camera" id="ring" value="ring" />
      <label for="ring">Whole ring</label>
    </div>

    <!-- Your custom initialization script. -->
    <script>
      async function apvizShowcaseReady(showcase) {

        // Initialize a 3D viewer and bind it to the div.
        const viewer = await showcase.createViewer({
          divId : "apviz-3d-viewer"
        });

        // Initial configuration that MUST explicitly include ALL the fields.
        // This will start displaying 3D.
        await viewer.update({
          fields : {
            "Gem" : "Diamond",
            "Ring" : "Gold Pink"
          }
        });

        // Handle camera update.
        document.querySelector("#marking").addEventListener("input", async () => {
          await viewer.update({
            camera : {
              type: "ORBITAL_FIXED_TARGET",
              focalLength: 800,
              yaw: 110,
              yawRestriction: { center: 110, size: 60 },
              pitch: -80,
              pitchRestriction: { center: -80, size: 40 },
              distance: 0.4,
              distanceRestrictionMin: 0.3,
              distanceRestrictionMax: 0.5,
              target: { x: 0, y: -0.01, z: 0 }
            }
          });
        });
        document.querySelector("#gem").addEventListener("input", async () => {
          await viewer.update({
            camera : {
              type: "ORBITAL_FIXED_TARGET",
              focalLength: 800,
              yaw: 110,
              pitch: -80,
              pitchRestriction: { center: -30, size: 100 },
              distance: 0.3,
              distanceRestrictionMin: 0.2,
              distanceRestrictionMax: 0.9,
              target: { x: 0, y: 0.01, z: 0 }
            }
          });
        });
        document.querySelector("#ring").addEventListener("input", async () => {
          await viewer.update({
            camera : {
              type: "ORBITAL_SMART",
              focalLength: 50,
              yaw: 90,
              pitch: 0,
              distanceRestrictionMin: 0.1
            }
          });
        });

      }
    </script>

    <!-- Non-blocking async script that will call "apvizShowcaseReady" once fully loaded. -->
    <script
      src="https://public.apviz.io/showcases/U0hPVzo1ajlKbGQxOFpN/releases/UkVMUzpIejE1ME5UMk1w/main.js"
      integrity="sha384-gsXDSToM7fE7cZsncUHyovYQwg2M+fi1S7LIlYStw1M1NhYL7E3eufm+TizwbO++"
      defer
      crossorigin="anonymous"
      data-apviz-callback="apvizShowcaseReady"
    ></script>
  </body>
</html>

ℹ️ You can pass multiple properties simultaneously to the update function, such as a field value, a marking zone, and a new camera state. The promise will be resolved once everything has been updated.

Get current camera state

The getCamera method allows capturing the current camera state so that it can be restored later.

// Get current camera state:
const result = await viewer.getCamera();

// The nested camera object can be passed as-is back to the `update` function:
await viewer.update({
  camera : result.camera
});

ℹ️ To capture the initial camera state, call the getCamera method before making any update calls.

Availability

This feature becomes available starting today. To utilize it, create a brand new release, as previous releases are immutable. The update function now supports the additional camera parameter.

For assistance, please reach out to your Apviz account manager or use the contact form.

Keep an eye on the changelog for more updates! 😉