Sử dụng thư viện jquery.hoverdir.js để làm hiệu ứng hover tuyệt đẹp (ok)

https://github.com/webmandesign/jquery.hoverdir

Một ví dụ thực hành :)

C:\Users\Administrator\OneDrive\Desktop\web\test.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <script src="js/jquery.min.js"></script>
  <!-- <script src="js/modernizr.js"></script> -->
  <script type="text/javascript" src="js/jquery.hoverdir.js"></script>
  <title>Document</title>
  <style type="text/css">
  .da-thumbs {
    list-style: none;
    width: 984px;
    height: 600px;
    position: relative;
    margin: 20px auto;
    padding: 0;
  }
  .da-thumbs li {
    float: left;
    margin: 0.4%;
    background: #EFEFEF;
    padding: 8px;
    position: relative;
    box-shadow: 0 1px 3px rgb(231 231 231 / 43%);
    width: 32.4%;
  }
  .da-thumbs li a {
    overflow: hidden;
  }
  .da-thumbs li a,
  .da-thumbs li a img {
    display: block;
    position: relative;
  }
  .da-thumbs li a div {
    position: absolute;
    background: #333;
    background: rgba(75, 75, 75, 0.7);
    width: 100%;
    height: 100%;
  }
  .da-thumbs li a div h5 {
    color: #FFF;
    font-size: 1.5em;
    margin: 3.5em 0 0 0;
    font-family: 'Audiowide-Regular';
    text-align: center;
  }
  .da-thumbs li a div span {
    display: block;
    padding: 10px 0;
    margin: 11px 20px 20px 20px;
    font-weight: normal;
    text-transform: capitalize;
    color: rgba(255, 255, 255, 0.9);
    text-align: center;
    font-size: 14px;
    font-family: 'Raleway-Regular';
  }
  </style>
</head>
<body>
  <section>
    <ul id="da-thumbs" class="da-thumbs">
      <li>
        <a href="images/g-1.jpg" rel="title" class="b-link-stripe b-animate-go  thickbox">
          <img src="images/g-1.jpg" alt="" />
          <div>
            <h5>Coffee</h5>
            <span>non suscipit leo fringilla non suscipit leo fringilla molestie</span>
          </div>
        </a>
      </li>
      <li>
        <a href="images/g-2.jpg" rel="title" class="b-link-stripe b-animate-go  thickbox">
          <img src="images/g-2.jpg" alt="" />
          <div>
            <h5>Coffee</h5>
            <span>non suscipit leo fringilla non suscipit leo fringilla molestie</span>
          </div>
        </a>
      </li>
      <li>
        <a href="images/g-3.jpg" rel="title" class="b-link-stripe b-animate-go  thickbox">
          <img src="images/g-3.jpg" alt="" />
          <div>
            <h5>Coffee</h5>
            <span>non suscipit leo fringilla non suscipit leo fringilla molestie</span>
          </div>
        </a>
      </li>
      <li>
        <a href="images/g-4.jpg" rel="title" class="b-link-stripe b-animate-go  thickbox">
          <img src="images/g-4.jpg" alt="" />
          <div>
            <h5>Coffee</h5>
            <span>non suscipit leo fringilla non suscipit leo fringilla molestie</span>
          </div>
        </a>
      </li>
      <li>
        <a href="images/g-5.jpg" rel="title" class="b-link-stripe b-animate-go  thickbox">
          <img src="images/g-5.jpg" alt="" />
          <div>
            <h5>Coffee</h5>
            <span>non suscipit leo fringilla non suscipit leo fringilla molestie</span>
          </div>
        </a>
      </li>
      <li>
        <a href="images/g-6.jpg" rel="title" class="b-link-stripe b-animate-go  thickbox">
          <img src="images/g-6.jpg" alt="" />
          <div>
            <h5>Coffee</h5>
            <span>non suscipit leo fringilla non suscipit leo fringilla molestie</span>
          </div>
        </a>
      </li>
      <li>
        <a href="images/g-7.jpg" rel="title" class="b-link-stripe b-animate-go  thickbox">
          <img src="images/g-7.jpg" alt="" />
          <div>
            <h5>Coffee</h5>
            <span>non suscipit leo fringilla non suscipit leo fringilla molestie</span>
          </div>
        </a>
      </li>
      <li>
        <a href="images/g-8.jpg" rel="title" class="b-link-stripe b-animate-go  thickbox">
          <img src="images/g-8.jpg" alt="" />
          <div>
            <h5>Coffee</h5>
            <span>non suscipit leo fringilla non suscipit leo fringilla molestie</span>
          </div>
        </a>
      </li>
      <li>
        <a href="images/g-9.jpg" rel="title" class="b-link-stripe b-animate-go  thickbox">
          <img src="images/g-9.jpg" alt="" />
          <div>
            <h5>Coffee</h5>
            <span>non suscipit leo fringilla non suscipit leo fringilla molestie</span>
          </div>
        </a>
      </li>
      <div class="clearfix"> </div>
    </ul>
  </section>
  <script type="text/javascript">
  $(function() {
    $(' #da-thumbs > li ').each(function() { $(this).hoverdir(); });
  });
  </script>
