Using Pixi.js plugin displacement filter to “morph” images while hovering connected sidebar links. Done using html, css, jQuery, TweenMax and pixi.js. Demo and download available.
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.7.1/pixi.min.js'></script>
HTML Snippet
<h2 class="u-a7">
Menu — Portfolio
</h2>
<div class="c-work">
<ul class="c-work__list js-work">
<!-- WORK ITEM -->
<li class="c-work__item">
<div class="c-work-item js-work-item" data-work-preview-id="0">
<span class="c-work-item__number u-b6">
01
</span>
<div class="c-work-item__title">
<h3 class="u-a6">
Hone Products
</h3>
</div>
<span class="c-work-item__category u-b4">
<i>/</i>Website
</span>
</div>
</li>
<!-- //WORK ITEM -->
<!-- WORK ITEM -->
<li class="c-work__item">
<div class="c-work-item js-work-item" data-work-preview-id="1">
<span class="c-work-item__number u-b6">
02
</span>
<div class="c-work-item__title">
<h3 class="u-a6">
Urban Culture
</h3>
</div>
<span class="c-work-item__category u-b4">
<i>/</i>Digital Presentation
</span>
</div>
</li>
<!-- //WORK ITEM -->
<!-- WORK ITEM -->
<li class="c-work__item">
<div class="c-work-item js-work-item" data-work-preview-id="2">
<span class="c-work-item__number u-b6">
03
</span>
<div class="c-work-item__title">
<h3 class="u-a6">
X — 6
</h3>
</div>
<span class="c-work-item__category u-b4">
<i>/</i>Website
</span>
</div>
</li>
<!-- //WORK ITEM -->
<!-- WORK ITEM -->
<li class="c-work__item">
<div class="c-work-item js-work-item" data-work-preview-id="3">
<span class="c-work-item__number u-b6">
04
</span>
<div class="c-work-item__title">
<h3 class="u-a6">
Difference
</h3>
</div>
<span class="c-work-item__category u-b4">
<i>/</i>Branding
</span>
</div>
</li>
<!-- //WORK ITEM -->
<!-- WORK ITEM -->
<li class="c-work__item">
<div class="c-work-item js-work-item" data-work-preview-id="4">
<span class="c-work-item__number u-b6">
05
</span>
<div class="c-work-item__title">
<h3 class="u-a6">
Cali-Hype
</h3>
</div>
<span class="c-work-item__category u-b4">
<i>/</i>E-commerce
</span>
</div>
</li>
<!-- //WORK ITEM -->
<!-- WORK ITEM -->
<li class="c-work__item">
<div class="c-work-item js-work-item" data-work-preview-id="5">
<span class="c-work-item__number u-b6">
06
</span>
<div class="c-work-item__title">
<h3 class="u-a6">
Prada x Diesel
</h3>
</div>
<span class="c-work-item__category u-b4">
<i>/</i>Website
</span>
</div>
</li>
<!-- //WORK ITEM -->
</ul>
<div class="c-work-preview">
<div class="c-work-preview__canvas js-work-preview-list">
<div class="canvas js-work-preview-canvas" data-displacement-map="https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/ui/rock.png" style="background-image: url(https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/ui/rock.png);"></div>
</div>
<ul class="c-work-preview__list js-work-preview-list">
<!-- WORK ITEM PREVIEW -->
<li class="c-work-preview__item">
<i class="c-work-preview__image js-work-preview" data-work-preview="https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/images/work-2.jpg" style="background-image: url(https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/images/work-2.jpg);"></i>
</li>
<!-- //WORK ITEM PREVIEW -->
<!-- WORK ITEM PREVIEW -->
<li class="c-work-preview__item">
<i class="c-work-preview__image js-work-preview" data-work-preview="https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/images/work-3.jpg" style="background-image: url(https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/images/work-3.jpg);"></i>
</li>
<!-- //WORK ITEM PREVIEW -->
<!-- WORK ITEM PREVIEW -->
<li class="c-work-preview__item">
<i class="c-work-preview__image js-work-preview" data-work-preview="https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/images/work-4.jpg" style="background-image: url(https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/images/work-4.jpg);"></i>
</li>
<!-- //WORK ITEM PREVIEW -->
<!-- WORK ITEM PREVIEW -->
<li class="c-work-preview__item">
<i class="c-work-preview__image js-work-preview" data-work-preview="https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/images/work-5.jpg" style="background-image: url(https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/images/work-5.jpg);"></i>
</li>
<!-- //WORK ITEM PREVIEW -->
<!-- WORK ITEM PREVIEW -->
<li class="c-work-preview__item">
<i class="c-work-preview__image js-work-preview" data-work-preview="https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/images/work-6.jpg" style="background-image: url(https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/images/work-6.jpg);"></i>
</li>
<!-- //WORK ITEM PREVIEW -->
<!-- WORK ITEM PREVIEW -->
<li class="c-work-preview__item">
<i class="c-work-preview__image js-work-preview" data-work-preview="https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/images/work-7.jpg" style="background-image: url(https://deghq.com/wordpress/bornfight/wp-content/themes/bf/static/images/work-7.jpg);"></i>
</li>
<!-- //WORK ITEM PREVIEW -->
</ul>
</div>
</div>
CSS Code
@import url("https://fonts.googleapis.com/css?family=Raleway");
body {
font-family: 'Raleway', sans-serif;
line-height: 1em;
background-color: #0d0d0d;
color: #ffffff;
overflow: hidden;
}
.u-b6 {
margin: 0;
font-size: 10px;
}
.u-b4 {
margin: 0;
font-size: 14px;
}
.u-a6 {
margin: 0;
margin-bottom: 0.6em;
font-size: 36px;
}
.u-a7 {
margin: 0;
font-size: 64px;
padding: 60px 60px 0 60px;
}
.c-work {
width: 100%;
padding: 60px;
height: 80vh;
display: flex;
align-items: center;
overflow: hidden;
}
.c-work__list {
position: relative;
z-index: 2;
}
.c-work__item {
display: block;
}
.c-work-item {
position: relative;
display: inline-block;
cursor: pointer;
padding: 15px 0;
}
.c-work-item__number {
position: absolute;
display: inline-block;
right: 100%;
top: 25px;
margin-right: 25px;
pointer-events: none;
transition: all 0.2s 0.1s cubic-bezier(0.25, 0.46, 0.45, 0.94);
will-change: transform, opacity;
}
.c-work-item__title {
transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
will-change: transform;
}
.c-work-item__category {
display: inline-block;
transition: all 0.2s 0.1s cubic-bezier(0.25, 0.46, 0.45, 0.94);
will-change: transform;
}
.c-work-item__category i {
font-style: normal;
display: inline-block;
margin-right: 8px;
}
.c-work-item:hover .c-work-item__title {
-webkit-transform: translateX(10px);
transform: translateX(10px);
}
.c-work-item:hover .c-work-item__number {
opacity: 0;
-webkit-transform: translateX(20px);
transform: translateX(20px);
}
.c-work-item:hover .c-work-item__category {
-webkit-transform: translateX(10px);
transform: translateX(10px);
}
.c-work-preview {
position: fixed;
width: 100%;
height: 100vh;
top: 0;
right: 0;
padding-right: 60px;
pointer-events: none;
z-index: 1;
}
.c-work-preview__canvas {
display: block;
position: absolute;
top: 0;
right: 60px;
width: 41.6666666667%;
height: 100%;
}
.c-work-preview__canvas .canvas {
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
width: 100%;
left: 0;
height: 0;
padding-bottom: 56.25%;
overflow: hidden;
background-size: 0;
}
.c-work-preview__canvas canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.c-work-preview__list {
display: block;
position: absolute;
top: 0;
right: 60px;
width: 41.6666666667%;
height: 100%;
}
.c-work-preview__item {
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
width: 100%;
left: 0;
height: 0;
padding-bottom: 56.25%;
overflow: hidden;
}
.c-work-preview__image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
opacity: 0;
visibility: hidden;
}
JavaScript
var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}var WorkList = function () {
function WorkList(options) {_classCallCheck(this, WorkList);
var _defaults = {
workItem: '.js-work-item',
workItemPreviewList: '.js-work-preview-list',
workItemImg: '.js-work-preview',
//
activeItemClass: 'is-active',
//
workCanvas: '.js-work-preview-canvas' };
this.defaults = Object.assign({}, _defaults, options);
if (this.getWorkItem().length > 0) {
this.init();
this.workItemHover(this.getWorkItem());
this.workHover(this.getWorkItemPreviewList());
this.initWorkCanvas();
}
}
// region Getters
, ''));
// CREATE FILTER
var filter = new PIXI.filters.DisplacementFilter(displacementMap);
displacementMap.name = 'displacementMap';
displacementMap.anchor.set(0.5);
displacementMap.scale.set(1);
displacementMap.position.set(canvasWidth / 2, canvasHeight / 2);
app.stage.filterArea = app.screen;
app.stage.filters = [filter];
app.stage.addChild(displacementMap);
// PIXI SPRITE ARRAY
var _iteratorNormalCompletion = true;var _didIteratorError = false;var _iteratorError = undefined;try {for (var _iterator = this.getWorkItemImg()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {if (window.CP.shouldStopExecution(0)) break;var spriteImage = _step.value;
//const texture = new PIXI.Texture.fromImage($(spriteImage).data('work-preview'));
var texture = new PIXI.Texture.fromImage($(spriteImage).css('background-image').replace(/.*\s?url\([\'\"]?/, '').replace(/[\'\"]?\).*/, ''));
var image = new PIXI.Sprite(texture);
image.name = 'workPreview';
image.alpha = 0;
image.width = canvasWidth;
image.height = canvasHeight;
this.slidesContainer.addChild(image);
}
// DISPLACE TIMELINE
window.CP.exitedLoop(0);} catch (err) {_didIteratorError = true;_iteratorError = err;} finally {try {if (!_iteratorNormalCompletion && _iterator.return) {_iterator.return();}} finally {if (_didIteratorError) {throw _iteratorError;}}}this.displaceTl = new TimelineMax({
paused: true });
this.displaceTl.add('start').
fromTo(this.getCanvasEl(), 0.4, {
autoAlpha: 0 },
{
autoAlpha: 1,
ease: Power4.easeOut },
"start").
fromTo(this.getCanvasEl(), 0.8, {
scale: 1.25 },
{
scale: 1,
ease: Power4.easeOut },
"start").
fromTo(
filter.scale, 1.6, {
x: 25,
y: 75 },
{
x: 0,
y: 0,
ease: Power4.easeOut,
onComplete: function onComplete() {
} },
"start");
return [this.slidesContainer, this.displaceTl];
} }, { key: 'workHoverEnter', value: function workHoverEnter(
layerId) {var _this2 = this;
// SET ALPHA OF HOVERED CASE PREVIEW
TweenMax.to(this.slidesContainer.children[layerId], 0.4, {
alpha: 1,
ease: Power3.easeOut,
onStart: function onStart() {
_this2.displaceTl.progress(0);
_this2.displaceTl.play();
} });
} }, { key: 'workHoverLeave', value: function workHoverLeave()
{
TweenMax.to(this.slidesContainer.children, 0.4, {
alpha: 0,
ease: Power3.easeOut });
} }]);return WorkList;}();
new WorkList();
Preview
Leave a Reply