本站更换主题啦!

故事要从四天前说起…

那天,我像往常一样刷着网站,偶然发现了DIYgod大佬的博客,看着这精美的主题,再回头审视一下自己使用的简陋到爆的next,不禁萌生了更换主题的想法。

根据footer里的信息,我找到了这个主题Sagiri的托管地址,将其下载了下来,配置好_config.yml文件并hexo s,本以为事情就这样结束了。然并卵,我发现有很多功能都无法正常使用,正如他本人在这篇文章中写的一样:

主题虽然开源了,但是属于自用性质的项目,很多应该做成可定制化的地方都没有做,从开源项目的视角来看做得并不好,而我目前又对制作主题并没有太高的兴致,所以使用之前还请慎重考虑

然而这是后话了,当时的我并没有看到这些,于是头铁地开始了主题文件的增删改查之路(此处省略一万字)。


四天过去了,通过对文件的深度剖析(指删除很多本来就有的模块然后重新添加),我深刻地了解了csshtmljavascript,明白了hexo主题的组织形式(并没有),于是准备记录一下这个主题部分特性的实现方式:

  1. 网页无刷新跳转/自动滚动到正文

    使用pjax实现,主要参考这篇文章

  2. 根据网页状态动态修改标题

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // cheat.js
    var OriginTitle = document.title;
    var titleTime;
    document.addEventListener('visibilitychange', function () {
    if (document.hidden) {
    $('[rel="icon"]').attr('href', "/images/failure.ico");
    document.title = '╭(°A°`)╮ 页面崩溃啦 ~';
    clearTimeout(titleTime);
    }
    else {
    $('[rel="icon"]').attr('href', "/images/favicon.ico");
    document.title = '(ฅ>ω<*ฅ) 噫又好了~' + OriginTitle;
    titleTime = setTimeout(function () {
    document.title = OriginTitle;
    }, 2000);
    }
    });
  3. 随机的丝带背景

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    // evan-you.js
    /*<canvas id="evanyou"></canvas>*/
    if (document.getElementById('evanyou')) {
    var c = document.getElementById('evanyou'),
    x = c.getContext('2d'),
    pr = window.devicePixelRatio || 1,
    w = window.innerWidth,
    h = window.innerHeight,
    f = 90,
    q,
    m = Math,
    r = 0,
    u = m.PI * 2,
    v = m.cos,
    z = m.random
    c.width = w * pr
    c.height = h * pr
    x.scale(pr, pr)
    x.globalAlpha = 0.6
    function evanyou () {
    x.clearRect(0, 0, w, h)
    q = [{ x: 0, y: h * .7 + f }, { x: 0, y: h * .7 - f }]
    while (q[1].x < w + f) d(q[0], q[1])
    }
    function d (i, j) {
    x.beginPath()
    x.moveTo(i.x, i.y)
    x.lineTo(j.x, j.y)
    var k = j.x + (z() * 2 - 0.25) * f,
    n = y(j.y)
    x.lineTo(k, n)
    x.closePath()
    r -= u / -50
    x.fillStyle = '#' + (v(r) * 127 + 128 << 16 | v(r + u / 3) * 127 + 128 << 8 | v(r + u / 3 * 2) * 127 + 128).toString(16)
    x.fill()
    q[0] = q[1]
    q[1] = { x: k, y: n }
    }
    function y (p) {
    var t = p + (z() * 2 - 1.1) * f
    return (t > h || t < 0) ? y(p) : t
    }
    document.onclick = evanyou
    document.ontouchstart = evanyou
    evanyou()
    }
  4. 点击的烟花效果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    // fireworks.js
    class Circle {
    constructor({ origin, speed, color, angle, context }) {
    this.origin = origin
    this.position = { ...this.origin }
    this.color = color
    this.speed = speed
    this.angle = angle
    this.context = context
    this.renderCount = 0
    }

    draw() {
    this.context.fillStyle = this.color
    this.context.beginPath()
    this.context.arc(this.position.x, this.position.y, 2, 0, Math.PI * 2)
    this.context.fill()
    }

    move() {
    this.position.x = (Math.sin(this.angle) * this.speed) + this.position.x
    this.position.y = (Math.cos(this.angle) * this.speed) + this.position.y + (this.renderCount * 0.3)
    this.renderCount++
    }
    }

    class Boom {
    constructor ({ origin, context, circleCount = 16, area }) {
    this.origin = origin
    this.context = context
    this.circleCount = circleCount
    this.area = area
    this.stop = false
    this.circles = []
    }

    randomArray(range) {
    const length = range.length
    const randomIndex = Math.floor(length * Math.random())
    return range[randomIndex]
    }

    randomColor() {
    const range = ['8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
    return '#' + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range)
    }

    randomRange(start, end) {
    return (end - start) * Math.random() + start
    }

    init() {
    for(let i = 0; i < this.circleCount; i++) {
    const circle = new Circle({
    context: this.context,
    origin: this.origin,
    color: this.randomColor(),
    angle: this.randomRange(Math.PI - 1, Math.PI + 1),
    speed: this.randomRange(1, 6)
    })
    this.circles.push(circle)
    }
    }

    move() {
    this.circles.forEach((circle, index) => {
    if (circle.position.x > this.area.width || circle.position.y > this.area.height) {
    return this.circles.splice(index, 1)
    }
    circle.move()
    })
    if (this.circles.length == 0) {
    this.stop = true
    }
    }

    draw() {
    this.circles.forEach(circle => circle.draw())
    }
    }

    class CursorSpecialEffects {
    constructor() {
    this.computerCanvas = document.createElement('canvas')
    this.renderCanvas = document.createElement('canvas')

    this.computerContext = this.computerCanvas.getContext('2d')
    this.renderContext = this.renderCanvas.getContext('2d')

    this.globalWidth = window.innerWidth
    this.globalHeight = window.innerHeight

    this.booms = []
    this.running = false
    }

    handleMouseDown(e) {
    const boom = new Boom({
    origin: { x: e.clientX, y: e.clientY },
    context: this.computerContext,
    area: {
    width: this.globalWidth,
    height: this.globalHeight
    }
    })
    boom.init()
    this.booms.push(boom)
    this.running || this.run()
    }

    handlePageHide() {
    this.booms = []
    this.running = false
    }

    init() {
    const style = this.renderCanvas.style
    style.position = 'fixed'
    style.top = style.left = 0
    style.zIndex = '999999999999999999999999999999999999999999'
    style.pointerEvents = 'none'

    style.width = this.renderCanvas.width = this.computerCanvas.width = this.globalWidth
    style.height = this.renderCanvas.height = this.computerCanvas.height = this.globalHeight

    document.body.append(this.renderCanvas)

    window.addEventListener('mousedown', this.handleMouseDown.bind(this))
    window.addEventListener('pagehide', this.handlePageHide.bind(this))
    }

    run() {
    this.running = true
    if (this.booms.length == 0) {
    return this.running = false
    }

    requestAnimationFrame(this.run.bind(this))

    this.computerContext.clearRect(0, 0, this.globalWidth, this.globalHeight)
    this.renderContext.clearRect(0, 0, this.globalWidth, this.globalHeight)

    this.booms.forEach((boom, index) => {
    if (boom.stop) {
    return this.booms.splice(index, 1)
    }
    boom.move()
    boom.draw()
    })
    this.renderContext.drawImage(this.computerCanvas, 0, 0, this.globalWidth, this.globalHeight)
    }
    }

    const cursorSpecialEffects = new CursorSpecialEffects()
    cursorSpecialEffects.init()
  5. 侧栏的固定

    使用affix实现,主要参考这篇文章

  6. valine评论系统支持pjax

    参考这个issue


害,换个主题真的太难了,一年之内不打算再换了!

好了,写完去睡觉啦 XD!


2020.1.30 23:12:33

全站由github迁移到coding,国内浏览速度得到大幅提升。(香港服务器就是香啊!)