update: perfect animation, compatibility issue

This commit is contained in:
Jeffrey Tse 2019-09-24 14:10:57 +08:00
parent 92840887d2
commit cda49e0301
10 changed files with 134 additions and 87 deletions

View file

@ -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'));

View file

@ -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 -%}

View file

@ -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>

View file

@ -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) {

View file

@ -15,8 +15,6 @@
} }
li { li {
border-bottom: 1px solid $background-color;
&:last-child { &:last-child {
border-bottom: none; border-bottom: none;
} }

View file

@ -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;
} }
} }

View file

@ -229,7 +229,7 @@ table {
/** /**
* Flex layout * Flex layout
*/ */
%flex-layout { %flex {
display: flex; display: flex;
} }

View file

@ -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
View 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);
})();
}
}