Skip to content

看板娘-oh-my-live2d-推荐

看板娘-oh-my-live2d

image-20250424123553718

目录

[toc]

版权

警告

本着开源共享、共同学习的精神:

本文是在 《Hyde Blog》博主的《看板娘》文章 基础上增加了一些自己的实际操作记录和修改,内容依旧属于原作者所有。转载无需和我联系,但请注明文章来源。如果侵权之处,请联系博主进行删除,谢谢。

环境

2025.4.24(已解决)

警告

次配置适用于Teek@1.0.2-2025.4.10版本(其它版本可自行测试)。

提示

自己开源的 《vitepress-theme-teek-one-public》网站模板。

此模板是在《Young Kbt blog》大佬开源项目《vitepress-theme-teek 》基础上修改为自己的风格而成,感谢大佬开发得主题,大佬威武。❤️❤️

简介

给自己网站加一个黑猫哦。🤣

提示

可自定义且开箱即用的 Live2D For Web 组件, 快速为您的个人网站加入 Live2D 看板娘

OhMyLive2D 是一个应用于浏览器环境且开箱即用的 Live2D 组件, 它支持所有版本的 Live2D 模型, 使用方式足够简单并且高可自定义, 可以快速为您的个人网站添加 Live2D 看板娘, 使您的个人网站变得更具有特色.

OhMyLive2D 的初衷是为了解决官方 Cubism SDK 在使用时还需要额外通过 script 标签外部引入以及使用和学习成本较高的缺点。而现在它在被 pixi-live2d-display 驱动的同时又提供了多种导入方式以及更简单更方便自定义配置的 API。因为 oh-my-live2d 是纯 javascript,所以它可以完全独立运行在浏览器环境, 这意味着你可以在任意 web 框架或传统的原生 JS 开发的 web 项目中的使用它,并且无需再导入其他任何依赖和 css 样式资源, 真正做到了开箱即用.


🍊 体验

您可以通过stackblitz在线体验,或者在任意项目使用 CDN 导入方式立即体验 Live2D For Web:

TS
<script src="https://unpkg.com/oh-my-live2d@latest"></script>
<script>
  OML2D.loadOml2d({
    models: [
      {
        path: 'https://model.oml2d.com/HK416-1-normal/model.json',
        position: [0, 60],
        scale: 0.08,
        stageStyle: {
          height: 450
        }
      }
    ]
  });
</script>

开始配置:

1、安装

sh
pnpm add oh-my-live2d
sh
npm install oh-my-live2d
sh
yarn add oh-my-live2d

使用

提示

更多使用方法查看oh-my-live2d 官方文档

2、封装组件

(推荐)

  • docs\.vitepress\theme\components\文件夹下新建OhMyLive2D.vue文件并以如下代码

警告

如果你的图标不显示是因为我使用了自定义图标,详情参考自定义图标,并在项目head中引入后即可使用您自己的图标

image-20250424213704012

需要登录自己的阿里云图标库:(你这里直接用我的就好)

image-20250424213754639

引入示例:

编辑docs\.vitepress\config.mts文件:

TS
    // 阿里图标库symbol 引用
    ["script",{src: "https://at.alicdn.com/t/c/font_4686603_33kna2v5qcm.js",defer: "defer",},],

image-20250424213630717

docs\.vitepress\theme\components\OhMyLive2D.vue文件具体代码:
vue
<script setup>
import { ref, onMounted } from "vue";

