Home / Frontend Codes and Demos / CSS Code Demos / Morph images on hover Menu Portfolio with pixi.js
Morph images on hover Menu Portfolio with pixi.js

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.

Morph images on hover Menu Portfolio with pixi.js

Morph images on hover Menu Portfolio with pixi.js

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.

Demo Download

Author Karlo Videk
Hits
Created JUNE 29, 2018
License Open
Compatible browsers Chrome, Firefox, Safari
{loadmodule mod_custom,Article Adsense Ads}

<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      /**      *      * @returns {*|jQuery|HTMLElement}      */_createClass(WorkList, [{ key: 'getWorkItem', value: function getWorkItem()         {             return $(this.defaults.workItem);         } }, { key: 'getWorkItemImg', value: function getWorkItemImg()          {             return $(this.defaults.workItemImg);         } }, { key: 'getWorkItemPreviewList', value: function getWorkItemPreviewList()          {             return $(this.defaults.workItemPreviewList);         } }, { key: 'getWorkCanvas', value: function getWorkCanvas()          {             return $(this.defaults.workCanvas);         } }, { key: 'getCanvasEl', value: function getCanvasEl()          {             return $(this.defaults.workCanvas).find('canvas');         }          // endregion     }, { key: 'init', value: function init()         {             console.log('WorkList init()');         }          /**            *            * @param workItem            */ }, { key: 'workItemHover', value: function workItemHover(         workItem) {var _this = this;             workItem.on('mouseenter', function (e) {                 e.preventDefault();                  var workItemId = $(e.currentTarget).data('work-preview-id');                  _this.workHoverEnter(workItemId);             });              workItem.on('mouseleave', function () {                 _this.workHoverLeave();             });         }          /**            *            * @param workContainer            */ }, { key: 'workHover', value: function workHover(         workContainer) {             $(document).on('mousemove', function (ev) {                 var decimalX = ev.clientX / window.innerWidth - 0.5;                 var decimalY = ev.clientY / window.innerHeight - 0.5;                  TweenMax.to(workContainer, 0.4, {                     x: 180 * decimalX,                     y: 90 * decimalY,                     ease: Power3.easeOut });              });              // SETTINGS             var workItem = $(this.defaults.workItem);             var hoverDuration = 0.4;             var opacityLevel = 0.3;               // CONTEXT SHIFTING             // mouseenter             $(document).on('mouseenter', this.defaults.workItem, function (ev) {                 ev.preventDefault();                  var notItem = workItem.not(ev.currentTarget);                  TweenMax.to(ev.currentTarget, hoverDuration, {                     opacity: 1,                     ease: Power3.easeOut });                   TweenMax.to(notItem, hoverDuration, {                     opacity: opacityLevel,                     x: 0,                     ease: Power3.easeOut });              });              // mouseleave             $(document).on('mouseleave', this.defaults.workItem, function (ev) {                 ev.preventDefault();                  var notItem = workItem.not(ev.currentTarget);                  TweenMax.to([ev.currentTarget, notItem], hoverDuration, {                     opacity: 1,                     ease: Power3.easeOut });              });         } }, { key: 'initWorkCanvas', value: function initWorkCanvas()          {             // CANVAS DIMENSIONS             var canvasWidth = this.getWorkItemImg().innerWidth();             var canvasHeight = this.getWorkItemImg().innerHeight();              // CREATE PIXI APPLICATION             var app = new PIXI.Application(             canvasWidth,             canvasHeight, {                 transparent: true });                // APPEND CANVAS             this.getWorkCanvas().append(app.view);              // CREATE SLIDES CONTAINER             this.slidesContainer = new PIXI.Container();             app.stage.addChild(this.slidesContainer);              // CREATE DISPLACEMENT MAP             //const displacementMap = PIXI.Sprite.fromImage(this.getWorkCanvas().data('displacement-map'));              var displacementMap = PIXI.Sprite.fromImage(this.getWorkCanvas().css('background-image').replace(/.*\s?url\([\'\"]?/, '').replace(/[\'\"]?\).*/, ''));              // 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

Morph images on hover Menu Portfolio with pixi.js preview

About CV

I'm frontend developer

Check Also

Naturalized Checkbox Toggle Switches

This demo is a response to a post by Marcus Connor addressing confusion with checkbox …