开始
之前写的个人博客确实有点太丑了,最近重写了一番。做了移动端适配,增加了文章标签以及做了相册等功能。
看着很不错。talk is cheap,show me you code。一图胜千言,且看如下效果:
个人博客地址:http://www.baijiawei.top
项目GitHub地址:https://github.com/bjw1234/bl...
自定义滚动条
目前对于自定义滚动条支持情况比较好的也就只有Chrome了,所以针对Chrome有必要把滚动条的样式改造一下。
虽然有jQuery插件可以完成各个浏览器下的自定义滚动条样式,但是由于整个项目都是用原生JS开发完成的,
未使用jQuery,所以也没必要为了一个滚动条引入一个库和一个插件了。
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
/*不要水平滚动条*/
::-webkit-scrollbar:horizontal {
height: 0;
}
/*主干样式*/
::-webkit-scrollbar-track {
background-color: rgba(0, 0, 0, .1);
-webkit-box-shadow: inset 1px 1px 0 rgba(0, 0, 0, .1);
}
/*鼠标悬浮时主干样式*/
::-webkit-scrollbar-track:hover {
background-color: rgba(0, 0, 0, .2);
-webkit-box-shadow: inset 1px 1px 0 rgba(0, 0, 0, .1);
}
/*滑块样式*/
::-webkit-scrollbar-thumb {
border-radius: 10px;
background-color: rgba(0, 0, 0, .3);
-webkit-box-shadow: inset 1px 1px 0 rgba(0, 0, 0, .1);
}
/*鼠标悬浮时滑块样式*/
::-webkit-scrollbar-thumb:hover {
border-radius: 10px;
background-color: rgba(0, 0, 0, .4);
-webkit-box-shadow: inset 1px 1px 0 rgba(0, 0, 0, .1);
}
:hover::-webkit-scrollbar-thumb {
border-radius: 10px;
background-color: rgba(0, 0, 0, .4);
-webkit-box-shadow: inset 1px 1px 0 rgba(0, 0, 0, .1);
}
/*上端按钮样式*/
::-webkit-scrollbar-button:start {
width: 10px;
height: 10px;
background: url(./image/scrollbar_arrow.png) no-repeat 0 0;
}
::-webkit-scrollbar-button:start:hover {
background: url(./image/scrollbar_arrow.png) no-repeat -15px 0;
}
/*下端按钮样式*/
::-webkit-scrollbar-button:end {
background: url(./image/scrollbar_arrow.png) no-repeat 0 -18px;
}
::-webkit-scrollbar-button:end:hover {
background: url(./image/scrollbar_arrow.png) no-repeat -15px -18px;
}
webkit提供的还有更多的伪类,可以定制更丰富滚动条样式。
详细内容参考:https://www.webkit.org/blog/3...
页面顶canvas动画
这里给出原作者的地址:https://codepen.io/iamfronten...
起初想着自己实现这个效果,大概写完之后发现人家的背景是用SVG做的,
还有一点点随风飘动的赶脚,索性就直接用的人家的代码。^_^||
原理:通过window
对象上的requestAnimationFrame
方法不断地重绘canvas,实现小星星,流星等的位移、透明度的变化。
写一点伪码:
let canvas = document.getElementById(‘canvas‘);
let ctx = canvas.getContext(‘2d‘);
// 初始化
init();
// 绘制
draw();
function draw(){
// 清空画板
ctx.clearRect(0,0,canvasW,canvasH);
// 绘制小星星
for(var i = 0; i < stars.length; i++) {
stars[i].move(); // 位移
stars[i].changAlpha(); // 改变透明度
stars[i].drawSelf(); // 画出自己
stars[i].checkBound(); // 边界检测
}
// 绘制流星同理
...
// 不断地重绘
window.requestAnimationFrame(draw);
}
// 星星类
function star(){
// 很多自己的属性
....
this.move = function(){}
this.changAlpha = function(){}
this.drawSelf = function(){}
this.checkBound = function(){}
}
如果流星出现的概率是3%
,我们怎么精准的控制它呢?
// 获取概率(Boolean)
function getProbability(percent) {
return Matth.floor(Math.random()*100+1) < percent;
}
getProbability(3); // 当返回true的时候再去添加彗星
流畅的返回顶部
原理:也是使用requestAnimationFrame
这个函数不断改变scrollTo
(滚动到)的位置。
使用setTimeout
函数调整容器的scrollTop
值虽然也能实现返回顶部的效果,但没有上面这种方法流畅。
// 返回顶部
function smoothScroll() {
var currentScroll = document.documentElement.scrollTop || document.body.scrollTop;
if (currentScroll > 0) {
window.requestAnimationFrame(smoothScroll);
window.scrollTo(0, currentScroll - (currentScroll / 5));
}
}
关于文章标签
一篇文章
对应多个标签
。
一个标签
也可以被多篇文章使用
。
典型的多对多关系。
后端数据库使用的是MongoDB
,实现这种多对多关系的数据表索引有点不知从何下手的感觉。
索性就使用了子文档的方式实现这样的效果。
(ps: 如果您有思路的话,希望可以不吝赐教,非常感谢。
)
const mongoose = require(‘mongoose‘);
const Category = require(‘./categorySch‘);
// Article
module.exports = new mongoose.Schema({
// 关联字段
children: [ // 子文档标签数组
Category
],
// 作者
user: {
type: mongoose.Schema.Types.ObjectId,
ref: ‘User‘
},
// 内容
content: {
type: String,
default: ‘‘
}
....
});
使用这种方式添加、查询标签都很容易。
// 将用户提交的标签用空格切分返回一个对象
let categoryArr = category.split(‘ ‘).map(item => {
return { category_name: item };
});
// 将用户提交的数据加入数据库
return new Article({
title: title,
// 直接就可以添加
children: categoryArr,
}).save();
// 查询就更简单了
article.children;
在模板中使用一个for
循环就可以直接渲染数据:
{% for category in art.children %}
<li class="tag">
<a href="...">{{ category.category_name }}</a>
</li>
{% endfor %}
至于根据标签查询对应文章,起初想着向后端传递标签的ID,但是,发现每篇文章下相同类别的标签对应的ID不同。
(这就是使用子文档的代价
),索性就直接传递标签名了,虽说这样的方式不优雅,但也能实现想要的效果了。
前一条和后一条数据
let prev = function () {
return Article.find({‘_id‘: {‘$gt‘: id}}).sort({_id: 1}).limit(1).then(result => {
data.prev = null;
if (result.length >= 0) {
data.prev = result[0];
}
});
};
let next = function () {
return Article.find({‘_id‘: {‘$lt‘: id}}).sort({_id: -1}).limit(1).then(result => {
data.next = null;
if (result.length >= 0) {
data.next = result[0];
}
});
};
相册功能开发
图片存储使用了图床(路过图床),后端只需要存储markdown
语法的字符串,
前端就可以解析成img
标签,还是蛮好用的。
最后
至于像是服务器搭建、模板引擎、markdown语法高亮、分页等功能就不重复说了。
详细内容可以看我之前的文章。
https://segmentfault.com/a/11...