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

AuthorKarlo Videk
CreatedJUNE 29, 2018
LicenseOpen
Compatible browsersChrome, Firefox, Safari
<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

Morph images on hover Menu Portfolio with pixi.js 1

W3TWEAKS

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *