【Hexo】全面改造属于你的个性化博客

3,056 阅读6分钟

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战

关于Hexo的一切 —— 我的Hexo专栏

零 前言

继上篇内容搭建博客教程, 本文将讲述一些博客主题的美化、实用功能的添加。

比如添加评论系统百度统计雪花飘落,添加live2d看板娘,鼠标点击显示字体效果,烟花爆炸效果等等等等……

提示:不同主题的添加方法可能有些不同,相同主题的不同版本配置方法也可能有所差异。

个性化还是需要一定的前端基础,了解 HTML、CSS、JS,了解 CSS 预处理语言 Sass、Less,搞懂Hexo的文件目录结构。

不过只要我们选好主题,认真阅读主题文档,大概了解每个文件是对应网页哪个部分的,然后认真阅读本篇教程,相信你一定可以的💪🏻💪🏻

一 添加live2d看板娘

项目地址:EYHN/hexo-helper-live2d: Add the Sseexxyyy live2d to your hexo! (github.com)

  1. 在右下角添加一个萌萌的看板娘,命令行输入 npm install --save hexo-helper-live2d 获取插件。

  2. 输入 npm install [name] 即可下载相应的模型,将 [name] 更换成模型名称即可,更多模型选择点击获取,各个模型的预览请访问原作者的博客

  3. 打开站点目录下的 _config.yml 文件,添加如下代码:

     live2d:
       enable: true
       scriptFrom: local
       model:
         use: live2d-widget-model-haruto # 模型选择
       display:
         position: right     # 模型位置
         width: 150          # 模型宽度
         height: 300         # 模型高度
       mobile:
         show: false         # 是否在手机端显示
    
  4. 设置好后我们就拥有了一个小可爱😇 image-20210818201518784

二 添加鼠标点击效果

爱心效果

  1. themes/你选择的主题/source/js 下新建文件 heart.js ,添加:

    !(function (e, t, a) {
      function n() {
        c(
          ".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 500%;-moz-border-radius: 50%;position: fixed;}.heart:after{top: -5px;}.heart:before{left: -5px;}"
        ),
          o(),
          r();
      }
      function r() {
        for (var e = 0; e < d.length; e++)
          d[e].alpha <= 0
            ? (t.body.removeChild(d[e].el), d.splice(e, 1))
            : (d[e].y--,
              (d[e].scale += 0.004),
              (d[e].alpha -= 0.013),
              (d[e].el.style.cssText =
                "left:" +
                d[e].x +
                "px;top:" +
                d[e].y +
                "px;opacity:" +
                d[e].alpha +
                ";transform:scale(" +
                d[e].scale +
                "," +
                d[e].scale +
                ") rotate(45deg);background:" +
                d[e].color +
                ";z-index:99999"));
        requestAnimationFrame(r);
      }
      function o() {
        var t = "function" == typeof e.onclick && e.onclick;
        e.onclick = function (e) {
          t && t(), i(e);
        };
      }
      function i(e) {
        var a = t.createElement("div");
        (a.className = "heart"),
          d.push({
            el: a,
            x: e.clientX - 5,
            y: e.clientY - 5,
            scale: 1,
            alpha: 1,
            color: s(),
          }),
          t.body.appendChild(a);
      }
      function c(e) {
        var a = t.createElement("style");
        a.type = "text/css";
        try {
          a.appendChild(t.createTextNode(e));
        } catch (t) {
          a.styleSheet.cssText = e;
        }
        t.getElementsByTagName("head")[0].appendChild(a);
      }
      function s() {
        return (
          "rgb(" +
          ~~(255 * Math.random()) +
          "," +
          ~~(255 * Math.random()) +
          "," +
          ~~(255 * Math.random()) +
          ")"
        );
      }
      var d = [];
      (e.requestAnimationFrame = (function () {
        return (
          e.requestAnimationFrame ||
          e.webkitRequestAnimationFrame ||
          e.mozRequestAnimationFrame ||
          e.oRequestAnimationFrame ||
          e.msRequestAnimationFrame ||
          function (e) {
            setTimeout(e, 1e3 / 60);
          }
        );
      })()),
        n();
    })(window, document);
    
    
  2. themes/你选择的主题/layout/layout.ejs下添加:

    <!-- 页面点击小红心 -->
    <script type="text/javascript" src="/js/heart.js"></script>
    
  3. 完成以上,当我们点击鼠标就可以看见爱心的特效了

    image-20210818205905348