</body>
</html>

<div class="da-thumbs">
  
  <div>
    <a href="#">
      <img src="https://cdn.shopify.com/s/files/1/1047/8278/products/electric-toy-car-bmw-x5_large.png?v=1449651980" />
      <div>hover image 1</div>
    </a>
  </div>
  
  <div>
    <a href="#">
      <img src="https://cdn.shopify.com/s/files/1/1047/8278/products/electric-toy-car-bmw-x5_large.png?v=1449651980" />
      <div>hover image 2</div>
    </a>
  </div>
  
  <div>
    <a href="#">
      <img src="https://cdn.shopify.com/s/files/1/1047/8278/products/electric-toy-car-bmw-x5_large.png?v=1449651980" />
      <div>hover image 3</div>
    </a>
  </div>

  <div>
    <a href="#">
      <img src="https://cdn.shopify.com/s/files/1/1047/8278/products/electric-toy-car-bmw-x5_large.png?v=1449651980" />
      <div>hover image 4</div>
    </a>
  </div>
  
  <div>
    <a href="#">
      <img src="https://cdn.shopify.com/s/files/1/1047/8278/products/electric-toy-car-bmw-x5_large.png?v=1449651980" />
      <div>hover image 5</div>
    </a>
  </div>
  
  <div>
    <a href="#">
      <img src="https://cdn.shopify.com/s/files/1/1047/8278/products/electric-toy-car-bmw-x5_large.png?v=1449651980" />
      <div>hover image 6</div>
    </a>
  </div>
  
</div>
.da-thumbs {
	position: relative;
  width: 800px;
	margin: 20px auto;
	padding: 0;
}
.da-thumbs > div {
  float: left;
  background-color: #eee;
  margin: 5px;
  padding: 3px;
	position: relative;
}
.da-thumbs > div a,
.da-thumbs > div a img {
	display: block;
	position: relative;
}
.da-thumbs > div a {
	overflow: hidden;
}
.da-thumbs > div a img {
	height: 200px;
}
.da-thumbs > div a div {
	position: absolute;
	width: 100%;
	height: 100%;
	background: rgba(60, 60, 60, 0.7);
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center
}
$(function () {
  $('.da-thumbs > div').hoverdir();
});

// external js file

