[JS] headroom.min.js

更新 2020年5月1日 发布 2018年7月12日  WP & Websites
/*!
 * headroom.js v0.9.4 - Give your page some headroom. Hide your header until you need it
 * Copyright (c) 2017 Nick Williams - http://wicky.nillia.ms/headroom.js
 * License: MIT
 */

! function (a, b) {
  "use strict";
  "function" == typeof define && define.amd ? define([], b) : "object" == typeof exports ? module.exports = b() : a.Headroom = b()
}(this, function () {
  "use strict";

  function a(a) {
    this.callback = a, this.ticking = !1
  }

  function b(a) {
    return a && "undefined" != typeof window && (a === window || a.nodeType)
  }

  function c(a) {
    if (arguments.length <= 0) throw new Error("Missing arguments in extend function");
    var d, e, f = a || {};
    for (e = 1; e < arguments.length; e++) {
      var g = arguments[e] || {};
      for (d in g) "object" != typeof f[d] || b(f[d]) ? f[d] = f[d] || g[d] : f[d] = c(f[d], g[d])
    }
    return f
  }

  function d(a) {
    return a === Object(a) ? a : {
      down: a,
      up: a
    }
  }

  function e(a, b) {
    b = c(b, e.options), this.lastKnownScrollY = 0, this.elem = a, this.tolerance = d(b.tolerance), this.classes = b.classes, this.offset = b.offset, this.scroller = b.scroller, this.initialised = !1, this.onPin = b.onPin, this.onUnpin = b.onUnpin, this.onTop = b.onTop, this.onNotTop = b.onNotTop, this.onBottom = b.onBottom, this.onNotBottom = b.onNotBottom
  }
  var f = {
    bind: !! function () {}.bind,
    classList: "classList" in document.documentElement,
    rAF: !!(window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame)
  };
  return window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame, a.prototype = {
    constructor: a,
    update: function () {
      this.callback && this.callback(), this.ticking = !1
    },
    requestTick: function () {
      this.ticking || (requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this))), this.ticking = !0)
    },
    handleEvent: function () {
      this.requestTick()
    }
  }, e.prototype = {
    constructor: e,
    init: function () {
      if (e.cutsTheMustard) return this.debouncer = new a(this.update.bind(this)), this.elem.classList.add(this.classes.initial), setTimeout(this.attachEvent.bind(this), 100), this
    },
    destroy: function () {
      var a = this.classes;
      this.initialised = !1;
      for (var b in a) a.hasOwnProperty(b) && this.elem.classList.remove(a[b]);
      this.scroller.removeEventListener("scroll", this.debouncer, !1)
    },
    attachEvent: function () {
      this.initialised || (this.lastKnownScrollY = this.getScrollY(), this.initialised = !0, this.scroller.addEventListener("scroll", this.debouncer, !1), this.debouncer.handleEvent())
    },
    unpin: function () {
      var a = this.elem.classList,
        b = this.classes;
      !a.contains(b.pinned) && a.contains(b.unpinned) || (a.add(b.unpinned), a.remove(b.pinned), this.onUnpin && this.onUnpin.call(this))
    },
    pin: function () {
      var a = this.elem.classList,
        b = this.classes;
      a.contains(b.unpinned) && (a.remove(b.unpinned), a.add(b.pinned), this.onPin && this.onPin.call(this))
    },
    top: function () {
      var a = this.elem.classList,
        b = this.classes;
      a.contains(b.top) || (a.add(b.top), a.remove(b.notTop), a.remove(b.pinned), this.onTop && this.onTop.call(this))
    },
    notTop: function () {
      var a = this.elem.classList,
        b = this.classes;
      a.contains(b.notTop) || (a.add(b.notTop), a.remove(b.top), this.onNotTop && this.onNotTop.call(this))
    },
    bottom: function () {
      var a = this.elem.classList,
        b = this.classes;
      a.contains(b.bottom) || (a.add(b.bottom), a.remove(b.notBottom), this.onBottom && this.onBottom.call(this))
    },
    notBottom: function () {
      var a = this.elem.classList,
        b = this.classes;
      a.contains(b.notBottom) || (a.add(b.notBottom), a.remove(b.bottom), this.onNotBottom && this.onNotBottom.call(this))
    },
    getScrollY: function () {
      return void 0 !== this.scroller.pageYOffset ? this.scroller.pageYOffset : void 0 !== this.scroller.scrollTop ? this.scroller.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop
    },
    getViewportHeight: function () {
      return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
    },
    getElementPhysicalHeight: function (a) {
      return Math.max(a.offsetHeight, a.clientHeight)
    },
    getScrollerPhysicalHeight: function () {
      return this.scroller === window || this.scroller === document.body ? this.getViewportHeight() : this.getElementPhysicalHeight(this.scroller)
    },
    getDocumentHeight: function () {
      var a = document.body,
        b = document.documentElement;
      return Math.max(a.scrollHeight, b.scrollHeight, a.offsetHeight, b.offsetHeight, a.clientHeight, b.clientHeight)
    },
    getElementHeight: function (a) {
      return Math.max(a.scrollHeight, a.offsetHeight, a.clientHeight)
    },
    getScrollerHeight: function () {
      return this.scroller === window || this.scroller === document.body ? this.getDocumentHeight() : this.getElementHeight(this.scroller)
    },
    isOutOfBounds: function (a) {
      var b = a < 0,
        c = a + this.getScrollerPhysicalHeight() > this.getScrollerHeight();
      return b || c
    },
    toleranceExceeded: function (a, b) {
      return Math.abs(a - this.lastKnownScrollY) >= this.tolerance[b]
    },
    shouldUnpin: function (a, b) {
      var c = a > this.lastKnownScrollY,
        d = a >= this.offset;
      return c && d && b
    },
    shouldPin: function (a, b) {
      var c = a < this.lastKnownScrollY,
        d = a <= this.offset;
      return c && b || d
    },
    update: function () {
      var a = this.getScrollY(),
        b = a > this.lastKnownScrollY ? "down" : "up",
        c = this.toleranceExceeded(a, b);
      this.isOutOfBounds(a) || (a <= this.offset ? this.top() : this.notTop(), a + this.getViewportHeight() >= this.getScrollerHeight() ? this.bottom() : this.notBottom(), this.shouldUnpin(a, c) ? this.unpin() : this.shouldPin(a, c) && this.pin(), this.lastKnownScrollY = a)
    }
  }, e.options = {
    tolerance: {
      up: 0,
      down: 0
    },
    offset: 0,
    scroller: window,
    classes: {
      pinned: "headroom--pinned",
      unpinned: "headroom--unpinned",
      top: "headroom--top",
      notTop: "headroom--not-top",
      bottom: "headroom--bottom",
      notBottom: "headroom--not-bottom",
      initial: "headroom"
    }
  }, e.cutsTheMustard = "undefined" != typeof f && f.rAF && f.bind && f.classList, e
});

footer.php

<script type="text/javascript" src="<?php bloginfo('template_url') ?>/js/headroom.min.js"></script>
<script type="text/javascript">
// grab an element
var myElement = document.querySelector("#header");
// construct an instance of Headroom, passing the element
var headroom  = new Headroom(myElement);
// initialise
headroom.init(); 
</script>

CSS

.headroom {
  transition: transform .25s ease-in-out;
  will-change: transform;
}
.headroom--top {
  position: relative;
  z-index: 10;
}
.headroom--pinned {
  transform: translateY(0%);
  position: fixed;
  width: 100%;
  background: white;
  z-index: 1000;
  top: 0;
}
.headroom--unpinned {
  transform: translateY(-100%);
}