用 canvas 绘制 aether

banner

将 aether 放入 next 的 sidebar 中

初学 hexo , 使用 next 的 Mist 主题

aether 转自 codepen

感谢 Sean Free

步骤

源码添加到 swig 模板中

添加所引用到的 js 库

<script src='https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.4.0/simplex-noise.min.js'></script>

在 sidebar.swig 中添加 aether 开关

{% if theme.aether.enable %}
    {% if theme.custom_file_path.aether %}
        {% set custom_aether= '../../../../' + theme.custom_file_path.aether %}
    {% else %}
        {% set custom_aether = '../_custom/aether.swig' %}
    {% endif %}
    <div id="aether">
        {% include custom_aether %}
    </div>
{% endif %}

修改 aether.swig

修改 appendChild 节点

aether.appendChild(canvas.b);

修改画布计算对象

let { innerWidth, innerHeight } = window;
innerWidth = 320;

修改绘制中心

center[0] = 0.5 * innerWidth;
center[1] = 0.8 * innerHeight;

在 custom.styl 中添加自定义样式

#aether {
  position: absolute;
  padding: 0;
  color: $grey-dark;
  text-align: center;
  width: 100%;
  height: 100%;
  z-index: -1;
  bottom: 0
}

预览过程中发现打开关闭 sidebar 时有色差

解决方案1 修改 sidebar 配色(不想改成纯黑)

解决方案2 修改 aether 画布颜色

经过阅读源码发现aether的绘制方式是叠加

ctx.b.fillStyle = 'rgba(0,0,0,0.1)';
ctx.b.fillRect(0,0,canvas.b.width,canvas.b.height);
......
ctx.b.save();
ctx.b.filter = 'blur(8px)';
ctx.b.globalCompositeOperation = 'lighten';
ctx.b.drawImage(canvas.a, 0, 0);
ctx.b.restore();

ctx.b.save();
ctx.b.globalCompositeOperation = 'lighter';
ctx.b.drawImage(canvas.a, 0, 0);
ctx.b.restore();

叠加的背景色需 rgb(0,0,0) , 否则会出现光晕轨迹 , 如果取消叠加效果 , 仅显示粒子 , 与作者原效果不符

仅显示粒子效果代码修改

ctx.b.fillStyle = 'rgba(34,34,34,0)'; 

所以修改画布方式无法实现 , 决定在上层添加透明遮罩层

let div = document.createElement("div")
div.style = `
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: #fff;
    opacity: 0.12;
`;
aether.appendChild(div)

aether.appendChild(canvas.b); 之后添加一个div节点 , 用作遮罩层

sidebar 的动画看起来有点突兀 , 将 aether 加入 sidebar 动画效果中

motion.js
showSidebar: 
$('.sidebar #aether').velocity(
    'transition.slideRightIn',
    {
        stagger : 50,
        drag    : true,
        complete: function() {
            self.sidebarEl.trigger('sidebar.motion.complete');
        }
    }
);
hideSidebar: 
this.sidebarEl.find('#aether').velocity('stop').css('display', 'none');

大功告成