ZuoZuomu

仰望星空,也得脚踏实地。

后台
文章详情

博客升级改造

2018-07-26

开始

之前写的个人博客确实有点太丑了,最近重写了一番。做了移动端适配,增加了文章标签以及做了相册等功能。 看着很不错。talk is cheap,show me you code。一图胜千言,且看如下效果:

clipboard.png

个人博客地址:http://www.baijiawei.top

项目GitHub地址:https://github.com/bjw1234/blogNext

自定义滚动条

目前对于自定义滚动条支持情况比较好的也就只有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/363/styling-scrollbars/

页面顶canvas动画

这里给出原作者的地址:https://codepen.io/iamfrontender/details/yNVPeX 起初想着自己实现这个效果,大概写完之后发现人家的背景是用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/1190000013738908

前端gulp自动化工具
元芳,你怎么看?
秘钥: