feat: add lazyload image
This commit is contained in:
parent
86f2e3ccc9
commit
3abec3cb33
|
@ -176,6 +176,13 @@ rss:
|
|||
enable: false
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# lazyload image
|
||||
# ---------------------------------------------------------------------------------------
|
||||
lazyload:
|
||||
enable: false
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# CDN
|
||||
# ---------------------------------------------------------------------------------------
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
<%- __js('js/code-copy.js') %>
|
||||
<% } %>
|
||||
|
||||
<% if (theme.lazyload.enable) { %>
|
||||
<%- __js('js/lazyload.js') %>
|
||||
<% } %>
|
||||
|
||||
<div class="post-scripts<%= theme.pjax.enable === true ? ' pjax' : '' %>">
|
||||
<% if (theme.toc.enable && is_post()) { %>
|
||||
<%- __js([
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
'use strict'
|
||||
hexo.extend.filter.register(
|
||||
'after_post_render',
|
||||
function (data) {
|
||||
const theme = hexo.theme.config;
|
||||
if (!theme.lazyload || !theme.lazyload.enable) return;
|
||||
data.content = data.content.replace(
|
||||
// Match 'img' tags width the src attribute.
|
||||
/<img([^>]*)src="([^"]*)"([^>]*)>/gim,
|
||||
function (match, attrBegin, src, attrEnd) {
|
||||
// Exit if the src doesn't exists.
|
||||
if (!src) return match;
|
||||
|
||||
return `<img ${attrBegin}
|
||||
lazyload
|
||||
src="/images/loading.svg"
|
||||
data-src="${src}"
|
||||
${attrEnd}
|
||||
>`
|
||||
}
|
||||
)
|
||||
},
|
||||
1
|
||||
);
|
|
@ -14,7 +14,7 @@ hexo.extend.helper.register('export_config', function () {
|
|||
|
||||
let {config, theme} = this;
|
||||
|
||||
// ------------ export language to js ------------
|
||||
// ------------------------ export language to js ------------------------
|
||||
const languageDir = path.join(__dirname, '../../languages');
|
||||
let file = fs.readdirSync(languageDir).find(v => v === `${config.language}.yml`);
|
||||
file = languageDir + '/' + (file ? file : 'en.yml');
|
||||
|
@ -24,7 +24,7 @@ hexo.extend.helper.register('export_config', function () {
|
|||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
// -----------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
let hexo_config = {
|
||||
|
@ -43,6 +43,7 @@ hexo.extend.helper.register('export_config', function () {
|
|||
code_copy: theme.code_copy,
|
||||
side_tools: theme.side_tools,
|
||||
pjax: theme.pjax,
|
||||
lazyload: theme.lazyload,
|
||||
version: theme.version,
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
@require 'keep-theme.styl'
|
||||
|
||||
|
||||
// ============================
|
||||
// ======================================================================
|
||||
// html, body
|
||||
// ============================
|
||||
// ======================================================================
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
@ -29,9 +29,9 @@ html, body {
|
|||
}
|
||||
|
||||
|
||||
// ============================
|
||||
// ======================================================================
|
||||
// scrollbar
|
||||
// ============================
|
||||
// ======================================================================
|
||||
* {
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
|
@ -48,18 +48,18 @@ html, body {
|
|||
}
|
||||
|
||||
|
||||
// ============================
|
||||
// ======================================================================
|
||||
// selection
|
||||
// ============================
|
||||
// ======================================================================
|
||||
::selection {
|
||||
background: var(--selection-color);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
||||
// ============================
|
||||
// ======================================================================
|
||||
// ul, ol, li
|
||||
// ============================
|
||||
// ======================================================================
|
||||
ul, ol, li {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
@ -67,9 +67,9 @@ ul, ol, li {
|
|||
}
|
||||
|
||||
|
||||
// ============================
|
||||
// ======================================================================
|
||||
// a
|
||||
// ============================
|
||||
// ======================================================================
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--default-text-color);
|
||||
|
@ -82,9 +82,24 @@ a {
|
|||
}
|
||||
|
||||
|
||||
// ============================
|
||||
// ======================================================================
|
||||
// img
|
||||
// ======================================================================
|
||||
img {
|
||||
&[lazyload] {
|
||||
padding: 20px;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
margin: 20px auto !important;
|
||||
background: var(--lazyload-background-color);
|
||||
transition();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ======================================================================
|
||||
// button
|
||||
// ============================
|
||||
// ======================================================================
|
||||
button {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
@ -113,9 +128,9 @@ button {
|
|||
}
|
||||
|
||||
|
||||
// ============================
|
||||
// ======================================================================
|
||||
// flex center
|
||||
// ============================
|
||||
// ======================================================================
|
||||
.flex-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -123,9 +138,9 @@ button {
|
|||
}
|
||||
|
||||
|
||||
// ============================
|
||||
// ======================================================================
|
||||
// clear float
|
||||
// ============================
|
||||
// ======================================================================
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
|
|
@ -172,6 +172,7 @@
|
|||
cursor: zoom-in;
|
||||
display: block;
|
||||
box-shadow: 0 0 2px var(--shadow-color);
|
||||
transition();
|
||||
|
||||
if (hexo-config('style.article_img_align') == 'center') {
|
||||
margin: 10px auto 2px;
|
||||
|
|
|
@ -6,24 +6,25 @@
|
|||
// ========================================================================================
|
||||
// layout
|
||||
// ========================================================================================
|
||||
$header-height = 76px; // 头部默认高度
|
||||
$header-shrink-height = $header-height * 0.72; // 头部收缩高度
|
||||
$scroll-progress-bar-height = 2px; // 头部进度条高度
|
||||
$main-content-width = 80%; // 中间内容区域宽度(PC)
|
||||
$main-content-width-tablet = 85%; // 中间内容区域宽度(平板)
|
||||
$main-content-width-mobile = 90%; // 中间内容区域宽度(手机)
|
||||
$circle-button-width = 40px; // tools 圆形工具按钮宽度
|
||||
$tools-button-width = 32px; // tools 方形工具按钮宽度
|
||||
$component-interspace = 30px; // 组件/模块的间隔值(PC)
|
||||
$header-height = 76px; // header height
|
||||
$header-shrink-height = $header-height * 0.72; // header shrink height
|
||||
$scroll-progress-bar-height = 2px; // scroll progress bar height
|
||||
$main-content-width = 80%; // main content width (tablet)
|
||||
$main-content-width-tablet = 86%; // main content width (PC)
|
||||
$main-content-width-mobile = 90%; // main content width (mobile)
|
||||
$circle-button-width = 38px; // post tool button width
|
||||
$component-spacing-value = 30px; // component-spacing-value (PC)
|
||||
|
||||
// main content max width
|
||||
$temp-content-max-width = hexo-config('style.content_max_width');
|
||||
$content-max-width = $temp-content-max-width ? convert($temp-content-max-width) : 1000px;
|
||||
|
||||
|
||||
// ========================================================================================
|
||||
// 媒体查询
|
||||
// media query
|
||||
// ========================================================================================
|
||||
$media-max-width = 780px; // 媒体查询最大宽度 (平板)
|
||||
$media-max-width-mobile = 500px; // 媒体查询最大宽度(手机)
|
||||
$media-max-width = 780px; // media query max width (tablet)
|
||||
$media-max-width-mobile = 500px; // media query max width (mobile)
|
||||
|
||||
keep-tablet()
|
||||
@media (max-width: $media-max-width)
|
||||
|
@ -76,6 +77,7 @@ $link-color = darken($default-text-color, 10%);
|
|||
$copyright-info-color = #CC0033;
|
||||
$avatar-background-color = #0066CC;
|
||||
$loading-progress-bar-color = #990000;
|
||||
$lazyload-background-color = rgba(200, 200, 200, 0.5);
|
||||
|
||||
|
||||
// ========================================================================================
|
||||
|
@ -99,6 +101,7 @@ $dark-link-color = lighten($dark-default-text-color, 10%);
|
|||
$dark-copyright-info-color = darken($copyright-info-color, 20%);
|
||||
$dark-avatar-background-color = darken($avatar-background-color, 10%);
|
||||
$dark-loading-progress-bar-color = lighten($loading-progress-bar-color, 50%);
|
||||
$dark-lazyload-background-color = rgba(50, 50, 50, 0.5);
|
||||
|
||||
|
||||
// ========================================================================
|
||||
|
@ -132,6 +135,7 @@ root-color(mode) {
|
|||
--copyright-info-color: mode == 'light' ? $copyright-info-color : $dark-copyright-info-color;
|
||||
--avatar-background-color: mode == 'light' ? $avatar-background-color : $dark-avatar-background-color;
|
||||
--loading-progress-bar-color : mode == 'light' ? $loading-progress-bar-color : $dark-loading-progress-bar-color;
|
||||
--lazyload-background-color : mode == 'light' ? $lazyload-background-color : $dark-lazyload-background-color;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ $article-date-font-size = 1rem;
|
|||
.archive-list-container {
|
||||
|
||||
.archive-item {
|
||||
margin-bottom: $component-interspace;
|
||||
margin-bottom: $component-spacing-value;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
|
|
|
@ -12,7 +12,7 @@ if (hexo-config('comment.valine.enable') && hexo-config('comment.gitalk.enable')
|
|||
|
||||
.comments-container {
|
||||
display: inline-block;
|
||||
margin-top: $component-interspace;
|
||||
margin-top: $component-spacing-value;
|
||||
width: 100%;
|
||||
|
||||
#comment-anchor {
|
||||
|
|
|
@ -91,7 +91,7 @@ $article-title-font-size = 1.6rem;
|
|||
|
||||
|
||||
.article-content {
|
||||
margin-top: $component-interspace;
|
||||
margin-top: $component-spacing-value;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
word-wrap: break-word;
|
||||
|
@ -99,13 +99,13 @@ $article-title-font-size = 1.6rem;
|
|||
}
|
||||
|
||||
.post-copyright-info {
|
||||
margin-top: $component-interspace;
|
||||
margin-top: $component-spacing-value;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.article-nav {
|
||||
height: 40px;
|
||||
margin-top: $component-interspace;
|
||||
margin-top: $component-spacing-value;
|
||||
|
||||
.article-prev, .article-next {
|
||||
max-width: $post-nav-max-width;
|
||||
|
|
|
@ -18,7 +18,7 @@ $category-name-font-size = 1.6rem;
|
|||
|
||||
font-weight: 600;
|
||||
padding-bottom: 20px;
|
||||
margin-bottom: $component-interspace;
|
||||
margin-bottom: $component-spacing-value;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,14 +78,14 @@ $page-aside-width = $temp-width ? convert($temp-width) : 260px;
|
|||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: $component-interspace 0;
|
||||
padding: $component-spacing-value 0;
|
||||
|
||||
+keep-tablet() {
|
||||
padding: $component-interspace * 0.8 0;
|
||||
padding: $component-spacing-value * 0.8 0;
|
||||
}
|
||||
|
||||
+keep-mobile() {
|
||||
padding: $component-interspace * 0.6 0;
|
||||
padding: $component-spacing-value * 0.6 0;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
|
@ -137,25 +137,25 @@ $page-aside-width = $temp-width ? convert($temp-width) : 260px;
|
|||
|
||||
.post-tools {
|
||||
position: fixed;
|
||||
top: $header-height + $component-interspace;
|
||||
right: $component-interspace;
|
||||
top: $header-height + $component-spacing-value;
|
||||
right: $component-spacing-value;
|
||||
transition();
|
||||
|
||||
.header-shrink & {
|
||||
top: $header-shrink-height + $component-interspace;
|
||||
top: $header-shrink-height + $component-spacing-value;
|
||||
|
||||
+keep-tablet() {
|
||||
top: $header-shrink-height * 0.9 + $component-interspace;
|
||||
top: $header-shrink-height * 0.9 + $component-spacing-value;
|
||||
}
|
||||
|
||||
+keep-mobile() {
|
||||
top: $header-shrink-height * 0.8 + $component-interspace;
|
||||
top: $header-shrink-height * 0.8 + $component-spacing-value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+keep-tablet() {
|
||||
top: $header-height * 0.9 + $component-interspace;
|
||||
top: $header-height * 0.9 + $component-spacing-value;
|
||||
right: 10px;
|
||||
transform: scale(0.82);
|
||||
transform-origin: right top;
|
||||
|
@ -163,7 +163,7 @@ $page-aside-width = $temp-width ? convert($temp-width) : 260px;
|
|||
|
||||
|
||||
+keep-mobile() {
|
||||
top: $header-height * 0.8 + $component-interspace;
|
||||
top: $header-height * 0.8 + $component-spacing-value;
|
||||
right: 5px;
|
||||
transform: scale(0.72);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ $tag-name-font-size = 1.6rem;
|
|||
|
||||
font-weight: 600;
|
||||
padding-bottom: 20px;
|
||||
margin-bottom: $component-interspace;
|
||||
margin-bottom: $component-spacing-value;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
|
||||
<svg width="38" height="38" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg" stroke="#fff">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<g transform="translate(1 1)" stroke-width="2">
|
||||
<circle stroke-opacity=".5" cx="18" cy="18" r="18"/>
|
||||
<path d="M36 18c0-9.94-8.06-18-18-18">
|
||||
<animateTransform
|
||||
attributeName="transform"
|
||||
type="rotate"
|
||||
from="0 18 18"
|
||||
to="360 18 18"
|
||||
dur="1s"
|
||||
repeatCount="indefinite"/>
|
||||
</path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 694 B |
|
@ -0,0 +1,41 @@
|
|||
KEEP.initLazyLoad = () => {
|
||||
const imgs = document.querySelectorAll('img');
|
||||
let now = Date.now();
|
||||
let needLoad = true;
|
||||
|
||||
function lazyload(imgs) {
|
||||
now = Date.now();
|
||||
needLoad = Array.from(imgs).some(i => i.hasAttribute('lazyload'));
|
||||
|
||||
const h = window.innerHeight;
|
||||
const s = document.documentElement.scrollTop || document.body.scrollTop;
|
||||
|
||||
imgs.forEach(img => {
|
||||
if (img.hasAttribute('lazyload') && !img.hasAttribute('loading')) {
|
||||
|
||||
if ((h + s) > img.offsetTop) {
|
||||
img.setAttribute('loading', true);
|
||||
const loadImageTimeout = setTimeout(() => {
|
||||
const temp = new Image();
|
||||
const src = img.getAttribute('data-src');
|
||||
temp.src = src;
|
||||
temp.onload = () => {
|
||||
img.src = src;
|
||||
img.removeAttribute('lazyload');
|
||||
img.removeAttribute('loading');
|
||||
clearTimeout(loadImageTimeout);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
lazyload(imgs);
|
||||
|
||||
window.onscroll = () => {
|
||||
if (Date.now() - now > 100 && needLoad) {
|
||||
lazyload(imgs);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,10 @@ window.addEventListener('DOMContentLoaded', () => {
|
|||
if (KEEP.theme_config.code_copy.enable === true) {
|
||||
KEEP.initCodeCopy();
|
||||
}
|
||||
|
||||
if (KEEP.theme_config.lazyload.enable === true) {
|
||||
KEEP.initLazyLoad();
|
||||
}
|
||||
}
|
||||
|
||||
KEEP.refresh();
|
||||
|
|
Loading…
Reference in New Issue