Dual Viewer
A draggable UI component which reveals two panes.
IE9+ with polyfill.
To support IE<=11, you will need to add classList
polyfill.
Dependencies
Odo Window Events, Odo Helpers, Odo Draggable, Odo Object Fit.
Object.assign
should also be available.
Styles
This component has required css - css/odo-dual-viewer.css. The theme (css/odo-dual-viewer-theme.css) should also be included and customized to your design.
Horizontal With Images
By default, the dual viewer is horizontal. When the user releases the scrubber, it will animate to the start, end, or center, depending on the zones
option.
Slide right or left to reveal more of one perspective.
Markup
This markup needs to be followed closely and is dependent on the dual viewer's css. You may put anything inside odo-dual-viewer__object
. This example is full-bleed, but it doesn’t have to be. See the video demo below for one that isn’t.
<div id="regular" class="odo-dual-viewer">
<div class="odo-dual-viewer__wrap odo-dual-viewer__overlay">
<div class="odo-dual-viewer__inner">
<div class="odo-dual-viewer__object">
<img class="odo-dual-viewer__media" src="https://placehold.it/320x400/1abc9c/ffffff&text=320w">
</div>
</div>
</div>
<div class="odo-dual-viewer__wrap odo-dual-viewer__underlay">
<div class="odo-dual-viewer__inner">
<div class="odo-dual-viewer__object">
<img class="odo-dual-viewer__media" src="https://placehold.it/320x400/3498db/ffffff&text=320w">
</div>
</div>
</div>
<div class="odo-dual-viewer__scrubber">
<div class="odo-dual-viewer__scrubber-handle grabbable"></div>
</div>
<div class="container">
<div class="odo-dual-viewer__scrubber-bounds">
</div>
</div>
</div>
Setup
var dualViewer = new OdoDualViewer(document.getElementById('regular'), {});
Scrubber Boundaries
The odo-dual-viewer__scrubber-bounds
element determines the limits of the draggable (scrubber). In this example, it is wrapped in a container
element, but that only applies to this page. The dual viewer will calculate the limits based on the distance from the left edge of odo-dual-viewer
to the left edge of odo-dual-viewer__scrubber-bounds
. The right edge is based on the width
of the scrubber bounds element.
Animating the dual viewer
You can programmatically animate the position of the scrubber in the dual viewer with the animateTo
method. The only parameter is a value between 0
and 1
, which represents the percentage to animate to. This value will be clamped to the scrubber’s limits.
document.getElementById('animate-to').addEventListener('click', function () {
var value = parseInt(document.getElementById('animate-to-value').value, 10);
dualViewer.animateTo(value / 100);
});
Vertical With Images
Slide right or left to reveal more of one perspective.
Markup
The markup for this vertical demo is identical to the horizontal demo above, except the id attribute is different.
Setup
var vertical = new OdoDualViewer(document.getElementById('vert'), {
isVertical: true
});
Horizontal With Videos
The dual viewer can hold any type of content. This one holds some html5 videos from gfycat. The first is Moon and cloudlapse and the second is Pouring Beauty Iceland.
Slide right or left to reveal more of one perspective.
Markup
The markup is nearly identical. <img>
s have been replaced by <video>
s and the scrubber bounds element now has inline styles defining its width.
<div id="dual-viewer-videos" class="odo-dual-viewer">
<div class="odo-dual-viewer__wrap odo-dual-viewer__overlay">
<div class="odo-dual-viewer__inner">
<div class="odo-dual-viewer__object">
<video class="odo-dual-viewer__media" autoplay loop>
<source src="https://zippy.gfycat.com/BestReflectingJunco.webm" type="video/webm">
<source src="https://zippy.gfycat.com/BestReflectingJunco.mp4" type="video/mp4">
</video>
</div>
</div>
</div>
<div class="odo-dual-viewer__wrap odo-dual-viewer__underlay">
<div class="odo-dual-viewer__inner">
<div class="odo-dual-viewer__object">
<video class="odo-dual-viewer__media" autoplay loop>
<source src="https://zippy.gfycat.com/EsteemedJovialHoneybadger.webm" type="video/webm">
<source src="https://zippy.gfycat.com/EsteemedJovialHoneybadger.mp4" type="video/mp4">
</video>
</div>
</div>
</div>
<div class="odo-dual-viewer__scrubber">
<div class="odo-dual-viewer__scrubber-handle grabbable"></div>
</div>
<!-- Not part of odo-dual-viewer.css - absolutely positioned -->
<p class="dual-viewer__help">Slide right or left to reveal more of one perspective.</p>
<div class="odo-dual-viewer__scrubber-bounds" style="width:80%;margin:auto;"></div>
</div>
Setup
var vid = new OdoDualViewer(document.getElementById('dual-viewer-videos'), {
animationDuration: 400,
zones: [0.3, 0.4, 0.6, 0.7]
});
Zones
When the user releases the scrubber, the dual viewer uses the position of scrubber as a percentage as a zone. The default zones
option is [0.33, 0.33, 0.66, 0.66]
. The first value in the array represents the lower zone. If the scrubber position (as a percent) is less than that value, the dual viewer will animate to 0
percent (within the boundaries). The second and third values create a zone for the middle. When the scrubber is released in the middle zone, it animates to the center. The last value is the upper zone. Any value above it will animate the scrubber to 1
percent (within the boundaries).
L = lower zone
M = middle zone
U = upper zone
+-------------------------------------+
| | | | | |
| | | | | |
| L | | M | | U |
| | | | | |
| | | | | |
+-------------------------------------+
| | |
0.25 0.5 0.75
If the scrubber is released between zones, nothing will happen.
Zones work the same way for vertical dual viewers with the lower zone on top and the upper zone at the bottom.
Like the example above, zones can overlap. The lower and upper zones take precedence over the middle.
Events
The dual viewer emits a CAME_TO_REST
event when the handle stops animating.
vid.on(OdoDualViewer.EventType.CAME_TO_REST, function(event) {
switch (event.position) {
case OdoDualViewer.Position.START:
console.log('Handle came to rest at the start');
break;
case OdoDualViewer.Position.END:
console.log('Handle came to rest at the end');
break;
case OdoDualViewer.Position.CENTER:
console.log('Handle came to rest in the center');
break;
}
});
No Zones
This example does not use zones to animate to a resting position.
Setup
var noZones = new OdoDualViewer(document.getElementById('no-zones'), {
hasZones: false,
startPosition: 0.1
});
Starting Position
The starting position of the scrubber and the amount revealed when the module is initialized can be changed. By default, it's 50%, but using the startPosition
option and a value between zero and one, you may change this behavior.