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;
}
var headerHeight = 0;
var header = document.querySelector('header');
if (header) {
headerHeight = header.offsetHeight;
}
var supportPageOffset = window.pageXOffset !== undefined;
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
var scrollPos = getScrollPos();
var offsetY = element.offsetTop - (header.offsetTop + header.offsetHeight + 20);
var x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
var y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
var offsetY = element.offsetTop - headerHeight - 12;
if (y === offsetY) {
if (offsetY == scrollPos.y) {
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
if (window.location.hash) {
hashLocate(window.location.hash);
}
window.addEventListener('load', function(event) {
if (window.location.hash) {
hashLocate(window.location.hash);
}
});
// The first event occurred
window.addEventListener('click', function(event) {
if (event.target.matches('a')) {
hashLocate(event.target.getAttribute('href'));

View file

@ -6,7 +6,8 @@
{%- seo -%}
<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="{{ "/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 -%}
{%- if jekyll.environment == 'production' and site.google_analytics -%}
{%- include extensions/google-analytics.html -%}

View file

@ -12,48 +12,49 @@
</div>
<script>
var menu = document.querySelector(".post-menu .post-menu-content");
var headings = document.querySelector(".post-content").querySelectorAll("h2, h3, h4, h5, h6");
function generateContent() {
var menu = document.querySelector(".post-menu .post-menu-content");
var headings = document.querySelector(".post-content").querySelectorAll("h2, h3, h4, h5, h6");
// Generate post menu
var menuHTML = '';
headings.forEach(function (h) {
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--) {
// Generate post menu
var menuHTML = '';
for (var i = 0; i < headings.length; i++) {
var h = headings[i];
var clientRect = h.getBoundingClientRect();
if (clientRect.top < offsetHeight) {
var id = 'h-' + h.getAttribute('id');
var curActive = menu.querySelector('a[href="#' + id + '"]');
if (curActive) {
curActive.classList.add('active');
menuHTML += (
'<li class="h-' + h.tagName.toLowerCase() + '">'
+ '<a href="#h-' + h.getAttribute('id') + '">' + h.textContent + '</a></li>');
}
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) {
lastActive.classList.remove('active');
}
event.preventDefault();
});
if (lastActive && changed) {
lastActive.classList.remove('active');
}
event.preventDefault();
});
}
generateContent();
</script>

View file

@ -62,21 +62,14 @@
<script>
(function() {
var supportPageOffset = window.pageXOffset !== undefined;
var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat");
function scrollY() {
return supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
}
var lastScrollY = scrollY();
var dataset = document.documentElement.dataset;
var lastScrollY = getScrollPos().y;
var documentElement = document.documentElement;
function storeScrollData() {
var y = scrollY();
var y = getScrollPos().y;
{%- if banner and header_transparent -%}
dataset.headerTransparent = "";
documentElement.setAttribute("data-header-transparent", "");
{%- endif -%}
var scrollStatus = "";
@ -91,7 +84,7 @@
}
lastScrollY = y;
dataset.scrollStatus = scrollStatus;
documentElement.setAttribute("data-scroll-status", scrollStatus);
}
window.addEventListener('scroll', function(e) {

View file

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

View file

@ -122,15 +122,19 @@ body {
position: absolute;
top: 110%;
right: -10px;
background-color: lighten($theme-color, 5%);
-webkit-transition: all 0.25s ease-in-out;
transition: all 0.25s ease-in-out;
width: 100px;
text-align: center;
padding-top: 0;
margin-top: 0;
z-index: 200;
border-radius: 3px;
padding-top: 8px;
padding-bottom: 8px;
visibility: hidden;
li {
background: lighten($theme-color, 5%);
padding: 5px;
a {
@ -140,24 +144,14 @@ body {
img {
width: 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 {
@extend .ct-language-selected;
}
}
}
.list-unstyled {
@ -169,7 +163,7 @@ body {
.ct-language {
display: inline-block;
position: relative;
background: #fefefe2b;
background-color: #fefefe2b;
padding: 3px 10px;
border-radius: 3px;
@ -177,8 +171,9 @@ body {
cursor: pointer;
.ct-language-dropdown {
padding-top: 8px;
margin-top: 8px;
max-height: 10000px;
visibility: visible;
}
}

View file

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

View file

@ -200,6 +200,7 @@ html {
*/
.page-content {
@extend %flex-1; /* <-- Keep footer on the bottom */
-ms-flex: none; /* <-- Fix IE footer issue */
padding: $spacing-unit * 1.5 0;
}
@ -378,7 +379,7 @@ html {
* Layout and sidebar
*/
.framework {
@extend %flex-layout;
@extend %flex;
.main {
@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);
})();
}
}