onMounted(async () => {
  if (import.meta.env.SSR) return;

  const { loadOml2d } = await import("oh-my-live2d");
  if (typeof window === "undefined") return;
  const oml2d = loadOml2d({
    models: [

      {
        name: "black-cat", //黑猫
        path: "https://model.hacxy.cn/cat-black/model.json",
        scale: 0.15,
        position: [0, 20],
        stageStyle: {
          height: 350,
        },
        clothesIndex: 1,
      },

      {
        name: "HK416-1-destroy", // 紫色-好看
        path: "https://raw.githubusercontent.com/iCharlesZ/vscode-live2d-models/master/model-library/girls-frontline/HK416-1/destroy/model.json",
        scale: 0.09,
        volume: 0,
        position: [20, -40],
        stageStyle: {
          height: 350,
          width: 330,
        },
      },

      {
        name: "senko", //小狐狸
        path: "https://model.hacxy.cn/Senko_Normals/senko.model3.json",
        position: [-10, 20],
      },

      {
        name: "HK416", //紫色cos-枪
        path: "https://model.hacxy.cn/HK416-1-normal/model.json",
        position: [0, 60],
        scale: 0.06,
        stageStyle: {
          height: 340,
        },
        clothesIndex: 0,
      },      
    //   {
    //     name: "shizuku-pajama", //桌前吃饭
    //     path: "https://model.hacxy.cn/shizuku_pajama/index.json",
    //     scale: 0.2,
    //     volume: 0,
    //     position: [40, 10],
    //     stageStyle: {
    //       height: 350,
    //       width: 330,
    //     },
    //   },
    

    //   {
    //     name: "shizuku",
    //     path: "https://model.hacxy.cn/shizuku/shizuku.model.json",
    //     scale: 0.2,
    //     volume: 0,
    //     position: [70, 70],
    //     stageStyle: {
    //       height: 370,
    //       width: 400,
    //     },
    //   },

    //   {
    //     name: "pio", //蝙蝠
    //     path: "https://model.hacxy.cn/Pio/model.json",
    //     scale: 0.4,
    //     position: [0, 50],
    //     stageStyle: {
    //       height: 300,
    //     },
    //     index: 10,
    //   },
    //   {
    //     name: "iCharlesZ", //白猫
    //     path: "https://raw.githubusercontent.com/iCharlesZ/vscode-live2d-models/master/model-library/tororo/tororo.model.json",
    //     scale: 0.15,
    //     position: [0, 20],
    //     stageStyle: {
    //       height: 350,
    //     },
    //     index: 10,
    //   },
    ],
    dockedPosition: "left", // 停靠位置,left/right/
    initialStatus: "active", // 用于控制组件在浏览器中以当前地址首次访问时的初始状态是否处于睡眠状态或活动状态,
    primaryColor: "#ffbfbc", // 主色调
    sayHello: true, // 是否在初始化阶段打印项目信息
    transitionTime: 5000, // 组件入场和离开的过渡动画时长,单位 ms
    disable: false, // 是否禁用状态条, 为true时将不会创建状态条,默认值: false
    mobileDisplay: false, // 是否在移动设备上显示
    itemStyle: {
      //配置菜单每个子项按钮的样式
      fontSize: "14px", //菜单图标大小
      color: "#5da8ff", //菜单小图标颜色
      // background: "rgba(255, 255, 255, 0.9)", //菜单背景颜色
      transition: "all 0.3s ease", // 过渡动画
      borderRadius: "50%", //菜单背景圆角
      padding: "5px", //菜单背景内边距
      margin: "10px", //菜单背景外边距
      boxShadow: "0 0 10px #646cff", //菜单背景阴影
      border: "1px solid #5da8ff", //菜单背景边框
    },
    menus: {
      items: [
        {
          id: "Rest",
          icon: "icon-rest",
          title: "休息",
          onClick: (oml2d) => {
            oml2d.stageSlideOut(); // 滑出舞台
          },
        },
        {
          id: "SwitchModel",
          icon: "icon-switch",
          title: "切换模型",
          onClick: (oml2d) => {
            oml2d.loadRandomModel(); // 随机加载模型
          },
        },
        {
          id: "About",
          icon: "icon-about",
          title: "关于",
          onClick: () => {
            window.open("https://github.com/hacxy");
          },
        },
        {
          id: "gitee",
          icon: "icon-gitee",
          title: "gitee",
          onClick: () => {
            window.open("https://gitee.com/onlyonexl/vitepress-theme-teek-one-public");
          },
        },
      ],
    },

    tips: {
      // 复制网站文字内容时的提示
      copyTips: {
        message: ["复制成功!记得标明出处哦~"], // 提示框内容
        duration: 3000, //提示框持续时间, 单位 ms
        priority: 10, //优先级,值越大,优先级越高
      },
      // 闲置状态下的提示
      idleTips: {
        duration: 5000, //提示框持续时间, 单位 ms
        interval: 10000, //闲置状态循环播放消息的间隔时间, 单位 ms
        message: [
          "你好呀,我是看板娘~",
          "欢迎来到我的小世界~",
          "快来和我一起探索吧~",
        ], // 提示框内容
        priority: 10, //优先级,值越大,优先级越高
        wordTheDay: (wordTheDayData) => {
          // return wordTheDayData.hitokoto;  // 一言文本
          return `${wordTheDayData.hitokoto}${wordTheDayData.from}`; // 一言+作者来源
        },
      },
      messageLine: 2, // 提示消息最大显示行数
      // 模型入场后的欢迎提示
      welcomeTips: {
        // 进入网站时的欢迎提示
        duration: 6000,
        priority: 10,
        message: {
          daybreak: "早上好!一日之计在于晨,美好的一天就要开始了。",
          morning: "上午好!工作顺利嘛,不要久坐,多起来走动走动哦!",
          noon: "中午了,工作了一个上午,现在是午餐时间!",
          afternoon: "午后很容易犯困呢,来杯咖啡吧~",
          dusk: "傍晚了!工作一天幸苦啦~",
          night: "晚上好,今天过得怎么样呢?",
          lateNight: "已经这么晚了呀,早点休息吧,晚安~",
          weeHours: "这么晚还不睡吗?当心熬夜秃头哦!",
        },
      },
    },

    statusBar: {
      disable: false, // 禁用状态栏
      errorColor: "#ff0000", // 加载状态下的颜色
      loadFailMessage: "模型加载失败", // 加载失败的提示
      loadSuccessMessage: "模型加载成功", // 加载成功的提示
      loadingIcon: "icon-loading", // 加载中的图标
      loadingMessage: "模型加载中", // 加载中的提示
    }, // 模型加载失败后的提示
  });

  // 监听模型加载完成事件
  oml2d.onLoad((status) => {
    switch (status) {
      case "success":
        console.log("加载成功");
        return;
      case "fail":
        console.log("加载失败");
        return;
      case "loading":
        console.log("正在加载中");
        return;
    }
  });

  // 舞台完全滑入事件
  oml2d.onStageSlideIn(() => {
    console.log("模型进入舞台");
    // oml2d.clearTips(); // 清除所有提示消息

    // oml2d.hideModelHitAreaFrames(); // 隐藏显示模型的可点击区域

    // oml2d.loadModelByIndex(0); // 加载模型索引为 0 的模型

    // oml2d.loadModelByName('HK416', 0);// 加载HK416模型和模型衣服索引为 0 的服装

    // oml2d.loadNextModelClothes(); // 加载下一个模型服装

    // oml2d.loadRandomModel(); // 随机加载模型

    // oml2d.reloadModel(); // 重载模型

    // oml2d.setModelAnchor({ x: 0, y: 0 }); // 设置模型锚点

    // oml2d.setModelPosition(0, 60); // 设置模型位置

    // oml2d.setModelRotation(0-360); // 设置模型旋转

    // oml2d.setModelScale(0.06); // 设置模型缩放

    // oml2d.setStageStyle({ width: 340, height: 340, })// 设置舞台大小

    oml2d.setStatusBarClickEvent(() => {
      // 绑定状态条点击事件
      oml2d.statusBarPopup("(ฅ´ω`ฅ) 摸摸头", 3000, oml2d.options.primaryColor);
      oml2d.stageSlideIn(); //舞台滑入
    });

    oml2d.setStatusBarHoverEvent({
      onIn: () => {
        oml2d.statusBarPopup("发现隐藏彩蛋", 10000, oml2d.options.primaryColor);
      },
      onOut: () => {
        oml2d.statusBarPopup("要常来看我哦", 10000, oml2d.options.primaryColor);
      },
    });

    oml2d.showModelHitAreaFrames(); // 显示显示模型的可点击区域

    // oml2d.stageSlideIn(); // 舞台滑入,不受关闭影响

    // oml2d.stageSlideOut(); // 舞台滑出

    // oml2d.statusBarClearEvents(); // 清除状态条所有已绑定事件

    // 三选一:statusBarOpen和statusBarPopup和statusBarClose,三个方法不能同时使用
    // oml2d.statusBarClose('关闭条状态', 3000, 'pink'); // 关闭条状态

    // oml2d.statusBarOpen('你干嘛', 'pink'); //弹出状态条并保持打开状态

    oml2d.statusBarPopup("爱自己", oml2d.options.primaryColor); // 使用配置的主色调

    oml2d.stopTipsIdle(); //停止空闲消息播放器

    oml2d.tipsMessage(`欢迎访问One Blog,当前版本:${oml2d.version}`, 5000, 10);
  });

  // 舞台完全滑出事件
  oml2d.onStageSlideOut(() => {
    console.log("模型离开舞台");
    oml2d.startTipsIdle(); // 恢复空闲消息播放器
  });
});
</script>

