update: perfect animation, compatibility issue
This commit is contained in:
parent
92840887d2
commit
cda49e0301
10 changed files with 134 additions and 87 deletions
|
@ -7,30 +7,31 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var headerHeight = 0;
|
|
||||||
var header = document.querySelector('header');
|
var header = document.querySelector('header');
|
||||||
if (header) {
|
var scrollPos = getScrollPos();
|
||||||
headerHeight = header.offsetHeight;
|
var offsetY = element.offsetTop - (header.offsetTop + header.offsetHeight + 20);
|
||||||
}
|
|
||||||
var supportPageOffset = window.pageXOffset !== undefined;
|
|
||||||
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
|
|
||||||
|
|
||||||
var x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
|
if (offsetY == scrollPos.y) {
|
||||||
var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
|
|
||||||
|
|
||||||
var offsetY = element.offsetTop - headerHeight - 12;
|
|
||||||
if (y === offsetY) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.scrollTo(x, offsetY);
|
if (header.offsetTop == 0 && offsetY > scrollPos.y) {
|
||||||
|
offsetY += header.offsetHeight;
|
||||||
|
} else if (header.offsetTop < 0 && offsetY < scrollPos.y) {
|
||||||
|
offsetY -= header.offsetHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
smoothScrollTo(offsetY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first event occurred
|
// The first event occurred
|
||||||
if (window.location.hash) {
|
window.addEventListener('load', function(event) {
|
||||||
hashLocate(window.location.hash);
|
if (window.location.hash) {
|
||||||
}
|
hashLocate(window.location.hash);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// The first event occurred
|
||||||
window.addEventListener('click', function(event) {
|
window.addEventListener('click', function(event) {
|
||||||
if (event.target.matches('a')) {
|
if (event.target.matches('a')) {
|
||||||
hashLocate(event.target.getAttribute('href'));
|
hashLocate(event.target.getAttribute('href'));
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
{%- seo -%}
|
{%- seo -%}
|
||||||
<link rel="shortcut icon" href="{{ site.favicon }}">
|
<link rel="shortcut icon" href="{{ site.favicon }}">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||||
<link rel="stylesheet" href="{{ "/assets/main.css" | relative_url }}">
|
<link rel="stylesheet" href="{{ "/assets/css/main.css" | relative_url }}">
|
||||||
|
<script src="{{ "/assets/js/main.js" | relative_url }}"></script>
|
||||||
{%- feed_meta -%}
|
{%- feed_meta -%}
|
||||||
{%- if jekyll.environment == 'production' and site.google_analytics -%}
|
{%- if jekyll.environment == 'production' and site.google_analytics -%}
|
||||||
{%- include extensions/google-analytics.html -%}
|
{%- include extensions/google-analytics.html -%}
|
||||||
|
|
|
@ -12,48 +12,49 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var menu = document.querySelector(".post-menu .post-menu-content");
|
function generateContent() {
|
||||||
var headings = document.querySelector(".post-content").querySelectorAll("h2, h3, h4, h5, h6");
|
var menu = document.querySelector(".post-menu .post-menu-content");
|
||||||
|
var headings = document.querySelector(".post-content").querySelectorAll("h2, h3, h4, h5, h6");
|
||||||
|
|
||||||
// Generate post menu
|
// Generate post menu
|
||||||
var menuHTML = '';
|
var menuHTML = '';
|
||||||
headings.forEach(function (h) {
|
for (var i = 0; i < headings.length; i++) {
|
||||||
menuHTML += (
|
|
||||||
'<li class="h-' + h.tagName.toLowerCase() + '">'
|
|
||||||
+ '<a href="#h-' + h.getAttribute('id') + '">' + h.textContent + '</a></li>');
|
|
||||||
});
|
|
||||||
|
|
||||||
menu.innerHTML = '<ul>' + menuHTML + '</ul>';
|
|
||||||
|
|
||||||
// The anchor offsetHeight
|
|
||||||
var headerHeight = 0;
|
|
||||||
var header = document.querySelector('header');
|
|
||||||
if (header) {
|
|
||||||
offsetHeight = header.offsetHeight + 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Active the menu item
|
|
||||||
window.addEventListener('scroll', function (event) {
|
|
||||||
var lastActive = menu.querySelector('.active');
|
|
||||||
var changed = true;
|
|
||||||
for (var i = headings.length - 1; i >= 0; i--) {
|
|
||||||
var h = headings[i];
|
var h = headings[i];
|
||||||
var clientRect = h.getBoundingClientRect();
|
menuHTML += (
|
||||||
if (clientRect.top < offsetHeight) {
|
'<li class="h-' + h.tagName.toLowerCase() + '">'
|
||||||
var id = 'h-' + h.getAttribute('id');
|
+ '<a href="#h-' + h.getAttribute('id') + '">' + h.textContent + '</a></li>');
|
||||||
var curActive = menu.querySelector('a[href="#' + id + '"]');
|
}
|
||||||
if (curActive) {
|
|
||||||
curActive.classList.add('active');
|
menu.innerHTML = '<ul>' + menuHTML + '</ul>';
|
||||||
|
|
||||||
|
// The header element
|
||||||
|
var header = document.querySelector('header.site-header');
|
||||||
|
|
||||||
|
// Active the menu item
|
||||||
|
window.addEventListener('scroll', function (event) {
|
||||||
|
var lastActive = menu.querySelector('.active');
|
||||||
|
var changed = true;
|
||||||
|
for (var i = headings.length - 1; i >= 0; i--) {
|
||||||
|
var h = headings[i];
|
||||||
|
var clientRect = h.getBoundingClientRect();
|
||||||
|
var headerHeight = header.offsetTop + header.offsetHeight + 20;
|
||||||
|
if (clientRect.top <= headerHeight) {
|
||||||
|
var id = 'h-' + h.getAttribute('id');
|
||||||
|
var curActive = menu.querySelector('a[href="#' + id + '"]');
|
||||||
|
if (curActive) {
|
||||||
|
curActive.classList.add('active');
|
||||||
|
}
|
||||||
|
if (lastActive == curActive) {
|
||||||
|
changed = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (lastActive == curActive) {
|
|
||||||
changed = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
if (lastActive && changed) {
|
||||||
if (lastActive && changed) {
|
lastActive.classList.remove('active');
|
||||||
lastActive.classList.remove('active');
|
}
|
||||||
}
|
event.preventDefault();
|
||||||
event.preventDefault();
|
});
|
||||||
});
|
}
|
||||||
|
generateContent();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -62,21 +62,14 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var supportPageOffset = window.pageXOffset !== undefined;
|
var lastScrollY = getScrollPos().y;
|
||||||
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
|
var documentElement = document.documentElement;
|
||||||
|
|
||||||
function scrollY() {
|
|
||||||
return supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastScrollY = scrollY();
|
|
||||||
var dataset = document.documentElement.dataset;
|
|
||||||
|
|
||||||
function storeScrollData() {
|
function storeScrollData() {
|
||||||
var y = scrollY();
|
var y = getScrollPos().y;
|
||||||
|
|
||||||
{%- if banner and header_transparent -%}
|
{%- if banner and header_transparent -%}
|
||||||
dataset.headerTransparent = "";
|
documentElement.setAttribute("data-header-transparent", "");
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|
||||||
var scrollStatus = "";
|
var scrollStatus = "";
|
||||||
|
@ -91,7 +84,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
lastScrollY = y;
|
lastScrollY = y;
|
||||||
dataset.scrollStatus = scrollStatus;
|
documentElement.setAttribute("data-scroll-status", scrollStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('scroll', function(e) {
|
window.addEventListener('scroll', function(e) {
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
border-bottom: 1px solid $background-color;
|
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,15 +122,19 @@ body {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 110%;
|
top: 110%;
|
||||||
right: -10px;
|
right: -10px;
|
||||||
|
background-color: lighten($theme-color, 5%);
|
||||||
-webkit-transition: all 0.25s ease-in-out;
|
-webkit-transition: all 0.25s ease-in-out;
|
||||||
transition: all 0.25s ease-in-out;
|
transition: all 0.25s ease-in-out;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top: 0;
|
margin-top: 0;
|
||||||
z-index: 200;
|
z-index: 200;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding-top: 8px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
visibility: hidden;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
background: lighten($theme-color, 5%);
|
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -140,24 +144,14 @@ body {
|
||||||
img {
|
img {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
max-height: 24px;
|
max-height: 24px;
|
||||||
|
border: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
padding-top: 10px;
|
|
||||||
border-radius: 3px 3px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
padding-bottom: 10px;
|
|
||||||
border-radius: 0 0 3px 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@extend .ct-language-selected;
|
@extend .ct-language-selected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-unstyled {
|
.list-unstyled {
|
||||||
|
@ -169,7 +163,7 @@ body {
|
||||||
.ct-language {
|
.ct-language {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
background: #fefefe2b;
|
background-color: #fefefe2b;
|
||||||
padding: 3px 10px;
|
padding: 3px 10px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
|
||||||
|
@ -177,8 +171,9 @@ body {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
.ct-language-dropdown {
|
.ct-language-dropdown {
|
||||||
padding-top: 8px;
|
margin-top: 8px;
|
||||||
max-height: 10000px;
|
max-height: 10000px;
|
||||||
|
visibility: visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -229,7 +229,7 @@ table {
|
||||||
/**
|
/**
|
||||||
* Flex layout
|
* Flex layout
|
||||||
*/
|
*/
|
||||||
%flex-layout {
|
%flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,6 +200,7 @@ html {
|
||||||
*/
|
*/
|
||||||
.page-content {
|
.page-content {
|
||||||
@extend %flex-1; /* <-- Keep footer on the bottom */
|
@extend %flex-1; /* <-- Keep footer on the bottom */
|
||||||
|
-ms-flex: none; /* <-- Fix IE footer issue */
|
||||||
padding: $spacing-unit * 1.5 0;
|
padding: $spacing-unit * 1.5 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +379,7 @@ html {
|
||||||
* Layout and sidebar
|
* Layout and sidebar
|
||||||
*/
|
*/
|
||||||
.framework {
|
.framework {
|
||||||
@extend %flex-layout;
|
@extend %flex;
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
@extend %flex-1;
|
@extend %flex-1;
|
||||||
|
|
57
assets/js/main.js
Normal file
57
assets/js/main.js
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
// Fix DOM matches function
|
||||||
|
if (!Element.prototype.matches) {
|
||||||
|
Element.prototype.matches =
|
||||||
|
Element.prototype.matchesSelector ||
|
||||||
|
Element.prototype.mozMatchesSelector ||
|
||||||
|
Element.prototype.msMatchesSelector ||
|
||||||
|
Element.prototype.oMatchesSelector ||
|
||||||
|
Element.prototype.webkitMatchesSelector ||
|
||||||
|
function(s) {
|
||||||
|
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
|
||||||
|
i = matches.length;
|
||||||
|
while (--i >= 0 && matches.item(i) !== this) {}
|
||||||
|
return i > -1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Scroll position
|
||||||
|
function getScrollPos() {
|
||||||
|
var supportPageOffset = window.pageXOffset !== undefined;
|
||||||
|
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
|
||||||
|
|
||||||
|
var x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
|
||||||
|
var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
|
||||||
|
|
||||||
|
return { x: x, y: y };
|
||||||
|
}
|
||||||
|
|
||||||
|
var _scrollTimer = [];
|
||||||
|
|
||||||
|
// Smooth scroll
|
||||||
|
function smoothScrollTo(y, time) {
|
||||||
|
time = time == undefined ? 500 : time;
|
||||||
|
|
||||||
|
var scrollPos = getScrollPos();
|
||||||
|
var count = 60;
|
||||||
|
var length = (y - scrollPos.y);
|
||||||
|
|
||||||
|
function easeInOut(k) {
|
||||||
|
return .5 * (Math.sin((k - .5) * Math.PI) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = _scrollTimer.length - 1; i >= 0; i--) {
|
||||||
|
clearTimeout(_scrollTimer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i <= count; i++) {
|
||||||
|
(function() {
|
||||||
|
var cur = i;
|
||||||
|
_scrollTimer[cur] = setTimeout(function() {
|
||||||
|
window.scrollTo(
|
||||||
|
scrollPos.x,
|
||||||
|
scrollPos.y + length * easeInOut(cur/count)
|
||||||
|
);
|
||||||
|
}, (time / count) * cur);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue