Hexo+Icarus3+live2d给博客添加看板娘

补坑

之前写过一篇icarus添加看板娘的教程但是版本是

icarus3之前的教程博客 传送门

上一篇博客那时候拉的live2D还需要导入jQuery 2020年1月1日起,项目不再依赖于 jQuery。

这次我把live2d直接放到了主题文件夹下的source下面 跟js/css/img同级

下载live2D

进入博客根目录

cd theme/icarus/source && git clone https://github.com/stevenjoezhang/live2d-widget.git

修改配置

1. 导入css依赖

找到theme/icarus/layout/common/head.jsx 插入css依赖

大概是在一百四十多行的样子吧 或者可以在head.jsx内搜索标签 然后插入这行


修改后完整的head.jsx

const { Component } = require('inferno');
const MetaTags = require('hexo-component-inferno/lib/view/misc/meta');
const OpenGraph = require('hexo-component-inferno/lib/view/misc/open_graph');
const StructuredData = require('hexo-component-inferno/lib/view/misc/structured_data');
const Plugins = require('./plugins');

function getPageTitle(page, siteTitle, helper) {
    let title = page.title;

    if (helper.is_archive()) {
        title = helper._p('common.archive', Infinity);
        if (helper.is_month()) {
            title += ': ' + page.year + '/' + page.month;
        } else if (helper.is_year()) {
            title += ': ' + page.year;
        }
    } else if (helper.is_category()) {
        title = helper._p('common.category', 1) + ': ' + page.category;
    } else if (helper.is_tag()) {
        title = helper._p('common.tag', 1) + ': ' + page.tag;
    } else if (helper.is_categories()) {
        title = helper._p('common.category', Infinity);
    } else if (helper.is_tags()) {
        title = helper._p('common.tag', Infinity);
    }

    return [title, siteTitle].filter(str => typeof str !== 'undefined' && str.trim() !== '').join(' - ');
}

module.exports = class extends Component {
    render() {
        const { env, site, config, helper, page } = this.props;
        const { url_for, cdn, fontcdn, iconcdn, is_post } = helper;
        const {
            url,
            meta_generator = true,
            head = {},
            article,
            highlight,
            variant = 'default'
        } = config;
        const {
            meta = [],
            open_graph = {},
            structured_data = {},
            canonical_url = page.permalink,
            rss,
            favicon
        } = head;

        const language = page.lang || page.language || config.language;
        const fontCssUrl = {
            default: fontcdn('Ubuntu:wght@400;600&family=Source+Code+Pro', 'css2'),
            cyberpunk: fontcdn('Oxanium:wght@300;400;600&family=Roboto+Mono', 'css2')
        };

        let hlTheme, images;
        if (highlight && highlight.enable === false) {
            hlTheme = null;
        } else if (article && article.highlight && article.highlight.theme) {
            hlTheme = article.highlight.theme;
        } else {
            hlTheme = 'atom-one-light';
        }

        if (typeof page.og_image === 'string') {
            images = [page.og_image];
        } else if (helper.has_thumbnail(page)) {
            images = [helper.get_thumbnail(page)];
        } else if (article && typeof article.og_image === 'string') {
            images = [article.og_image];
        } else if (page.content && page.content.includes(']*src=['"]([^'"]+)([^>]*>)/gi;
            while ((img = imgPattern.exec(page.content)) !== null) {
                images.push(img[1]);
            }
        } else {
            images = [url_for('/img/og_image.png')];
        }

        let adsenseClientId = null;
        if (Array.isArray(config.widgets)) {
            const widget = config.widgets.find(widget => widget.type === 'adsense');
            if (widget) {
                adsenseClientId = widget.client_id;
            }
        }

        let openGraphImages = images;
        if ((typeof open_graph === 'object' && open_graph !== null)
            && ((Array.isArray(open_graph.image) && open_graph.image.length > 0) || typeof open_graph.image === 'string')) {
            openGraphImages = open_graph.image;
        } else if ((Array.isArray(page.photos) && page.photos.length > 0) || typeof page.photos === 'string') {
            openGraphImages = page.photos;
        }

        let structuredImages = images;
        if ((typeof structured_data === 'object' && structured_data !== null)
            && ((Array.isArray(structured_data.image) && structured_data.image.length > 0) || typeof structured_data.image === 'string')) {
            structuredImages = structured_data.image;
        } else if ((Array.isArray(page.photos) && page.photos.length > 0) || typeof page.photos === 'string') {
            structuredImages = page.photos;
        }

        return 
            
            {meta_generator ?  : null}
            
            {meta && meta.length ?  : null}
            
            
            {getPageTitle(page, config.title, helper)}

            {typeof open_graph === 'object' && open_graph !== null ?  : null}

            {typeof structured_data === 'object' && structured_data !== null ?  : null}

            {canonical_url ?  : null}
            {rss ?  : null}
            {favicon ?  : null}
            
            {hlTheme ?  : null}
            
            
            {/* 这行是live2d需要的css依赖 */}
            
            

            {adsenseClientId ?  : null}
        ;
    }
};

2. 修改刚下载的live2d-widget 下的autoload.js

注释掉第二行 //const live2d_path = "https://cdn.jsdelivr.net/gh/stevenjoezhang/live2d-widget@latest/";

放开第三行 const live2d_path = "/live2d-widget/";

修改后的autoload.js

// 注意:live2d_path 参数应使用绝对路径
//const live2d_path = "https://cdn.jsdelivr.net/gh/stevenjoezhang/live2d-widget@latest/";
const live2d_path = "/live2d-widget/";

// 封装异步加载资源的方法
function loadExternalResource(url, type) {
    return new Promise((resolve, reject) => {
        let tag;

        if (type === "css") {
            tag = document.createElement("link");
            tag.rel = "stylesheet";
            tag.href = url;
        }
        else if (type === "js") {
            tag = document.createElement("script");
            tag.src = url;
        }
        if (tag) {
            tag.onload = () => resolve(url);
            tag.onerror = () => reject(url);
            document.head.appendChild(tag);
        }
    });
}

// 加载 waifu.css live2d.min.js waifu-tips.js
if (screen.width >= 768) {
    Promise.all([
        loadExternalResource(live2d_path + "waifu.css", "css"),
        loadExternalResource(live2d_path + "live2d.min.js", "js"),
        loadExternalResource(live2d_path + "waifu-tips.js", "js")
    ]).then(() => {
        initWidget({
            waifuPath: live2d_path + "waifu-tips.json",
            //apiPath: "https://live2d.fghrsh.net/api/",
            cdnPath: "https://cdn.jsdelivr.net/gh/fghrsh/live2d_api/"
            //cdnPath: "https://live2d.fghrsh.net/api/"
        });
    });
}
// initWidget 第一个参数为 waifu-tips.json 的路径,第二个参数为 API 地址
// API 后端可自行搭建,参考 https://github.com/fghrsh/live2d_api
// 初始化看板娘会自动加载指定目录下的 waifu-tips.json
3. 在主题内导入autoload.js

前提是 live2d-widget 的位置在theme/icarus/source

找到theme/icarus/layout/common/scripts.jsx 在末尾处 标签内添加


添加后完整的scripts.jsx

const {Component, Fragment} = require('inferno');
const Plugins = require('./plugins');

module.exports = class extends Component {
    render() {
        const {site, config, helper, page} = this.props;
        const {url_for, cdn} = helper;
        const {external_link, article} = config;
        const language = page.lang || page.language || config.language || 'en';

        let externalLink;
        if (typeof external_link === 'boolean') {
            externalLink = {enable: external_link, exclude: []};
        } else {
            externalLink = {
                enable: typeof external_link.enable === 'boolean' ? external_link.enable : true,
                exclude: external_link.exclude || []
            };
        }

        let fold = 'unfolded';
        let clipboard = true;
        if (article && article.highlight) {
            if (typeof article.highlight.clipboard !== 'undefined') {
                clipboard = !!article.highlight.clipboard;
            }
            if (typeof article.highlight.fold === 'string') {
                fold = article.highlight.fold;
            }
        }

        const embeddedConfig = `var IcarusThemeSettings = {
            site: {
                url: '${config.url}',
                external_link: ${JSON.stringify(externalLink)}
            },
            article: {
                highlight: {
                    clipboard: ${clipboard},
                    fold: '${fold}'
                }
            }
        };`;

        return 
            
            
            
            
            {clipboard ?  : null}
            
            
            
        ;
    }
};

4. 开启live2d

编辑主题配置文件_config.yml 添加

live2d:
  enable: true

大功告成!

备注

看板娘到这儿应该就可以出来了 但是会发现在icarus的样式下面 这时候需要把看板娘给置顶

找到live2d-widget 下的waifu.css 修改33行 id为#waifu的样式 把z-index:1 修改为z-index:1000;

修改后的waifu.css

#waifu-toggle {
    background-color: #fa0;
    border-radius: 5px;
    bottom: 66px;
    color: #fff;
    cursor: pointer;
    font-size: 12px;
    left: 0;
    margin-left: -100px;
    padding: 5px 2px 5px 5px;
    position: fixed;
    transition: margin-left 1s;
    width: 60px;
    writing-mode: vertical-rl;
}

#waifu-toggle.waifu-toggle-active {
    margin-left: -50px;
}

#waifu-toggle.waifu-toggle-active:hover {
    margin-left: -30px;
}

#waifu {
    bottom: -1000px;
    left: 0;
    line-height: 0;
    margin-bottom: -10px;
    position: fixed;
    transform: translateY(3px);
    transition: transform .3s ease-in-out, bottom 3s ease-in-out;
    z-index: 1000;
}

#waifu:hover {
    transform: translateY(0);
}

#waifu-tips {
    animation: shake 50s ease-in-out 5s infinite;
    background-color: rgba(236, 217, 188, .5);
    border: 1px solid rgba(224, 186, 140, .62);
    border-radius: 12px;
    box-shadow: 0 3px 15px 2px rgba(191, 158, 118, .2);
    font-size: 14px;
    line-height: 24px;
    margin: -30px 20px;
    min-height: 70px;
    opacity: 0;
    overflow: hidden;
    padding: 5px 10px;
    position: absolute;
    text-overflow: ellipsis;
    transition: opacity 1s;
    width: 250px;
    word-break: break-all;
}

#waifu-tips.waifu-tips-active {
    opacity: 1;
    transition: opacity .2s;
}

#waifu-tips span {
    color: #0099cc;
}

#waifu #live2d {
    cursor: grab;
    height: 280px;
    position: relative;
    width: 280px;
}

#waifu #live2d:active {
    cursor: grabbing;
}

#waifu-tool {
    color: #aaa;
    opacity: 0;
    position: absolute;
    right: -10px;
    top: 70px;
    transition: opacity 1s;
}

#waifu:hover #waifu-tool {
    opacity: 1;
}

#waifu-tool span {
    color: #7b8c9d;
    cursor: pointer;
    display: block;
    line-height: 30px;
    text-align: center;
    transition: color .3s;
}

#waifu-tool span:hover {
    color: #0684bd; /* #34495e */
}

@keyframes shake {
    2% {
        transform: translate(.5px, -1.5px) rotate(-.5deg);
    }

    4% {
        transform: translate(.5px, 1.5px) rotate(1.5deg);
    }

    6% {
        transform: translate(1.5px, 1.5px) rotate(1.5deg);
    }

    8% {
        transform: translate(2.5px, 1.5px) rotate(.5deg);
    }

    10% {
        transform: translate(.5px, 2.5px) rotate(.5deg);
    }

    12% {
        transform: translate(1.5px, 1.5px) rotate(.5deg);
    }

    14% {
        transform: translate(.5px, .5px) rotate(.5deg);
    }

    16% {
        transform: translate(-1.5px, -.5px) rotate(1.5deg);
    }

    18% {
        transform: translate(.5px, .5px) rotate(1.5deg);
    }

    20% {
        transform: translate(2.5px, 2.5px) rotate(1.5deg);
    }

    22% {
        transform: translate(.5px, -1.5px) rotate(1.5deg);
    }

    24% {
        transform: translate(-1.5px, 1.5px) rotate(-.5deg);
    }

    26% {
        transform: translate(1.5px, .5px) rotate(1.5deg);
    }

    28% {
        transform: translate(-.5px, -.5px) rotate(-.5deg);
    }

    30% {
        transform: translate(1.5px, -.5px) rotate(-.5deg);
    }

    32% {
        transform: translate(2.5px, -1.5px) rotate(1.5deg);
    }

    34% {
        transform: translate(2.5px, 2.5px) rotate(-.5deg);
    }

    36% {
        transform: translate(.5px, -1.5px) rotate(.5deg);
    }

    38% {
        transform: translate(2.5px, -.5px) rotate(-.5deg);
    }

    40% {
        transform: translate(-.5px, 2.5px) rotate(.5deg);
    }

    42% {
        transform: translate(-1.5px, 2.5px) rotate(.5deg);
    }

    44% {
        transform: translate(-1.5px, 1.5px) rotate(.5deg);
    }

    46% {
        transform: translate(1.5px, -.5px) rotate(-.5deg);
    }

    48% {
        transform: translate(2.5px, -.5px) rotate(.5deg);
    }

    50% {
        transform: translate(-1.5px, 1.5px) rotate(.5deg);
    }

    52% {
        transform: translate(-.5px, 1.5px) rotate(.5deg);
    }

    54% {
        transform: translate(-1.5px, 1.5px) rotate(.5deg);
    }

    56% {
        transform: translate(.5px, 2.5px) rotate(1.5deg);
    }

    58% {
        transform: translate(2.5px, 2.5px) rotate(.5deg);
    }

    60% {
        transform: translate(2.5px, -1.5px) rotate(1.5deg);
    }

    62% {
        transform: translate(-1.5px, .5px) rotate(1.5deg);
    }

    64% {
        transform: translate(-1.5px, 1.5px) rotate(1.5deg);
    }

    66% {
        transform: translate(.5px, 2.5px) rotate(1.5deg);
    }

    68% {
        transform: translate(2.5px, -1.5px) rotate(1.5deg);
    }

    70% {
        transform: translate(2.5px, 2.5px) rotate(.5deg);
    }

    72% {
        transform: translate(-.5px, -1.5px) rotate(1.5deg);
    }

    74% {
        transform: translate(-1.5px, 2.5px) rotate(1.5deg);
    }

    76% {
        transform: translate(-1.5px, 2.5px) rotate(1.5deg);
    }

    78% {
        transform: translate(-1.5px, 2.5px) rotate(.5deg);
    }

    80% {
        transform: translate(-1.5px, .5px) rotate(-.5deg);
    }

    82% {
        transform: translate(-1.5px, .5px) rotate(-.5deg);
    }

    84% {
        transform: translate(-.5px, .5px) rotate(1.5deg);
    }

    86% {
        transform: translate(2.5px, 1.5px) rotate(.5deg);
    }

    88% {
        transform: translate(-1.5px, .5px) rotate(1.5deg);
    }

    90% {
        transform: translate(-1.5px, -.5px) rotate(-.5deg);
    }

    92% {
        transform: translate(-1.5px, -1.5px) rotate(1.5deg);
    }

    94% {
        transform: translate(.5px, .5px) rotate(-.5deg);
    }

    96% {
        transform: translate(2.5px, -.5px) rotate(-.5deg);
    }

    98% {
        transform: translate(-1.5px, -1.5px) rotate(-.5deg);
    }

    0%, 100% {
        transform: translate(0, 0) rotate(0);
    }
}

你可能感兴趣的:(Hexo+Icarus3+live2d给博客添加看板娘)