<script>
export default { name: "oh-my-live2d" };
</script>

<template>
  <div class="oh-my-live2d"></div>
</template>

<style lang="scss" scoped></style>

3、注册

  • 最后在docs\.vitepress\theme\components\目录下的TeekLayoutProvider.vue组件注册
VUE
<script setup lang="ts" name="TeekLayoutProvider">
import OhMyLive2D from "./OhMyLive2D.vue"; //导入看板娘组件
</script>

<template>
  <Teek.Layout>
    // 其他代码
    <template #layout-top>
    <!-- 看板娘组件 -->
      <OhMyLive2D />
    </template>
  </Teek.Layout>
</template>

image-20250424123333519


扩展:index.ts 注册 官方注册方式(个人Teek项目不涉及)
  • docs\.vitepress\theme\index.ts文件中并以如下代码
TS
export default {
  extends: Teek, //第三方主题
  async enhanceApp() {  //注意添加`async`
    // @ts-ignore-error   注意:非SSR环境下加载Live2D模型需要添加// @ts-ignore-error,否则TS会报错误
    if (!import.meta.env.SSR) {
      const { loadOml2d } = await import("oh-my-live2d");
      loadOml2d({
        models: [
          {
            path: "https://raw.githubusercontent.com/iCharlesZ/vscode-live2d-models/master/model-library/girls-frontline/HK416-2/normal/model.json",
          },
        ],
      });
    }
  },
};

