diff --git a/README.md b/README.md index e8fdeaa..0c2806d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,39 @@ # Present -一个简洁的个人主页,支持显示博客文章. + +Present is present by Zapic. +一个简洁的个人主页,支持显示博客文章/随机背景图片/随机语句. +[即时预览](https://kawaiizapic.github.io/Present/) +![preview.png](https://i.loli.net/2020/11/15/ukl6jRxNm8O7bD2.png) + +### Browser support: +| IE | Chrome | Firefox | Other | +| ---- | ---- | ---- | ---- | +| 11+(Particle Support) | 49+ | 52+ | (?) | + +## Setting-up: + +### 随机背景图片 +1. 将图片放入`static/img/`内. +2. 建议放入一个图片的缩略图优化加载体验. +3. 在`index.html`内找到`var bgArr = [...` +4. 按以下格式添加一个对象: +``` +{ + "url": "static/img/background.jpg", + "thumb": "static/img/background-thumb.jpg" // 如果没有缩略图,可以留空. +} +``` +5. 如果不会可以简单的学一下`JavaScript`语法. + +### 随机语句 +1. 在`index.html`内找到`var senArr = [...` +2. 按照 [Typinyin.js](https://github.com/ClassicOldSong/typinyin.js) 的文档添加语句. +3. 如果不会可以简单的学一下`JavaScript`语法. + + +### 博客文章输出 +**注意:** 使用本功能,你的服务器必须支持`PHP 5.6+`,并启用`XML`拓展. + +1. 在`feed.php`内找到`$feed_url`; +2. 将`$feed_url`修改为你的博客RSS订阅地址. +3. 如果不会可以简单的学一下`PHP`语法. \ No newline at end of file diff --git a/feed.php b/feed.php new file mode 100644 index 0000000..f9848a1 --- /dev/null +++ b/feed.php @@ -0,0 +1,26 @@ +channel->item; +$resp = [ + "status" => 0, + "data" => [] +]; +if($data){ + for($i = 0; $i < 8; $i++){ + if($data[$i]){ + $resp["data"][]=[ + "link" => ((array)$data[$i]->link)[0], + "title" => ((array)$data[$i]->title)[0], + "timestamp" => date("Y-m-d",strtotime($data[$i]->pubDate[0])) + ]; + } + else{ + break; + } + } +} +else{ + $resp["status"] = -1; +} +header("Content-type: application/json"); +echo json_encode($resp); diff --git a/index.html b/index.html new file mode 100644 index 0000000..8f3517e --- /dev/null +++ b/index.html @@ -0,0 +1,125 @@ + + + + + Present + + + + + + + + + +
+
+
+ + + + + + + + +
+
+

Loading...

+

Present

+

