当前位置: 首页 > news >正文

关于在博客页面添加live2d-widget的一些心得和踩过的坑

如何在自己的博客页面使用自定义Live2D模型

在Hugo站点(我使用的是Reimu主题,其他主题也是同理的)中集成自定义Live2D模型,需要配置资源加载、处理CDN问题和大文件等。下面是详细步骤,基于我的实际经验(包括模型加载失败、CDN加载失败、GitHub Raw 400错误和大文件限制等等问题)。

1: 准备Live2D资源

  1. 创建GitHub仓库:新建一个公开仓库(如your_github_username/live2d_api),下载live2d-api仓库的model文件夹以及model.json文件上传到新建仓库。后续对应的文件目录结构也要参考这个库下面的教程。在这里插入图片描述
    下载live2d-widget库下dist文件夹的所有内容,上传到仓库。确保分支为main在这里插入图片描述
    如果要上传自己的Live2D模型文件(.moc3、.json、纹理图片等),只需要薅来的模型文件中把model.json或者说model3.json改名为index.json就可以了,但是注意命名不要有中文,会出现乱码。当然上传了新模型的话,对应的modellist也需要对应修改,这部分很简单,可以直接参考live2d-api仓库的教程。

  2. 关键文件

    • waifu-tips.json:交互框内容。(我是下载下来按照自己喜好修改了,如果你觉得原来的也行的话,就用源仓库的也行)。
    • waifu.csswaifu-tips.js:样式和模型加载脚本。
    • modellist.json:模型存放信息,用于加载模型。
  3. 关于访问
    每次上传了新的模型,需要点击该仓库的tag,然后新建release,只有这样后续才能使用cdn链接加载你的模型。
    在这里插入图片描述

注意:仓库必须公开,否则Raw访问会返回400 Bad Request。如果你想吃现成的话当然也可以直接照抄我的仓库,也有一些我嫖到的免费模型:live2d_api

2: 配置Reimu主题中的Live2D

Reimu主题内置Live2D支持(在themes/reimu/static/resources/live2d-widgets@0.9.0/autoload.js)。别的主题也应该有,如果没有的话可以把live2d-widget仓库下载下来把autoload.js保存到跟这个主题对应的位置。我的autoload.js是已经修改过的,所以说可能和原版不太一样,如果原版的不太行的话,可以尝试一下我的:

