Documentation
Overview
The Arcsine viewer represents an interactive 3D scene containing a model to view, select camera viewpoints to view the model from, and floating buttons to navigate to certain viewpoints. The viewer also handles a number of user input events to enable intuitive movement through this scene.
A key element of the viewer that distiguishes this technology from other 3D viewers is the notion of viewpoints. Each viewpoint defines a virtual camera position that perfectly aligns the camera's view of the model to a specific product photo. Selecting a viewpoint, through either interaction or code, will move the camera to view the object from the specified angle. Viewpoint data isn't loaded until it is viewed for the first time.
To use the viewer, an instance of it can be embedded directly through HTML, or through our Javascript SDK, with customization available in both methods.
Direct Embed
Include the SDK script:
<script src="https://cdn.arcsineimaging.com/scripts/2.4.0/sdk.bundle.js"></script>
A viewer can be embedded directly in HTML without any scripting.
<div arcsine-viewer="your-project-id"></div>
All elements with the arcsine-viewer attribute set will be automatically targeted by the SDK script and populated with a viewer instance. This example will load a model with the default configuration. The viewer will scale to the size of its container element so make sure this has a non-zero width and height.
Javascript Embed
Start by including the SDK script:
<script src="https://cdn.arcsineimaging.com/scripts/2.4.0/sdk.bundle.js"></script>
When the SDK loads, the Javascript API is accessible under window.arcsineImaging.
To initialize a viewer:
const viewer = window.arcsineImaging.createViewer(document.getElementById('viewer-container'), {
id: 'your-project-id'
});
To load the model:
// Load is asynchronous and returns a Promise.
viewer.load().then(() => {
console.log('loaded!');
// Now you can control the viewer with API methods.
});
Alternatively, you can handle the model to load with an event listener:
viewer.addEventListener('viewer-ready', () => {
console.log('loaded!');
});
Configuration
Direct embeds can be customized with HTML attributes while Javascript embeds use an options hash. These two examples are equivalent.
<div
id="viewer-container"
arcsine-viewer="your-project-id"
initial-viewpoint="1"
navigation="none"
>
</div>
const viewer = window.arcsineImaging.createViewer(document.getElementById('viewer-container'), {
id: 'your-project-id',
initialViewpoint: 1,
navigation: 'none'
});
This table provides an overview of viewer configuration options, their Javascript property name, corresponding HTML attribute, and default values.
Javascript | HTML | Description |
id | arcsine-viewer | The ID of your project.
This configuration option is required |
initialViewpoint | initial-viewpoint | The ID of the initial viewpoint.
Default: 0 |
initialAnimation | initial-animation | Type of animation to play when the viewer loads. Currently slideshow, turntable, scroll and none are supported. This should be used in combination with an animation configuration.
Default: none |
autoLoad | auto-load | Whether the model should load automatically. If false the model won't load until the container element receives a click event. The placeholder image will be shown in its place.
Default: true |
navigation | navigation | Type of viewpoint navigation bar to display.
Currently thumbnails or none are supported.
Default: thumbnails |
navigationOrder | navigation-order | Array of viewpoint IDs to include in the navigation bar in the order they appear from left to right. ex. [3, 1, 0, 5]
Default: Every viewpoint ordered by ID |
expandable | expandable | Whether to include UI to expand the viewer to fill the browser window.
Default: true |
backgroundOpacity | background-opacity | Background fill color overlay opacity. Valid range is [0.0, 1.0]
Default: 1.0 |
transitionDuration | transition-duration | Duration in milliseconds of viewpoint transitions initiated by user interaction.
Default: 1200 |
showViewpointTargets | show-viewpoint-targets | When to display detail viewpoint targets (the floating "plus icons"). One of always,
never or on-zoom.
Default: on-zoom |
captureScrollWheel | capture-scroll-wheel | Whether wheel events over the the viewer will zoom the model or scroll the page. This only applies to desktop.
One of always,
never or on-focus.
Default: always |
placeholder | placeholder | URL of image to display before the model is active.
Default: Displays a scaled image of the initial-viewpoint for a seamless transition into the 3D view. |
animations | See animations documentation. | |
viewpointFraming | See viewpoint framing documentation. |
Animations
Animations make it possible to move the camera to different viewpoints without direct user interaction. Currently there are three kinds of animations: turntable, slideshow, and scroll, each described below.
Animations are configured through the animations property. The animation set to play once the viewer loads can be configured through the initialAnimation property. Once the user initializes a click or touch event on the viewer the animation will stop, and the model will become freely interactable.
Multiple animations can be configured and controlled at runtime through the viewer.stopAnimation() and viewer.startAnimation() API calls.
const viewer = window.arcsineImaging.createViewer(document.getElementById('viewer-container'), {
id: 'your-project-id',
initialAnimation: 'turntable',
animations: {
turntable: {
// options
},
slideshow: {
// options
},
scroll: {
// options
}
}
});
Turntable
The turntable animation will rotate the model around the scene's vertical axis at a constant speed. This animation will only play if the current viewpoint is an outer type.
{
turntable: {
speed: 0.5, // Speed of the rotation. Negative values are counter-clockwise, positive are clockwise.
// Valid range is [-1.0, 1.0].
// Default: 0.25
startingViewpointId: 0, // Viewpoint to transition to when starting the turntable animation.
// Default: Value configured in `initialViewpoint`
}
}
Slideshow
The slideshow animation will cycle through a sequence of viewpoints and perform customizable 3D movements on each "slide". To explore all slideshow possibilities check out the animation designer.
{
slideshow: {
// Use these top-level properties to override defaults for every slide in the sequence.
slideDuration: 1500,
zoomDistance: 0.5,
orbitAngle: 90,
orbitDistance: 0.5,
transitionDuration: 1000,
repeat: false, // Whether to restart the slideshow when it reaches the last viewpoint in the sequence.
sequence: [
{
viewpointId: 0, // Active viewpoint for this slide.
// Required.
slideDuration: 2000, // Time in milliseconds representing how long to dwell on each viewpoint.
// Default: 2000
zoomDistance: 0.3, // Defines how far the camera should dolly in while a slide is active. Valid range is [0, 1].
// Default: 0.0
orbitAngle: 270, // Direction of orbit in degrees clockwise from up. Valid range is [-360, 360].
// Default: 0
orbitDistance: 0.25 // Defines how far the camera should orbit. Valid range is [0, 1].
// Default: 0.0
transitionDuration: 1500 // Duration in milliseconds for transition to the next viewpoint in the sequence.
// Default: Transition duration of the viewer.
}
//
// Additional steps in the slideshow sequence.
//
]
}
}
Scroll Experimental
This is an experimental feature and the API may be subject to change in future releases.The scroll animation will cycle through viewpoints and perform interpolated 3D movements based on the user's scroll position. It is usually used with a viewer styled with position: sticky; pointer-events: none; so that animations stay within the viewport and aren't disabled by touch events while scrolling. The animation is active when the top of the passed in boundingElement is above the top of the browser's viewport.
<!-- (scroll-animation-bounds height) = (viewer height) + (sum of sequence heights) -->
<div id="scroll-animation-bounds" style="height: 2100px; position: relative;">
<div id="viewer-root" style="top: 0; height: 600px; position: sticky;"></div>
</div>
{
scroll: {
boundingElement: document.getElementById('scroll-animation-bounds'),
sequence: [
{
viewpointId: 1, // Active viewpoint for this portion of the scroll animation.
// Required.
zoomDistance: 0.3, // Defines how far the camera should dolly in while a slide is active. Valid range is [0, 1].
// Default: 0.0
orbitAngle: 270, // Direction of orbit in degrees clockwise from up. Valid range is [-360, 360].
// Default: 0
orbitDistance: 0.25 // Defines how far the camera should orbit. Valid range is [0, 1].
// Default: 0.0
height: 500 // Vertical scroll distance in CSS pixels wherein this viewpoint will be shown.
// Required.
},
{
viewpointId: 2,
height: 500
},
{
viewpointId: 3,
height: 500
}
]
}
}
Viewpoint Framing
Viewpoint framing allows for viewpoints to be repositioned to better fit alongside page content, while maintaining the size and position of the viewer. This provides tighter control over how 3D content fits on the page as the viewer animates. Field of view is used to set the zoom of the viewpoint and the X & Y shifts control the pan. This feature is only available when using a Javascript embed. The viewpointFraming property can be used to customize framing before the viewer loads. See the synchronized text example for a demo of how this can be useful.
const viewer = window.arcsineImaging.createViewer(document.getElementById('viewer-container'), {
id: 'your-project-id',
viewpointFraming: {
0: { // Viewpoint ID for which the framing values will apply.
fov: 2.0, // Zooms camera to 200% of the viewpoint's intrinsic field of view.
// Valid range [0.25, 2.5]
// Default: 1.0
shiftX: 0.5, // Shifts camera right by 50% of viewport width.
// Valid range [-1.0, 1.0]
// Default: 0.0
shiftY: -0.1 // Shifts camera down by 10% of viewport height.
// Valid range [-1.0, 1.0]
// Default: 0.0
},
4: { // Additional viewpoints can be configured
// Omitted viewpoints or properties will retain their default values.
shiftX: 0.1
shiftY: 0.4
}
}
});
Additionally, viewport framing can be globally configured at runtime with viewer.enableViewpointFraming() and viewer.disableViewpointFraming(), or configured at the viewpoint level with viewpoint.setFov(), viewpoint.setShiftX(), and viewpoint.setShiftY().
API
Global Object
Available through window.arcsineImaging after the initial script loads.
createViewer(container: HTMLElement, options: Object): ArcsineViewer
Initialize a viewer embed inside of the passed container. The viewer will scale to the size of the container.
viewers : [ArcsineViewer]
Array of initialized viewer objects.
isSupportedBrowser : Boolean
Whether the client’s browser contains every feature needed to display the viewer.
ArcsineViewer Instance
element: HTMLElement
Element containing this viewer.
load(): Promise
ASYNC
Load the model’s assets. This is called automatically if autoLoad is set to true.
All API methods aside from addEventListener and removeEventListener can only be called after the returned Promise resolves.
getViewpointById(id: Number): Viewpoint
Returns the viewpoint with the passed ID or null if none match.
setViewpointById(id: Number): Promise
ASYNC
Performs an animated transition to passed viewpoint ID. The returned promise resolves with true when the transition is completed.
If a transition is already playing the viewer will attempt to wait for its conclusion before transitioning to the passed ID.
If the transition fails to play (usually a result of quickly repeated calls to this method) the returned promise will resolve with false.
getCurrentViewpoint(): Viewpoint
Returns the current viewpoint being projected onto the model.
getViewpoints(): [Viewpoint]
Returns an array of available viewpoints for this model.
resize()
Resizes the underlying <canvas> to fit the viewer's parent element.
startAnimation(animationType: String, config: Object): Promise
ASYNC
Begin playing the animation configured for the passed animation type. The returned promise resolves with true when the animation begins to play.
If an animation is already playing or no animation is configured
for the passed type the promise resolves with false.
The optional second argument will override any animation setup during viewer initialization and allow you to change animations at runtime.
stopAnimation()
Stop any running animation.
enableViewpointFraming()
Enable viewpoint framing for all viewpoints. Viewpoint framing is enabled by default.
disableViewpointFraming()
Disable viewpoint framing for all viewpoints.
addEventListener(eventName: String, listener: Function)
removeEventListener(eventName: String, listener: Function)
Event Name | Listener Argument | Fired When |
viewer-ready | None | Viewer is fully loaded and interactable. As a convenience, the arcsine-viewer-ready class will be added to the viewer's container element when this event is fired. |
animation-started | animationType : String | Animation begins playing |
animation-stopped | animationType : String | Animation stops playing |
transition-started | viewpointId : Number | Animated transition to a viewpoint starts. |
transition-finished | viewpointId : Number | Animated transition to a viewpoint finishes. |
viewpoint-id-changed | viewpointId : Number | Viewpoint being projected onto the model changes. |
Viewpoint Instance
id : Number
type : String
One of outer, detail or posed-outer.
- Outer viewpoints allow users to freely move between other outer viewpoints by dragging the camera through the scene. The model will automatically update based on nearby outer viewpoints. Double-clicking the background of the viewer will snap the camera to the nearest outer viewpoint.
- Detail viewpoints are focused on a single area of the model and have to be zoomed out to move to other viewpoints. Users can navigate to detail viewpoints from outer ones by clicking on the plus buttons that appear when zooming, or by double-clicking on the model.
- Posed outer viewpoints are a special type of viewpoint that combine elements of both outer and detail viewpoints. They are similar to detail ones in that when selected, movement is bound to only that viewpoint. However, no plus buttons will appear in the scene for these and are navigated to like outer viewpoints.
Viewpoint Framing
Note that viewpoint framing will only be applied after you transition to the viewpoint so applying new framing to the current viewpoint will not take immediate effect.
setFov(scale: Number)
Scale the viewpoint's intrinsic field of view by the passed value. Valid range is [0.25, 2.5].
setShiftX(shiftX: Number)
Set the viewpoint's horizontal lens shift. Valid range is [-1.0, 1.0].
setShiftY(shiftY: Number)
Set viewpoint's vertical lens shift. Valid range is [-1.0, 1.0].
Examples
Transparent background
Some designs require the model to run overtop of existing content without the default opaque background. Here's how to achieve this effect.
<div id="example-viewer-one" style="width: 100%; height: 300px; margin: auto;"></div>
<script>
const exampleViewerOne = window.arcsineImaging.createViewer(document.getElementById('example-viewer-one'), {
id: 'nike-cosmic-unityv1_5f5899bfbea0',
// First we configure the viewer to discard the background fill.
//
backgroundOpacity: 0.0,
// The default placeholder is a JPG which doesn't support transparency. In order to create a
// seamless transition with the fully-loaded 3D view we need to create a custom PNG of our initial
// viewpoint with the background cut out.
//
// Note the `?fit=scaled` parameter. This will tell the viewer to apply the same aspect-fitting & framing to
// your custom placeholder as it does to the default placeholder.
//
placeholder: 'https://arcsineimaging.com/assets/initial-viewpoint-transparent-0fbb0a4dd5e0bf7334343474731ae2e8a871cb02282eca39e88c1cc7803bd773.png?fit=scaled',
autoLoad: false,
expandable: false,
navigation: 'none'
});
</script>
Synchronize copy to model movements
Here we'll use viewpoint framing to create a more guided product storytelling experience. We'll also show how to toggle interactivity in the viewer.
Feature A
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Feature B
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Feature C
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
<div id="example-viewer-two"></div>
<div data-viewpoint="0" class="active feature" style="left: 0; top: 0;">
<h3>Feature A</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
<div data-viewpoint="7" class="feature" style="right: 0; top: 0;">
<h3>Feature B</h3>
<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<div data-viewpoint="5" class="feature" style="bottom: 20%; left:0;">
<h3>Feature C</h3>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>
</div>
<button data-viewpoint="0" class="feature-button">Feature A</button>
<button data-viewpoint="7" class="feature-button">Feature B</button>
<button data-viewpoint="5" class="feature-button">Feature C</button>
<button class="interactive-button">Enable Interactivity</button>
<style>
/*
* The `pointer-events` property can be used to toggle between a guided & fully-interactive experience.
*/
#example-viewer-two {
pointer-events: none;
width: 100%;
height: 600px;
margin: auto;
}
#example-viewer-two.interactive {
pointer-events: initial;
}
.feature {
text-align: left;
position: absolute;
width: 35%;
z-index: 1;
margin: 20px;
opacity: 0;
pointer-events: none;
transition: opacity 0.5s linear;
}
.feature.active {
transition-delay: 0.6s;
opacity: 1;
pointer-events: initial;
}
</style>
<script>
const exampleViewerTwo = window.arcsineImaging.createViewer(document.getElementById('example-viewer-two'), {
id: 'nike-cosmic-unityv1_5f5899bfbea0',
initialViewpoint: 0,
navigation: 'none',
expandable: false,
// Viewpoint framing is used here to position key angles alongside content on the page.
//
viewpointFraming: {
0: {
shiftX: 0.2,
fov: 1.5
},
5: {
shiftX: 0.15,
fov: 0.6
},
7: {
shiftX: -0.25,
fov: 0.8
}
},
// We'll configure an animation to play when the user chooses to make the viewer interactive.
// Initially nothing is animated as no `initialAnimation` property is configured.
//
animations: {
turntable: {
speed: -0.5,
startingViewpointId: 3
}
}
});
exampleViewerTwo.load().then(() => {
const featureButtons = document.querySelectorAll('.feature-button');
const featureTextBlocks = document.querySelectorAll('.feature');
const interactiveButton = document.querySelector('.interactive-button');
let isInteractive = false;
const setInteractivity = (value) => {
if (isInteractive === value) { return; }
featureTextBlocks.forEach((block) => {
block.classList.remove('active');
});
exampleViewerTwo.element.classList.toggle('interactive', value);
// Dynamically toggle between centered viewpoints and viewpoints shifted to fit next to text.
//
value ? exampleViewerTwo.disableViewpointFraming() : exampleViewerTwo.enableViewpointFraming();
isInteractive = value;
}
const enableInteractivityClicked = () => {
setInteractivity(true);
exampleViewerTwo.startAnimation('turntable');
};
const showFeatureClicked = (event) => {
// Use hardcoded HTML data attributes to match animated elements to
// buttons and viewpoints.
//
const viewpoint = parseInt(event.currentTarget.getAttribute('data-viewpoint'));
// Ignore the event if the requested feature is already shown.
//
if (!isInteractive && viewpoint == exampleViewerTwo.getCurrentViewpoint().id)
{
return;
}
setInteractivity(false);
exampleViewerTwo.setViewpointById(viewpoint);
};
// We could wait for `setViewpointById` to resolve in the above function to show the text blocks
// but we'd have to wait for the entire transition to complete. (We'd also have to detect the case
// where the transition fails to play).
//
// Binding to `transition-started` allows us to start the text fade-in right at the start of the
// transition & synchronize the movement a little better.
//
exampleViewerTwo.addEventListener('transition-started', (id) => {
if (!isInteractive)
{
featureTextBlocks.forEach((block) => {
block.classList.remove('active');
});
const targetFeatureText = document.querySelector(`.feature[data-viewpoint="${id}"]`);
targetFeatureText.classList.add('active');
}
});
// Bind all button events.
//
featureButtons.forEach((button) => button.addEventListener('click', showFeatureClicked));
interactiveButton.addEventListener('click', enableInteractivityClicked);
});
</script>
Additional Information
Supported Browsers
Unsupported browsers (IE11 & older) will show a simplified, non-3D experience. We query the browser's feature set to determine compatibility. You can use window.arcsineImaging.isSupportedBrowser before loading a viewer to implement special behavior in this case.
Previous Versions
Unless otherwise noted this documentation is valid for Arcsine Viewer SDK versions 2.X.X. See the the v1 docs for information on previous versions.
Copyright
All models and photographs appearing on this site are the property of Arcsine Imaging, LLC. They are protected by U.S. Copyright Laws, and are not to be downloaded or reproduced in any way without the written permission of Arcsine Imaging, LLC.