+
+
+
+
+
+
+
+
+
+
+ + Loading... +
+
+
+ This is a simple homepage theme by Zapic. +
+ +
+
+
+
+
+
链接
+
+
+
+
文章
+
+
+
+
关于
+
+
+
+
+ +
+ + + + + + + + diff --git a/static/css/loading.css b/static/css/loading.css new file mode 100644 index 0000000..13e0481 --- /dev/null +++ b/static/css/loading.css @@ -0,0 +1,181 @@ +/** + * + * Present by Zapic @ 2020 + * https://github.com/KawaiiZapic/Present/ + * + * Please DO NOT remove this copyright message, as the basic respect for origin author. + * + */ + +.flex-center { + display: flex; + align-items: center; + justify-content: center; +} + +.fixed-layer { + top: 0; + left: 0; + position: fixed; + +} + +.loading-indicator, .fixed-layer, .self-avatar { + top: 0; + left: 0; +} + +.text-center { + text-align: center; +} + +.avatar-name { + opacity: 0; +} + +.loading-indicator { + z-index: 2; + position: absolute; +} + +.loading-indicator * { + transform-origin: center; +} + +.loading-indicator .circle-line { + fill: none; + stroke: #fb7299; + stroke-width: 8; + stroke-dasharray: 351; + transform-origin: center center; + animation: spinner-path 1s infinite; +} + +.loading-indicator .circle-rotating { + animation: spinner-rotate 2s linear infinite; +} + +.loading-indicator .circle-step { + animation: spinner-layer 4s steps(1) infinite; +} + +.loading-mask { + z-index: 1; + width: 100%; + height: 100%; + background: white; +} + +.loading-pre { + opacity: 1; + transition: .5s .5s; + transform: translateY(0); +} + +.loading-wrapper { + width: 128px; + height: 128px; + overflow: hidden; + position: relative; + border-radius: 64px; +} + +.loading-wrapper .avatar-img { + width: 100%; + height: 100%; + transition: .5s .5s; + object-fit: contain; + object-position: center; +} + +.loading-text { + z-index: 1; + color: #666; + height: 1.6em; + display: block; + line-height: 0; + font-size: 3em; + margin-left: 24px; + user-select: none; + position: relative; + -ms-user-select: none; +} + + +.self-avatar { + width: 100vw; + height: 100vh; + position: absolute; + min-height: 270px; +} + +.self-avatar .avatar-img { + opacity: 0; + z-index: 1; + position: absolute; + transform: translateY(32px); +} + +@keyframes spinner-path { + 0% { + transform: rotate(0); + stroke-dashoffset: 345; + } + 50% { + transform: rotate(0); + stroke-dashoffset: 81; + } + 100% { + stroke-dashoffset: 345; + transform: rotate(270deg); + + } +} + +@keyframes spinner-layer { + 0% { + transform: rotate(360deg); + } + 25% { + transform: rotate(270deg); + } + 50% { + transform: rotate(180deg); + } + 75% { + transform: rotate(90deg); + } + 100% { + transform: rotate(0deg); + } +} + +@keyframes spinner-rotate { + 0% { + transform: rotate(0); + } + 100% { + transform: rotate(360deg); + } +} + + +@media (max-width: 750px) { + .loading-indicator { + transform: scale(.75); + transform-origin: top left; + } + + .loading-text { + margin-left: 0; + } + + .loading-wrapper { + width: 96px; + height: 96px; + } + + .self-avatar { + flex-direction: column; + } +} \ No newline at end of file diff --git a/static/css/main.css b/static/css/main.css new file mode 100644 index 0000000..edb3c4b --- /dev/null +++ b/static/css/main.css @@ -0,0 +1,433 @@ +/** + * + * Present by Zapic @ 2020 + * https://github.com/KawaiiZapic/Present/ + * + * Please DO NOT remove this copyright message, as the basic respect for origin author. + * + */ + +a[href] { + color: #333; + text-decoration: none; +} + +body { + margin: 0; + overflow-x: hidden; + padding-left: 50vw; + font-family: 'Google Sans', 'helvetica', 'Aiarl', sans-serif; +} + +body.locked, .content-container, .self-wrapper, .article-title { + overflow: hidden; +} + +.link-item, .switcher-btn, .self-wrapper, .btn-icon .fa, .btn-text, .btn-select-indicator, .article-loading, .article-content, .article-title { + transition: .2s; +} + +.link-icon, .switcher-btn, .empty { + user-select: none; + -ms-user-select: none; +} + +.article-content { + height: 0; + opacity: 0; +} + +.article-loading { + height: 100%; + flex-direction: column; +} + +.article-loading .loading-indicator { + position: relative; + transform: scale(.5); + visibility: visible !important; + transform-origin: center center; +} + +.article-content.empty { + color: #ccc; + height: 100%; + display: flex; + align-items: center; + flex-direction: column; + justify-content: center; +} + +.article-content.empty .fa { + font-size: 3em; +} + +.article-item { + margin-top: 0; + margin-bottom: 10px; +} + +.article-time { + color: #ccc; + width: 85px; + float: right; + margin-top: 4px; + display: inline-block; +} + +.article-title { + width: calc(100% - 90px); + display: inline-block; + text-overflow: ellipsis; +} + +.article-title:hover { + color: #fb7299; +} + +.background-layer { + z-index: -10; + width: 100vw; + height: 100vh; + transition: 1s; + display: block; + transition-property: filter, transform; + background: none no-repeat center/cover; +} + +.background-layer.loading { + filter: blur(50px); + transform: scale(1.5); +} + +.background-filter { + z-index: -9; + width: 100vw; + height: 100vh; + background-image: linear-gradient(0deg, rgba(0, 0, 0, .2), transparent); +} + +.btn-icon { + margin-top: 8px; +} + +.btn-icon .fa { + font-size: 2em; +} + +.btn-select-indicator { + bottom: 0; + height: 3px; + width: 33.3%; + position: absolute; + border-radius: 5px; + box-sizing: border-box; + background-color: white; +} + +.btn-text { + font-size: 12px; +} + +.content-container { + width: 320px; + height: 400px; + background: white; + position: relative; + border-radius: 3px; + box-shadow: 4px 4px 5px 0 rgba(0, 0, 0, .5); +} + +.content-layer { + width: 50vw; + height: 100vh; + min-height: 420px; + box-sizing: border-box; +} + +.content-layer.finished { + animation: .5s 1s content-in; +} + +.dokidoki-text { + opacity: 0; + color: white; + font-size: .4em; + line-height: 1.2; + max-width: 200px; + transition: .5s 1s; + white-space: nowrap; +} + +.dokidoki-text span { + white-space: pre-wrap !important; +} + +.footer-container { + left: 0; + z-index: 0; + width: 100%; + bottom: 8px; + color: white; + position: absolute; + text-shadow: 4px 4px 5px rgba(0, 0, 0, .5); +} +.finished .dokidoki-text { + opacity: 1; + transform: translateY(-3em); + text-shadow: 4px 4px 5px rgba(0, 0, 0, .5); +} + +.finished .loading-wrapper { + transition: box-shandow .5s 1s; + box-shadow: 4px 4px 5px 0 rgba(0, 0, 0, .5); +} + +.finished.no-delay .no-delay, .finished.no-delay { + transition: 0s !important; +} + +.footer-container a { + color: #fb7299; +} + +.info-container { + height: 100%; + white-space: normal; +} + +.link-icon { + width: 100%; + height: 64px; + color: #fb7299; + padding: 8px 0; + box-sizing: border-box; +} + +.link-icon .fa { + font-size: 2.5em; +} + +.link-item { + float: left; + width: 33.3%; + color: #333; + padding: 10px 0; + border-radius: 5px; + box-sizing: border-box; + text-decoration-line: none; +} + +.link-item:hover { + background: rgba(0, 0, 0, .05); +} + +.loaded .article-content { + opacity: 1; +} + +.loaded .article-loading { + opacity: 0; + pointer-events: none; +} + +.self-avatar.finished { + width: 50vw; + transition: .5s 1s; + pointer-events: none; +} + +.self-avatar.finished g { + animation-play-state: paused; +} + +.self-avatar.finished .avatar-img { + opacity: 1; + transform: translateY(0); +} + +.self-avatar.finished .avatar-name { + animation: name-out 1.5s 1 forwards; +} + +.self-avatar.finished .circle-line { + transition: .5s; + stroke: transparent; + animation: spinner-fill 1.5s 1 forwards; +} + +.self-avatar.finished .loading-pre { + opacity: 0; + transform: translateY(-1em); +} + +.self-avatar.finished .loading-mask { + width: 0; + transition: .5s 1s; +} + +.self-content { + float: left; + width: 33.3%; + height: 100%; + padding: 20px 10px; + display: inline-block; + box-sizing: border-box; +} + +.self-content.links-container { + display: flex; + flex-wrap: wrap; +} + +.self-switcher { + left: 0; + bottom: 0; + width: 100%; + height: 64px; + position: absolute; + background-color: #fb7299; +} + +.self-wrapper { + width: 300%; + position: absolute; + white-space: nowrap; + height: calc(100% - 64px); +} + +.switcher-btn { + float: left; + width: 33.3%; + color: white; + height: 100%; + cursor: pointer; +} + +.switcher-btn:hover { + background: rgba(255, 255, 255, .2); +} + +.switcher-btn.selected .btn-icon .fa { + font-size: 2.5em; + transform: translateY(.1em); +} + +.switcher-btn.selected .btn-text { + opacity: 0; +} + +@keyframes content-in { + 0% { + opacity: 0; + transform: translateX(50px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes content-in-hoz { + 0% { + opacity: 0; + transform: translateY(50px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes spinner-fill { + 0% { + stroke: #FB7299; + stroke-width: 8; + transform: scale(1); + stroke-dasharray: 351; + stroke-dashoffset: 345; + } + 33% { + stroke: #cccccc; + stroke-dashoffset: 0; + stroke-dasharray: 403; + transform: scale(1.15); + } + 66% { + stroke: #cccccc; + stroke-dashoffset: 0; + stroke-dasharray: 403; + transform: scale(1.15); + } + 100% { + stroke: white; + stroke-dashoffset: 0; + stroke-dasharray: 403; + transform: scale(1.15); + } +} + +@keyframes name-out { + 0% { + transform: translateY(0); + opacity: 0; + } + 33% { + transform: translateY(0); + opacity: 0; + } + 66% { + opacity: 1; + color: #333; + transform: translateY(-1em); + text-shadow: none; + } + 100% { + transform: translateY(-1.2em); + opacity: 1; + color: white; + text-shadow: 4px 4px 5px rgba(0, 0, 0, .5); + } + +} + +@media (max-width: 750px) { + body { + padding-left: 0; + padding-top: 40vh; + } + + .content-layer { + width: 100vw; + height: 60vh; + min-height: 450px; + padding-left: 10px; + align-items: start; + position: relative; + padding-right: 10px; + } + + .content-layer.finished { + animation: .5s 1s content-in-hoz; + } + + .self-avatar.finished { + width: 100vw; + height: 40vh; + } + + .self-avatar.finished .loading-mask { + width: 100%; + height: 0; + } +} + +@media (max-height: 750px) and (max-width: 750px) { + body { + padding-top: 300px; + } + + .content-layer { + align-items: start; + } +} diff --git a/static/img/avatar.jpg b/static/img/avatar.jpg new file mode 100755 index 0000000..13aa6df Binary files /dev/null and b/static/img/avatar.jpg differ diff --git a/static/img/background-1-thumb.jpg b/static/img/background-1-thumb.jpg new file mode 100644 index 0000000..ec9b789 Binary files /dev/null and b/static/img/background-1-thumb.jpg differ diff --git a/static/img/background-1.jpg b/static/img/background-1.jpg new file mode 100644 index 0000000..ef52f4a Binary files /dev/null and b/static/img/background-1.jpg differ diff --git a/static/img/background-2-thumb.jpg b/static/img/background-2-thumb.jpg new file mode 100644 index 0000000..606ab70 Binary files /dev/null and b/static/img/background-2-thumb.jpg differ diff --git a/static/img/background-2.jpg b/static/img/background-2.jpg new file mode 100644 index 0000000..4d1ffad Binary files /dev/null and b/static/img/background-2.jpg differ diff --git a/static/js/main.js b/static/js/main.js new file mode 100644 index 0000000..2b8463a --- /dev/null +++ b/static/js/main.js @@ -0,0 +1,115 @@ +/** + * + * Present by Zapic @ 2020 + * https://github.com/KawaiiZapic/Present/ + * + * Please DO NOT remove this copyright message, as the basic respect for origin author. + * + */ + +NodeList.prototype.forEach = NodeList.prototype.forEach || function (callback) { + for (let i = 0; i < this.length; i++) { + callback.call(this[i], this[i], i) + } +}; + +function qSlt(selector) { + return document.querySelector(selector); +} + +function qSltAll(selector) { + return document.querySelectorAll(selector); +} + +function setArtTip(content) { + qSlt(".article-content").classList.add("empty"); + qSlt(".article-content").innerHTML = content; +} + +function randomSet(set) { + for (var i = 0; i < set.length; i++) { + var r = Math.floor(Math.random() * (set.length - i)); + var p = set[r]; + set[r] = set[i]; + set[i] = p; + } +} + +var feed = new XMLHttpRequest(); +feed.open("GET", feedPath, true); +feed.addEventListener("load", function () { + qSlt(".article-container").classList.add("loaded"); + try { + var data = JSON.parse(feed.responseText); + } catch (e) { + } + if (feed.status !== 200 || !data || data.status === -1) { + setArtTip('

暂时无法连接到博客

'); + return; + } + data = data.data; + if (data.length === 0) { + setArtTip('

暂时没有文章

'); + return; + } + for (var i = 0; i < data.length; i++) { + qSlt(".article-content").innerHTML += '

' + data[i].title + '' + data[i].timestamp + '

'; + } +}); +feed.addEventListener("error", function () { + qSlt(".article-container").classList.add("loaded"); + setArtTip('

暂时无法连接到博客

'); +}); +feed.send(); +var sBg = bgArr[Math.floor(Math.random() * bgArr.length)]; +qSlt(".background-layer").style.backgroundImage = "url(" + sBg.thumb + ")"; +var bgLoader = new Image(); +bgLoader.src = sBg.url; +var bgTimeout = -1; + +function bgHandler() { + bgTimeout === -1 ? 0 : clearTimeout(bgTimeout); + qSlt(".background-layer").style.backgroundImage = "url(" + sBg.url + ")"; + qSlt(".background-layer").classList.remove("loading"); +} + +bgLoader.complete ? bgHandler() : (function () { + bgLoader.addEventListener("load", bgHandler); + bgTimeout = setTimeout(function () { + qSlt(".background-layer").classList.add("loading"); + }, 1000); +})(); +var doki = new Typinyin(); +randomSet(senArr); +doki.setOptions({ + sentences: senArr, + startDelay: 1000, + typeSpeed: 100, + pause: 3000, + backSpeed: 60, + cursorChar: "|", + loop: true, +}); +window.addEventListener("DOMContentLoaded", function () { + qSlt(".circle-line").addEventListener("animationiteration", function () { + doki.attach(".dokidoki-text"); + qSlt(".self-avatar").classList.add("finished"); + qSlt(".content-layer").classList.add("finished"); + setTimeout(function () { + document.body.classList.remove("locked"); + qSlt(".content-layer").classList.remove("finished"); + qSlt(".self-avatar").classList.add("no-delay"); + doki.init(); + }, 1500); + qSltAll(".switcher-btn").forEach(function (v) { + var id = v.id.substr(-1); + v.addEventListener("click", function () { + qSlt(".self-wrapper").style.transform = "translateX(-" + 33.3 * (parseInt(id) - 1) + "%)"; + qSlt(".btn-select-indicator").style.left = "" + 33.3 * (parseInt(id) - 1) + "%"; + qSlt(".selected").classList.remove("selected"); + v.classList.add("selected"); + }); + }); + }, {once: true}); +}); +console.log("\n %c Present %c By Zapic \n\n", "color: #fff; background: #fb7299; padding:5px 0;", "background: #efefef; padding:5px 0;"); \ No newline at end of file