文字效果

  1. themes/你选择的主题/source/js下新建文件show_text.js,添加:

    var a_idx = 0;
    jQuery(document).ready(function($) {
        $("body").click(function(e) {
            var a = new Array
            ("富强", "民主", "文明", "和谐", "自由", "平等", "公正", "法治", "爱国", "敬业", "诚信", "友善");
            var $i = $("<span/>").text(a[a_idx]);
            a_idx = (a_idx + 1) % a.length;
            var x = e.pageX,
            y = e.pageY;
            $i.css({
                "z-index": 5,
                "top": y - 20,
                "left": x,
                "position": "absolute",
                "font-weight": "bold",
                "color": "#FF0000"		// 修改颜色处
            });
          
            $("body").append($i);
            $i.animate({
                "top": y - 180,
                "opacity": 0
            },
          3000,
          function() {
              $i.remove();
          });
        });
        setTimeout('delay()', 2000);
    });
    
    function delay() {
        $(".buryit").removeAttr("onclick");
    }
    
  2. 社会主义核心价值观可以更换为其他的文字,想要每次点击显示不同颜色需要修改其中 color 的值:

    "color": "rgb(" + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + ")"
    
  3. themes/你选择的主题/layout/layout.ejs 下添加:

    <!--单击显示文字-->
    <script type="text/javascript" src="/js/show_text.js"></script>
    

