intimater 2019-06-28
之前写的个人博客确实有点太丑了,最近重写了一番。做了移动端适配,增加了文章标签以及做了相册等功能。
看着很不错。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...
这里给出原作者的地址: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...