(function (factory) {
  'use strict';
  if (typeof define === 'function' && define.amd) {
    define(['jquery'], factory);
  } else if (typeof exports !== 'undefined') {
    module.exports = factory(require('jquery'));
  } else {
    factory(jQuery);
  }
})(function ($) {
  'use strict';

  function Hoverdir(element, options) {
    this.$el = $(element);
    // set options
    this.options = $.extend(true, {}, this.defaults, options);
    // initialize visibility to false for show and hide method
    this.isVisible = false;
    // get the hover for this element
    this.$hoverElem = this.$el.find(this.options.hoverElem);
    // transition properties
    this.transitionProp = 'all ' + this.options.speed + 'ms ' + this.options.easing;
    // support for CSS transitions
    this.support = this._supportsTransitions();
    // load the events
    this._loadEvents();
  }

  Hoverdir.prototype = {
    defaults: {
      speed: 300,
      easing: 'ease',
      hoverDelay: 0,
      inverse: false,
      hoverElem: 'div'
    },
    constructor: Hoverdir,
    /**
         * Detect if CSS transitions are supported
         *
         * @return {Boolean}
         */
    _supportsTransitions: function () {
      if (typeof Modernizr !== 'undefined') {
        return Modernizr.csstransitions;
      } else {
        var b = document.body || document.documentElement,
            s = b.style,
            p = 'transition';

        if (typeof s[p] === 'string') {
          return true;
        }

        // Tests for vendor specific prop
        var v = ['Moz', 'webkit', 'Webkit', 'Khtml', 'O', 'ms'];
        p = p.charAt(0).toUpperCase() + p.substr(1);

        for (var i = 0; i < v.length; i++) {
          if (typeof s[v[i] + p] === 'string') {
            return true;
          }
        }

        return false;
      }
    },
    /**
         * Bind the events to the element
         */
    _loadEvents: function () {
      this.$el.on('mouseenter.hoverdir mouseleave.hoverdir', $.proxy(function (event) {
        this.direction = this._getDir({x: event.pageX, y: event.pageY});

        if (event.type === 'mouseenter') {
          this._showHover();
        }
        else {
          this._hideHover();
        }
      }, this));
    },
    /**
         * Show the hover of the element
         */
    _showHover: function () {
      var styleCSS = this._getStyle(this.direction);

      if (this.support) {
        this.$hoverElem.css('transition', '');
      }

      this.$hoverElem.hide().css(styleCSS.from);
      clearTimeout(this.tmhover);

      this.tmhover = setTimeout($.proxy(function () {
        this.$hoverElem.show(0, $.proxy(function () {
          if (this.support) {
            this.$hoverElem.css('transition', this.transitionProp);
          }
          this._applyAnimation(styleCSS.to);

        }, this));
      }, this), this.options.hoverDelay);

      this.isVisible = true;
    },
    /**
         * Hide the hover to the element
         */
    _hideHover: function () {
      var styleCSS = this._getStyle(this.direction);
      if (this.support) {
        this.$hoverElem.css('transition', this.transitionProp);
      }
      clearTimeout(this.tmhover);
      this._applyAnimation(styleCSS.from);
      this.isVisible = false;
    },
    /**
         * get the direction when the event is triggered
         * credits : http://stackoverflow.com/a/3647634
         *
         * @param {Object} coordinates
         * @returns {Interger}
         */
    _getDir: function (coordinates) {
      // the width and height of the current div
      var w = this.$el.width(),
          h = this.$el.height(),
          // calculate the x and y to get an angle to the center of the div from that x and y.
          // gets the x value relative to the center of the DIV and "normalize" it
          x = (coordinates.x - this.$el.offset().left - (w / 2)) * (w > h ? (h / w) : 1),
          y = (coordinates.y - this.$el.offset().top - (h / 2)) * (h > w ? (w / h) : 1),
          // the angle and the direction from where the mouse came in/went out clockwise (TRBL=0123);
          // first calculate the angle of the point,
          // add 180 deg to get rid of the negative values
          // divide by 90 to get the quadrant
          // add 3 and do a modulo by 4 to shift the quadrants to a proper clockwise TRBL (top/right/bottom/left) **/
          direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4;
      return direction;
    },
    /**
         * get the style when the event is triggered
         *
         * @param {(Interger|String)} direction
         * @returns {Object}
         */
    _getStyle: function (direction) {
      var fromStyle, toStyle,
          slideFromTop = {'left': '0', 'top': '-100%'},
          slideFromBottom = {'left': '0', 'top': '100%'},
          slideFromLeft = {'left': '-100%', 'top': '0'},
          slideFromRight = {'left': '100%', 'top': '0'},
          slideTop = {'top': '0'},
          slideLeft = {'left': '0'};

      switch (direction) {
        case 0:
        case 'top':
          // from top
          fromStyle = !this.options.inverse ? slideFromTop : slideFromBottom;
          toStyle = slideTop;
          break;
        case 1:
        case 'right':
          // from right
          fromStyle = !this.options.inverse ? slideFromRight : slideFromLeft;
          toStyle = slideLeft;
          break;
        case 2:
        case 'bottom':
          // from bottom
          fromStyle = !this.options.inverse ? slideFromBottom : slideFromTop;
          toStyle = slideTop;
          break;
        case 3:
        case 'left':
          // from left
          fromStyle = !this.options.inverse ? slideFromLeft : slideFromRight;
          toStyle = slideLeft;
          break;
      }

      return {from: fromStyle, to: toStyle};
    },
    /**
         * Apply a transition or fallback to jquery animate based on Modernizr.csstransitions support
         *
         * @param {Object} styleCSS
         */
    _applyAnimation: function (styleCSS) {
      $.fn.applyStyle = this.support ? $.fn.css : $.fn.animate;
      this.$hoverElem.stop().applyStyle(styleCSS, $.extend(true, [], {duration: this.options.speed}));
    },
    /**
         * Show $hoverElem from the direction in argument
         *
         * @param {String} [direction=top] direction
         */
    show: function (direction) {
      this.$el.off('mouseenter.hoverdir mouseleave.hoverdir');
      if (!this.isVisible) {
        this.direction = direction || 'top';
        this._showHover();
      }
    },
    /**
         * Hide $hoverElem from the direction in argument
         *
         * @param {String} [direction=bottom] direction
         */
    hide: function (direction) {
      this.rebuild();
      if (this.isVisible) {
        this.direction = direction || 'bottom';
        this._hideHover();
      }
    },
    setOptions: function (options) {
      this.options = $.extend(true, {}, this.defaults, this.options, options);
    },
    /**
         * Unbinds the plugin.
         */
    destroy: function () {
      this.$el.off('mouseenter.hoverdir mouseleave.hoverdir');
      this.$el.data('hoverdir', null);
    },
    /**
         * Bind the plugin.
         */
    rebuild: function (options) {
      if (typeof options === 'object') {
        this.setOptions(options);
      }
      this._loadEvents();
    }
  };

  $.fn.hoverdir = function (option, parameter) {
    return this.each(function () {
      var data = $(this).data('hoverdir');
      var options = typeof option === 'object' && option;

      // Initialize hoverdir.
      if (!data) {
        data = new Hoverdir(this, options);
        $(this).data('hoverdir', data);
      }

      // Call hoverdir method.
      if (typeof option === 'string') {
        data[option](parameter);

        if (option === 'destroy') {
          $(this).data('hoverdir', false);
        }
      }
    });
  };

  $.fn.hoverdir.Constructor = Hoverdir;
});

Last updated