烟花爆炸效果

  1. themes/你选择的主题/source/js 下新建文件 firework.js ,添加:

    "use strict";
    function updateCoords(e) {
      (pointerX =
        (e.clientX || e.touches[0].clientX) -
        canvasEl.getBoundingClientRect().left),
        (pointerY =
          e.clientY || e.touches[0].clientY - canvasEl.getBoundingClientRect().top);
    }
    function setParticuleDirection(e) {
      var t = (anime.random(0, 360) * Math.PI) / 180,
        a = anime.random(50, 180),
        n = [-1, 1][anime.random(0, 1)] * a;
      return { x: e.x + n * Math.cos(t), y: e.y + n * Math.sin(t) };
    }
    function createParticule(e, t) {
      var a = {};
      return (
        (a.x = e),
        (a.y = t),
        (a.color = colors[anime.random(0, colors.length - 1)]),
        (a.radius = anime.random(16, 32)),
        (a.endPos = setParticuleDirection(a)),
        (a.draw = function () {
          ctx.beginPath(),
            ctx.arc(a.x, a.y, a.radius, 0, 2 * Math.PI, !0),
            (ctx.fillStyle = a.color),
            ctx.fill();
        }),
        a
      );
    }
    function createCircle(e, t) {
      var a = {};
      return (
        (a.x = e),
        (a.y = t),
        (a.color = "#F00"),
        (a.radius = 0.1),
        (a.alpha = 0.5),
        (a.lineWidth = 6),
        (a.draw = function () {
          (ctx.globalAlpha = a.alpha),
            ctx.beginPath(),
            ctx.arc(a.x, a.y, a.radius, 0, 2 * Math.PI, !0),
            (ctx.lineWidth = a.lineWidth),
            (ctx.strokeStyle = a.color),
            ctx.stroke(),
            (ctx.globalAlpha = 1);
        }),
        a
      );
    }
    function renderParticule(e) {
      for (var t = 0; t < e.animatables.length; t++) {
        e.animatables[t].target.draw();
      }
    }
    function animateParticules(e, t) {
      for (var a = createCircle(e, t), n = [], i = 0; i < numberOfParticules; i++) {
        n.push(createParticule(e, t));
      }
      anime
        .timeline()
        .add({
          targets: n,
          x: function (e) {
            return e.endPos.x;
          },
          y: function (e) {
            return e.endPos.y;
          },
          radius: 0.1,
          duration: anime.random(1200, 1800),
          easing: "easeOutExpo",
          update: renderParticule,
        })
        .add({
          targets: a,
          radius: anime.random(80, 160),
          lineWidth: 0,
          alpha: { value: 0, easing: "linear", duration: anime.random(600, 800) },
          duration: anime.random(1200, 1800),
          easing: "easeOutExpo",
          update: renderParticule,
          offset: 0,
        });
    }
    function debounce(e, t) {
      var a;
      return function () {
        var n = this,
          i = arguments;
        clearTimeout(a),
          (a = setTimeout(function () {
            e.apply(n, i);
          }, t));
      };
    }
    var canvasEl = document.querySelector(".fireworks");
    if (canvasEl) {
      var ctx = canvasEl.getContext("2d"),
        numberOfParticules = 30,
        pointerX = 0,
        pointerY = 0,
        tap = "mousedown",
        colors = ["#FF1461", "#18FF92", "#5A87FF", "#FBF38C"],
        setCanvasSize = debounce(function () {
          (canvasEl.width = 2 * window.innerWidth),
            (canvasEl.height = 2 * window.innerHeight),
            (canvasEl.style.width = window.innerWidth + "px"),
            (canvasEl.style.height = window.innerHeight + "px"),
            canvasEl.getContext("2d").scale(2, 2);
        }, 500),
        render = anime({
          duration: 1 / 0,
          update: function () {
            ctx.clearRect(0, 0, canvasEl.width, canvasEl.height);
          },
        });
      document.addEventListener(
        tap,
        function (e) {
          "sidebar" !== e.target.id &&
            "toggle-sidebar" !== e.target.id &&
            "A" !== e.target.nodeName &&
            "IMG" !== e.target.nodeName &&
            (render.play(), updateCoords(e), animateParticules(pointerX, pointerY));
        },
        !1
      ),
        setCanvasSize(),
        window.addEventListener("resize", setCanvasSize, !1);
    }
    ("use strict");
    function updateCoords(e) {
      (pointerX =
        (e.clientX || e.touches[0].clientX) -
        canvasEl.getBoundingClientRect().left),
        (pointerY =
          e.clientY || e.touches[0].clientY - canvasEl.getBoundingClientRect().top);
    }
    function setParticuleDirection(e) {
      var t = (anime.random(0, 360) * Math.PI) / 180,
        a = anime.random(50, 180),
        n = [-1, 1][anime.random(0, 1)] * a;
      return { x: e.x + n * Math.cos(t), y: e.y + n * Math.sin(t) };
    }
    function createParticule(e, t) {
      var a = {};
      return (
        (a.x = e),
        (a.y = t),
        (a.color = colors[anime.random(0, colors.length - 1)]),
        (a.radius = anime.random(16, 32)),
        (a.endPos = setParticuleDirection(a)),
        (a.draw = function () {
          ctx.beginPath(),
            ctx.arc(a.x, a.y, a.radius, 0, 2 * Math.PI, !0),
            (ctx.fillStyle = a.color),
            ctx.fill();
        }),
        a
      );
    }
    function createCircle(e, t) {
      var a = {};
      return (
        (a.x = e),
        (a.y = t),
        (a.color = "#F00"),
        (a.radius = 0.1),
        (a.alpha = 0.5),
        (a.lineWidth = 6),
        (a.draw = function () {
          (ctx.globalAlpha = a.alpha),
            ctx.beginPath(),
            ctx.arc(a.x, a.y, a.radius, 0, 2 * Math.PI, !0),
            (ctx.lineWidth = a.lineWidth),
            (ctx.strokeStyle = a.color),
            ctx.stroke(),
            (ctx.globalAlpha = 1);
        }),
        a
      );
    }
    function renderParticule(e) {
      for (var t = 0; t < e.animatables.length; t++) {
        e.animatables[t].target.draw();
      }
    }
    function animateParticules(e, t) {
      for (var a = createCircle(e, t), n = [], i = 0; i < numberOfParticules; i++) {
        n.push(createParticule(e, t));
      }
      anime
        .timeline()
        .add({
          targets: n,
          x: function (e) {
            return e.endPos.x;
          },
          y: function (e) {
            return e.endPos.y;
          },
          radius: 0.1,
          duration: anime.random(1200, 1800),
          easing: "easeOutExpo",
          update: renderParticule,
        })
        .add({
          targets: a,
          radius: anime.random(80, 160),
          lineWidth: 0,
          alpha: { value: 0, easing: "linear", duration: anime.random(600, 800) },
          duration: anime.random(1200, 1800),
          easing: "easeOutExpo",
          update: renderParticule,
          offset: 0,
        });
    }
    function debounce(e, t) {
      var a;
      return function () {
        var n = this,
          i = arguments;
        clearTimeout(a),
          (a = setTimeout(function () {
            e.apply(n, i);
          }, t));
      };
    }
    var canvasEl = document.querySelector(".fireworks");
    if (canvasEl) {
      var ctx = canvasEl.getContext("2d"),
        numberOfParticules = 30,
        pointerX = 0,
        pointerY = 0,
        tap = "mousedown",
        colors = ["#FF1461", "#18FF92", "#5A87FF", "#FBF38C"],
        setCanvasSize = debounce(function () {
          (canvasEl.width = 2 * window.innerWidth),
            (canvasEl.height = 2 * window.innerHeight),
            (canvasEl.style.width = window.innerWidth + "px"),
            (canvasEl.style.height = window.innerHeight + "px"),
            canvasEl.getContext("2d").scale(2, 2);
        }, 500),
        render = anime({
          duration: 1 / 0,
          update: function () {
            ctx.clearRect(0, 0, canvasEl.width, canvasEl.height);
          },
        });
      document.addEventListener(
        tap,
        function (e) {
          "sidebar" !== e.target.id &&
            "toggle-sidebar" !== e.target.id &&
            "A" !== e.target.nodeName &&
            "IMG" !== e.target.nodeName &&
            (render.play(), updateCoords(e), animateParticules(pointerX, pointerY));
        },
        !1
      ),
        setCanvasSize(),
        window.addEventListener("resize", setCanvasSize, !1);
    }
    
  2. themes/你选择的主题/layout/layout.ejs 下添加:

    <canvas class="fireworks" style="position: fixed;left: 0;top: 0;z-index: 1; pointer-events: none;" ></canvas> 
    <script type="text/javascript" src="//cdn.bootcss.com/animejs/2.2.0/anime.min.js"></script> 
    <script type="text/javascript" src="/js/firework.js"></script>
    
  3. 效果如下

    image-20210818210757509

三 添加网站运行时间

  1. 记录网站运行时间在页脚显示,所以在 themes/你选择的主题/layout/_partial/footer.ejs 下添加:

    <span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span>
    <script>
        var now = new Date();
        function createtime() {
            var grt = new Date("08/10/2018 17:38:00"); //在此处修改你的建站时间
            now.setTime(now.getTime() + 250);
            days = (now - grt) / 1000 / 60 / 60 / 24;
            dnum = Math.floor(days);
            hours = (now - grt) / 1000 / 60 / 60 - 24 * dnum;
            hnum = Math.floor(hours);
            if (String(hnum).length == 1) {
                hnum = "0" + hnum;
            }
            minutes = (now - grt) / 1000 / 60 - 24 * 60 * dnum - 60 * hnum;
            mnum = Math.floor(minutes);
            if (String(mnum).length == 1) {
                mnum = "0" + mnum;
            }
            seconds = (now - grt) / 1000 - 24 * 60 * 60 * dnum - 60 * 60 * hnum - 60 * mnum;
            snum = Math.round(seconds);
            if (String(snum).length == 1) {
                snum = "0" + snum;
            }
            document.getElementById("timeDate").innerHTML =
                "本站已运行 " + dnum + " 天 ";
            document.getElementById("times").innerHTML =
                hnum + " 小时 " + mnum + " 分 " + snum + " 秒";
        }
        setInterval("createtime()", 250);
    </script>
    
  2. 效果如下:

    image-20210818211602854

四 添加浏览器标题恶搞

  1. 在用户切换标签页的时候,更改浏览器标题呼唤用户回归,在 themes/你选择的主题/source/js 下新建文件 funny.js ,添加:

    var OriginTitle = document.title;
    var titleTime;
    document.addEventListener('visibilitychange', function () {
        if (document.hidden) {
            $('[rel="icon"]').attr('href', "/funny.ico");
            document.title = '╭(°A°`)╮ 页面崩溃啦 ~';
            clearTimeout(titleTime);
        }
        else {
            $('[rel="icon"]').attr('href', "/favicon.ico");
            document.title = '(ฅ>ω<*ฅ) 噫又好啦 ~' + OriginTitle;
            titleTime = setTimeout(function () {
                document.title = OriginTitle;
            }, 2000);
        }
    });
    
  2. 其中的 favicon.ico 为正常显示图标,funny.ico 为用户切换后的图标,需要你自己设置🙈

五 添加动态诗词

  1. 采用的是今日诗词,每次返回一句诗词,根据时间、地点、天气、事件智能推荐。官网 API 文档,在 themes/你选择的主题/layout/_partial/head.ejs 添加下面的一行代码:

    <script src="https://sdk.jinrishici.com/v2/browser/jinrishici.js" charset="utf-8"></script>
    
  2. 如果不成功,请将主题配置文件subtitle的值为false🙈

六 添加动态科技线条背景

  1. themes/你选择的主题/layout/layout.ejs文件中添加:

    <!--动态线条背景-->
    <script type="text/javascript"
    color="122 103 238" opacity='0.7' zIndex="-2" count="200" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js">
    </script>
    
  2. color表示线条颜色,opactity表示线条透明度,count表示线条总数量,都可自己修改~

