<div class="image-compare column" data-vertical="true">
<div class=" media ">
<img class="media__item" src="/demo/teaser/teaser6.jpg" alt=>
</div>
<div class="second-image vertical">
<div class="handle">
<div class="caption first">Caption of first image</div>
<div class="comparator"></div>
<div class="caption second">Caption of first image</div>
</div>
<div class="wrapper">
<div class=" media ">
<img class="media__item" src="/demo/teaser/teaser5.jpg" alt=>
</div>
</div>
</div>
</div>
<div class="image-compare column" data-vertical="true">
{{render '@atoms-media--image' image1}}
<div class="second-image vertical">
<div class="handle">
<div class="caption first">{{caption1}}</div>
<div class="comparator"></div>
<div class="caption second">{{caption1}}</div>
</div>
<div class="wrapper">
{{render '@atoms-media--image' image2}}
</div>
</div>
</div>
{
"image1": {
"src": "/demo/teaser/teaser6.jpg"
},
"image2": {
"src": "/demo/teaser/teaser5.jpg"
},
"caption1": "Caption of first image",
"caption2": "Caption of second image"
}
.image-compare {
position: relative;
padding: 0;
overflow: hidden;
user-select: none;
-webkit-touch-callout: none;
.media {
font-size: 1px;
}
.second-image {
position: absolute;
top: 0;
right: 0;
// display: none;
width: 50%;
height: 100%;
padding: 0 0 0 2.4rem;
text-align: right;
.wrapper {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
.media {
display: inline-block;
float: right;
}
&.vertical {
top: inherit;
right: inherit;
bottom: 0;
left: 0;
width: 100%;
height: 50%;
padding: 2.4rem 0 0;
.handle {
top: 0;
left: inherit;
width: 100%;
height: 4.8rem;
cursor: n-resize;
.caption {
left: 0;
&.first {
top: auto;
right: auto;
bottom: 2.6rem;
}
&.second {
top: 2.6rem;
bottom: auto;
left: auto;
}
}
&::before,
&::after {
top: -15px;
left: 50%;
width: 30px;
height: 20px;
margin: 0 0 0 -15px;
background-position-x: -43px;
text-align: left;
}
&::before {
$symbol: map-get($icons, 'chevron-up');
@include icon-content-extended($symbol, block, 3rem);
line-height: 2rem;
}
&::after {
$symbol: map-get($icons, 'chevron-down');
@include icon-content-extended($symbol, block, 3rem);
top: auto;
bottom: -15px;
line-height: 2rem;
}
&:hover,
&.active {
&::before {
top: -5px;
}
&::after {
bottom: -5px;
}
}
.comparator {
width: 100%;
height: 4px;
margin: 2.2rem 0;
}
}
.media {
position: absolute;
bottom: 0;
left: 0;
}
}
}
.handle {
position: absolute;
left: 0;
z-index: 20;
width: 4.8rem;
height: 100%;
cursor: w-resize;
&::before,
&::after {
position: absolute;
top: 50%;
display: block;
width: 2rem;
height: 3rem;
margin-top: -1.5rem;
font-size: 3rem;
color: $white;
transition: all 0.25s linear;
}
&::before {
$symbol: map-get($icons, 'chevron-left');
@include icon-content-extended($symbol, block, 3rem);
left: -1.5rem;
}
&::after {
$symbol: map-get($icons, 'chevron-right');
@include icon-content-extended($symbol, block, 3rem);
right: -1.5rem;
text-align: left;
}
&:hover,
&.active {
&::before {
left: -0.5rem;
}
&::after {
right: -0.5rem;
}
}
.comparator {
width: 4px;
height: 100%;
margin: 0 auto;
background-color: $primary;
}
.caption {
position: absolute;
top: 0;
min-width: 100px;
padding: 10px;
border: 0;
&.first {
right: 2.6rem;
background-color: $gray;
color: $white;
}
&.second {
left: 2.6rem;
background-color: $white;
color: $primary;
text-align: left;
}
}
}
}
Example code snippet from coremedia9:
import $ from 'jquery';
import * as nodeDecorationService from '@coremedia/js-node-decoration-service';
import {EVENT_LAYOUT_CHANGED} from '@coremedia/js-basic';
const IMAGE_COMPARE_SELECTOR = '.image-compare';
const IMAGE_SELECTOR = '.media';
const SECOND_BLOCK_SELECTOR = '.second-image';
const HANDLE_SELECTOR = '.handle';
const $document = $(document);
$(function() {
nodeDecorationService.addNodeDecoratorBySelector(IMAGE_COMPARE_SELECTOR, function ($target) {
$.each($target, function () {
const options = {
$element: $target
};
init();
function init() {
options.vertical = options.$element.data('vertical') || false;
options.vertical && getSecondBlock().addClass('vertical');
options.dimension = 50;
options.mousePosition = {x: 0, y: 0};
options.proxyFunction = null;
getSecondBlock().show();
resize();
bindEvents();
$document.trigger(EVENT_LAYOUT_CHANGED);
}
function bindEvents() {
let comparator = getHandle()[0];
comparator.addEventListener('mousedown', function(e) {
options.mousePosition = {x: e.x, y: e.y};
options.proxyFunction = mouseMove;
getHandle().addClass('active');
document.addEventListener('mousemove', options.proxyFunction, false);
}, false);
document.addEventListener("mouseup", function(e) {
options.proxyFunction && (document.removeEventListener('mousemove', options.proxyFunction, false), options.proxyFunction = null, getHandle().removeClass('active'));
}, false);
comparator.addEventListener('touchstart', function(e) {
e.preventDefault();
if (e.touches.length > 1) { // skip multitouch
return;
}
const touch = e.touches[0];
options.mousePosition = {x: touch.clientX, y: touch.clientY};
options.proxyFunction = touchMove;
getHandle().addClass('active');
document.addEventListener("touchmove", options.proxyFunction, false);
}, false);
document.addEventListener("touchend", function(e) {
options.proxyFunction && (document.removeEventListener("touchmove", options.proxyFunction, false), options.proxyFunction = null, getHandle().removeClass('active'));
}, false);
}
function mouseMove(e) {
e && e.preventDefault();
moveComparator({x: e.x, y: e.y});
}
function touchMove(e) {
e.preventDefault();
if (e.touches.length > 1) {
return;
}
var touch = e.touches[0];
moveComparator({x: touch.clientX, y: touch.clientY});
}
function moveComparator(newPosition) {
const delta = (options.mousePosition[options.vertical ? 'y' : 'x'] - newPosition[options.vertical ? 'y' : 'x']) / options.$element[options.vertical ? 'height' : 'width']() * 100;
options.dimension += delta;
options.dimension < 0 && (options.dimension = 0);
options.dimension > 100 && (options.dimension = 100);
options.mousePosition = newPosition;
getSecondBlock()[options.vertical ? 'height' : 'width'](getSecondImage()[options.vertical ? 'height' : 'width']() * options.dimension / 100);
}
function getHandle() {
return options.$handle || (options.$handle = $(HANDLE_SELECTOR, options.$element));
}
function getFirstImage() {
return options.$firstImage || (options.$firstImage = $(IMAGE_SELECTOR + ':first', options.$element));
}
function getSecondBlock() {
return options.$secondBlock || (options.$secondBlock = $(SECOND_BLOCK_SELECTOR, options.$element));
}
function getSecondImage() {
return options.$secondImage || (options.$secondImage = $(IMAGE_SELECTOR, getSecondBlock()));
}
function resize() {
getSecondImage().width(getFirstImage().width());
getSecondBlock()[options.vertical ? 'height' : 'width'](options.dimension + '%');
}
$document.on(EVENT_LAYOUT_CHANGED, function() {
resize();
});
});
});
});