4、更新

  • 如需更新 oh-my-live2d 你只需要在安装命令后缀加上@latest 即可更新至当前最新发行版, 当然 vuepressvitepress 等插件也同理
sh
pnpm add oh-my-live2d@latest
sh
npm install oh-my-live2d@latest
sh
yarn add oh-my-live2d@latest

5、验证

运行项目,验证效果:

image-20250424123759454

image-20250424123903116

image-20250424123948939

image-20250424124016397

结束。

选项

提示

相关配置项可以参考oh-my-live2d 官方选项配置

模型

提示

想要更换模型在 @iCharlesZ 这里找,替换 model 中的 pathurl 链接即可

TS
export default {
  extends: Teek,
  // oh-my-live2d 配置
  async enhanceApp() {
    if (!import.meta.env.SSR) {
      const { loadOml2d } = await import("oh-my-live2d");
      loadOml2d({
        models: [
          {
            path: "https://raw.githubusercontent.com/iCharlesZ/vscode-live2d-models/master/model-library/girls-frontline/HK416-1/normal/model.json",
          },
        ],
      });
    }
  },
};

关于我

我的博客主旨:

  • 排版美观,语言精炼;
  • 文档即手册,步骤明细,拒绝埋坑,提供源码;
  • 本人实战文档都是亲测成功的,各位小伙伴在实际操作过程中如有什么疑问,可随时联系本人帮您解决问题,让我们一起进步!

🍀 个人网站

image-20250109220325748

🍀 微信二维码

x2675263825 (舍得), qq:2675263825。

image-20230107215114763

🍀 微信公众号

《云原生架构师实战》

image-20230107215126971

🍀 csdn

https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

image-20230107215149885

🍀 知乎

https://www.zhihu.com/people/foryouone

image-20230107215203185

最后

如果你还有疑惑,可以去我的网站查看更多内容或者联系我帮忙查看。

如果你有更好的方式,评论区留言告诉我。谢谢!

好了,本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!

最近更新