七 添加雪花飘落效果

  1. themes/你选择的主题/source/js下新建文件snow.js,添加:

    (function($){
    	$.fn.snow = function(options){
    	var $flake = $('<div id="snowbox" />').css({'position': 'absolute','z-index':'9999', 'top': '-50px'}).html('&#10052;'),
    	documentHeight 	= $(document).height(),
    	documentWidth	= $(document).width(),
    	defaults = {
    		minSize		: 10,
    		maxSize		: 20,
    		newOn		: 1000,
    		flakeColor	: "#AFDAEF" /* 此处可以定义雪花颜色,若要白色可以改为#FFFFFF */
    	},
    	options	= $.extend({}, defaults, options);
    	var interval= setInterval( function(){
    	var startPositionLeft = Math.random() * documentWidth - 100,
    	startOpacity = 0.5 + Math.random(),
    	sizeFlake = options.minSize + Math.random() * options.maxSize,
    	endPositionTop = documentHeight - 200,
    	endPositionLeft = startPositionLeft - 500 + Math.random() * 500,
    	durationFall = documentHeight * 10 + Math.random() * 5000;
    	$flake.clone().appendTo('body').css({
    		left: startPositionLeft,
    		opacity: startOpacity,
    		'font-size': sizeFlake,
    		color: options.flakeColor
    	}).animate({
    		top: endPositionTop,
    		left: endPositionLeft,
    		opacity: 0.2
    	},durationFall,'linear',function(){
    		$(this).remove()
    	});
    	}, options.newOn);
        };
    })(jQuery);
    $(function(){
        $.fn.snow({ 
    	    minSize: 5, 	// 定义雪花最小尺寸 
    	    maxSize: 50,	// 定义雪花最大尺寸 
    	    newOn: 300  	// 定义密集程度,数字越小越密集 
        });
    });
    
  2. themes/你选择的主题/layout/layout.ejs下添加:

    <script src="/js/snow.js"></script>
    

八 添加评论系统

来必力

官网地址:来必力 (livere.com)

  1. 点击导航栏的安装,选择免费版本,注册填写网站信息,填写完成后会给你一段代码把uid复制下来:

    image-20210818214425206

  2. 在主题配置下修改:

    # Livere comment configuration, the default is not activated
    # Livere 来必力评论模块的配置,默认为不激活
    livere:
      enable: true   	# true为开启评论系统
      uid: 		# 这里填写上一步获取的uid
    

Valine

官网地址:介绍 | Valine 一款快速、简洁且高效的无后端评论系统。

  1. 注册并登录LeanCloud,创建应用并在设置页面找到应用Keys,复制其中的APPIDAPPKEY

    image-20210818214854104

  2. 修改主题配置文件:

    # The configuration of the Valine comment module is not activated by default.
    # To use it, activate the configuration item and set appId and appKey.
    # Valine 评论模块的配置,默认为不激活,如要使用,就请激活该配置项,并设置 appId 和 appKey.
    valine:
      enable: false  	# true即为开启评论系统
      appId:   			# 此处填写你的appid
      appKey:  			# 此处填写你的appkey
      notify: false
      verify: false
      visitor: true
      avatar: 'mm' 
      pageSize: 10
      placeholder: 'test test' 	# Comment Box placeholder
      background:  # 设置评论区背景图
    

九 添加百度统计

官网地址:百度统计——领先的中文网站分析平台 (baidu.com)

  1. 注册登陆后,在管理界面网站列表添加自己的网站地址

  2. 接着点击代码获取,复制该代码

    image-20210818215422699

  3. 接着在themes/你选择的主题/layout/_partial下新建文件 baidu-analytics.ejs,里面粘贴你刚复制的代码~

  4. 修改主题文件夹下的配置文件baidu_analytic:,将你的key(图中马赛克部分)填进去即可。

十 添加各种网页小挂件

  • abowman.com/ 里面有很多有趣的小挂件,可以养养鱼、龟、狗、仓鼠等各式各样的虚拟宠物,直接复制代码就可以用。
  • www.revolvermaps.com/ 它提供网站访客地理信息,可以以2D、3D等形式显示。
  • www.amazingcounters.com/ 免费网站计数器,有非常多的样式供你选。
  • www.seniverse.com/widget/get 心知天气提供基于Web的免费天气插件,可以为你的网站添加一项简洁美观的天气预报功能,并自动适配PC和手机上的浏览。

最后的主题推荐


真的写了很长时间,xdm点个赞呗😆

这两天内会更新博客的域名绑定和SEO优化~ 欢迎关注交流

更多有趣文章:Mancuoj 的个人主页