// live2d_path 参数建议使用绝对路径
const live2d_path = "https://fastly.jsdelivr.net/npm/live2d-widgets@1.0.0-rc.7/dist/";// 封装异步加载资源的方法
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.type = 'module';tag.src = url;}if (tag) {tag.onload = () => resolve(url);tag.onerror = () => reject(url);document.head.appendChild(tag);}});
}// 避免跨域图片资源问题
const OriginalImage = window.Image;
window.Image = function (...args) {const img = new OriginalImage(...args);img.crossOrigin = "anonymous";return img;
};
window.Image.prototype = OriginalImage.prototype;// 加载 waifu.css 和 waifu-tips.js
(async () => {// 备用CDN列表,如果主CDN无法访问会自动尝试备用CDNconst cdnList = ["https://fastly.jsdelivr.net/gh/nizigen/live2d_api@v1.4/","https://cdn.jsdelivr.net/gh/nizigen/live2d_api@v1.4/","https://raw.githubusercontent.com/nizigen/live2d_api/v1.4/","https://gcore.jsdelivr.net/gh/nizigen/live2d_api@v1.4/"];let currentCdnIndex = 0;let loadSuccess = false;// 尝试加载资源的函数,支持本地优先+CDN回退async function tryLoadResources (cdnUrl) {try {// 优先尝试加载本地CSSlet cssPromise;try {cssPromise = loadExternalResource("/waifu.css", "css");console.log("尝试加载本地CSS: /waifu.css");} catch (localError) {console.warn("本地CSS加载失败,使用CDN:", localError);cssPromise = loadExternalResource(cdnUrl + "waifu.css", "css");}await Promise.all([cssPromise,loadExternalResource(cdnUrl + "waifu-tips.js", "js")]);loadSuccess = true;return cdnUrl;} catch (error) {console.warn(`CDN ${cdnUrl} 加载失败,尝试下一个...`);return null;}}// 尝试所有CDN直到成功或全部失败while (!loadSuccess && currentCdnIndex < cdnList.length) {const result = await tryLoadResources(cdnList[currentCdnIndex]);if (result) {console.log(`成功使用CDN: ${result}`);break;}currentCdnIndex++;}if (!loadSuccess) {console.error("所有CDN都无法访问,Live2D功能将被禁用");return;}const workingCdn = cdnList[currentCdnIndex];// 配置选项的具体用法见 README.mdtry {console.log("初始化Live2D Widget...");console.log("工作CDN:", workingCdn);console.log("waifu-tips.json路径:", workingCdn + "waifu-tips.json");initWidget({waifuPath: workingCdn + "waifu-tips.json",cdnPath: workingCdn,cubism2Path: live2d_path + "live2d.min.js",cubism5Path: "https://cubism.live2d.com/sdk-web/cubismcore/live2dcubismcore.min.js",tools: ["hitokoto", "asteroids", "switch-model", "switch-texture", "photo", "info", "quit"],logLevel: "info", // 改为info级别以获得更多调试信息drag: false});console.log("Live2D Widget初始化完成");// 添加必要的CSS样式确保Live2D正确显示const style = document.createElement('style');style.textContent = `#waifu.waifu-active {bottom: 0 !important;transform: translateY(0) !important;}#waifu.waifu-hidden {bottom: -1000px !important;}#live2d {display: block !important;visibility: visible !important;pointer-events: auto !important;}#waifu-tool {display: block !important;opacity: 1 !important;pointer-events: auto !important;}#waifu-tips {display: block !important;pointer-events: auto !important;}`;document.head.appendChild(style);// 清除可能导致问题的缓存localStorage.removeItem("modelId");localStorage.removeItem("modelTexturesId");} catch (error) {console.error("Live2D初始化失败:", error);console.warn("建议检查网络连接或更换CDN源");}// 添加全局错误处理,防止Live2D错误导致页面崩溃window.addEventListener('error', (event) => {// 处理Live2D相关的错误if (event.message && event.message.includes('hitTest')) {console.warn("Live2D hitTest错误,已自动修复:", event.message);event.preventDefault(); // 阻止错误传播return false;}// 处理资源加载错误if (event.filename && (event.filename.includes('live2d') || event.filename.includes('textures.cache'))) {console.warn("Live2D资源加载错误,已自动处理:", event.message);event.preventDefault();return false;}});// 添加额外的检查和调试信息setTimeout(() => {const waifuElement = document.getElementById('waifu');const live2dCanvas = document.getElementById('live2d');console.log("Live2D元素检查:");console.log("- waifu元素存在:", !!waifuElement);console.log("- live2d画布存在:", !!live2dCanvas);if (waifuElement) {console.log("- waifu类名:", waifuElement.className);console.log("- waifu样式:", getComputedStyle(waifuElement).bottom);}if (live2dCanvas) {console.log("- 画布尺寸:", live2dCanvas.width, "x", live2dCanvas.height);console.log("- 画布样式:", getComputedStyle(live2dCanvas).display, getComputedStyle(live2dCanvas).visibility);}// 如果画布存在但不可见,强制显示if (live2dCanvas && getComputedStyle(live2dCanvas).display === 'none') {console.log("强制显示Live2D画布");live2dCanvas.style.display = 'block';live2dCanvas.style.visibility = 'visible';}// 如果waifu元素存在但没有active类,添加它if (waifuElement && !waifuElement.classList.contains('waifu-active')) {console.log("添加waifu-active类");waifuElement.classList.add('waifu-active');}// 如果Live2D加载失败,尝试降级方案if (!live2dCanvas || live2dCanvas.width === 0) {console.warn("Live2D模型加载失败,尝试降级显示");// 可以在这里添加降级的静态图片显示}}, 3000);
})();console.log(`く__,.ヘヽ.        /  ,ー、 〉\ ', !-─‐-i  /  /´/`ー'       L//`ヽ、/   /,   /|   ,   ,       ',イ   / /-‐/  i  L_ ハ ヽ!   iレ ヘ 7イ`ト   レ'ァ-ト、!ハ|   |!,/7 '0'     ´0iソ|    ||.从"    _     ,,,, / |./    |レ'| i>.、,,__  _,.イ /   .i   |レ'| | / k_7_/レ'ヽ,  ハ.  || |/i 〈|/   i  ,.ヘ |  i  |.|/ /  i:    ヘ!    \  |kヽ>、ハ    _,.ヘ、    /、!!'〈//`T´', \ `'7'ーr'レ'ヽL__|___i,___,ンレ|ノト-,/  |___./'ー'    !_,.:
`);
  1. 启用Live2D:在config/_default/params.yml中设置(这就是Reimu专属的配置文件了,别的主题我不清楚,所以推荐大家都来用这个主题喵!):

    live2d_widgets:enable: trueposition: left  # 或 right
    
  2. 修改autoload.js:原来的版本会有一个live2d-path,可以直接改成https://fastly.jsdelivr.net/npm/live2d-widgets@1.0.0-rc.7/dist/,我这里直接使用了多个cdn链接防止有的cdn链接无法访问,编辑themes/reimu/static/resources/live2d-widgets@0.9.0/autoload.js,调整CDN列表以避免加载失败:

    const cdnList = ["https://cdn.jsdelivr.net/gh/nizigen/live2d_api@main/",  // 稳定CDN优先"https://fastly.jsdelivr.net/gh/nizigen/live2d_api@main/","https://gcore.jsdelivr.net/gh/nizigen/live2d_api@main/","https://raw.githubusercontent.com/nizigen/live2d_api/main/"  // 作为备用
    ];
    
    • 为什么这样?GitHub Raw不稳定(易400错误、限流),优先用jsDelivr代理,下面第三点对应的workingcdn其实就是通过cdnlist里面第一个能够使用的链接。还有就是加载Cubism3及以上的live2d模型需要core,我的尝试下https://fastly.jsdelivr.net/npm/live2d-widgets@1.0.0-rc.7/dist/,这个版本是可以找到对应的core的。
  3. 初始化:在autoload.js的initWidget函数配置的仓库:
    详细的关于initWidget的参数的问题可以去原仓库看readme,这里不详细介绍了。大家在使用的时候把cdn列表里面的任意一个改为自己的用户名以及仓库名替换这里的workingcdn就好了,live2d_path建议就使用我在第二点提到的那个。

  initWidget({waifuPath: workingCdn + "waifu-tips.json",cdnPath: workingCdn,cubism2Path: live2d_path + "live2d.min.js",cubism5Path: "https://cubism.live2d.com/sdk-web/cubismcore/live2dcubismcore.min.js",tools: ["hitokoto", "asteroids", "switch-model", "switch-texture", "photo", "info", "quit"],logLevel: "info", // 改为info级别以获得更多调试信息drag: false});  

3: 处理大文件(超过20MB的图片)

一些CDN(如jsDelivr)限制单文件20-50MB。如果有些纹理图片太大:
压缩:用WPS图片压缩或者在网上找压缩网站压缩到<20MB替换掉原图片。

通过以上步骤,应该可以在博客中用上自定义Live2D模型!如果遇到问题,欢迎在评论区提出来,如果是我遇到过的问题乐意给大家解答。效果预览:我的博客

(参考:Live2D官方文档、Reimu主题GitHub、live2d-widget、live2d-api)

http://www.dtcms.com/a/423641.html

相关文章:

  • 2025年,今后需要进步的方面
  • 有哪些做平面设计好素材网站自学it怎么入门
  • Android16 adb投屏工具Scrcpy介绍
  • 酵母展示技术如何重塑酶工程?从定向进化到工业催化的突破
  • 广汉做网站立白内部网站
  • 【FPGA+DSP系列】——(3)中断学习(以定时器中断为例)
  • 重庆网上注册公司网站配置 wordpress
  • ECMAScript 2025 有哪些新特性?
  • CSP-S 提高组 2025 初赛试题解析(第三部分:完善程序题(二)(39-43))
  • 前端实战:基于React Hooks与Ant Design V5的多级菜单系统
  • 单片机OTA升级:高效无线更新的秘密
  • 社区平安建设基层网站重庆企业网站建设官网
  • 嵌入式学习笔记4.STM32中断系统及外部中断EXTI
  • 手机网站模板大全上海市公共招聘网官网
  • Python爬虫实战:获取国家天文数据中心公开的观测信息与数据分析
  • 中核西北建设集团网站苏州手机社区网站建设
  • 网站建设皿金手指谷哥壹柒小米发布会2022
  • 实战:用Scrapy框架搭建第一个爬虫项目
  • Kubernetes 的本质:一个以 API 为中心的“元操作系统”
  • 网站设计的公司选哪家陕西建设网官网登录
  • 基于EasyExcel、FastExcel封装spring boot starter
  • Arpg第五节——方法
  • 太原网站搭建推广服装设计网站模板下载
  • 人工智能-机器学习day3
  • 第四部分:VTK常用类详解(第113章 vtkTensorGlyph张量符号化类)
  • 中国平安官方网站心态建设课件做网站的学校
  • 翻译插件分享
  • 网页设计广州网站购物型网站用dw做
  • 水平扩展与垂直扩展
  • React基础到进阶