看板娘 原创
oh-my-live2d 推荐
简介
提示
可自定义且开箱即用的 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:
<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>
安装
pnpm add oh-my-live2d
npm install oh-my-live2d
yarn add oh-my-live2d
更新
- 如需更新
oh-my-live2d
你只需要在安装命令后缀加上@latest 即可更新至当前最新发行版, 当然vuepress
、vitepress
等插件也同理
pnpm add oh-my-live2d@latest
npm install oh-my-live2d@latest
yarn add oh-my-live2d@latest
使用
提示
更多使用方法查看oh-my-live2d 官方文档
封装组件注册 推荐
- 在
docs\.vitepress\theme\components\
文件夹下新建OhMyLive2D.vue
文件并以如下代码
警告
如果你的图标不显示是因为我使用了自定义图标,详情参考自定义图标,并在项目head
中引入后即可使用您自己的图标
引入示例:
// 阿里图标库symbol 引用
["script",{src: "https://at.alicdn.com/t/c/font_xxxxxxx_xj7acblxpxj.js",defer: "defer",},],
/* docs\.vitepress\theme\components\OhMyLive2D.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: "HK416", //紫色cos
path: "https://model.hacxy.cn/HK416-1-normal/model.json",
position: [0, 60],
scale: 0.06,
stageStyle: {
height: 340,
},
clothesIndex: 0,
},
{
name: "black-cat", //黑猫
path: "https://model.hacxy.cn/cat-black/model.json",
scale: 0.15,
position: [0, 20],
stageStyle: {
height: 350,
},
clothesIndex: 1,
},
{
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: "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: "shizuku",
path: "https://model.hacxy.cn/shizuku/shizuku.model.json",
scale: 0.2,
volume: 0,
position: [70, 70],
stageStyle: {
height: 370,
width: 400,
},
},
{
name: "senko",
path: "https://model.hacxy.cn/Senko_Normals/senko.model3.json",
position: [-10, 20],
},
{
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: "SwitchModelClothes",
icon: "icon-skin",
title: "切换服装",
onClick: (oml2d) => {
oml2d.loadRandomModel(); // 随机加载模型
},
},
{
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/SeasirHyde/teek-hyde");
},
},
{
id: "toggleDock",
icon: "icon-github",
title: "切换停靠",
onClick: (oml2d) => {
console.log(oml2d);
console.log(oml2d.options.dockedPosition);
},
},
],
},
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(`欢迎访问Hyde 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>
/* docs\.vitepress\theme\components\TeekLayoutProvider.vue */
<script setup lang="ts" name="TeekLayoutProvider">
// @ts-ignore
import OhMyLive2D from "./OhMyLive2D.vue"; //导入看板娘组件
</script>
<template>
<Teek.Layout>
<template #layout-top>
<!-- 看板娘组件 -->
<OhMyLive2D />
</template>
其他组件...
</Teek.Layout>
</template>
index.ts 注册 官方注册方式
- 在
docs\.vitepress\theme\index.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",
},
],
});
}
},
};
选项
提示
相关配置项可以参考oh-my-live2d 官方选项配置。
模型
提示
想要更换模型在 @iCharlesZ 这里找,替换 model
中的 path
或url
链接即可
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",
},
],
});
}
},
};
Website
简介
提示
vitepress-theme-website 是一个基于 Vitepress 的主题插件,集成评论 Waline、Live2D 看板娘。查看 Demo
安装
pnpm add -D vitepress-theme-website
yarn add -D vitepress-theme-website
npm install vitepress-theme-website
bun add -D vitepress-theme-website
使用
- 在
.vitepress/theme/index.ts
粘贴下面代码并保存
// .vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
import { useLive2d } from 'vitepress-theme-website'
export default {
extends: DefaultTheme,
setup() {
//看板娘
useLive2d({
enable: true,
model: {
url: 'https://raw.githubusercontent.com/iCharlesZ/vscode-live2d-models/master/model-library/hibiki/hibiki.model.json'
},
display: {
position: 'right',
width: '135px',
height: '300px',
xOffset: '35px',
yOffset: '5px'
},
mobile: {
show: true
},
react: {
opacity: 0.8
}
})
}
}
由于 live2d.js 打包后会导致模型显示不全,需要用 cdn 方式引用。
live2d.js 下载地址,下载完成后放在和 .vitepress 平级的 public 目录中。
.
├─ docs
│ ├─ .vitepress
│ ├─ public
│ │ └─ live2d.js >我在这里
│ └─ index.md
└─ node_modules
docs\.vitepress\config.mts
文件中增加如下配置:
export default defineConfig({
head: [["script", { src: "/live2d.js" }]];
})
live2d-widget
简介
提示
在网页中添加 Live2D 看板娘。兼容 PJAX,支持无刷新加载。
使用
docs\.vitepress\config.mts
文件中增加如下配置:
export default defineConfig({
["script", { src: "https://fastly.jsdelivr.net/gh/stevenjoezhang/live2d-widget@latest/autoload.js" }],
})
效果
访问https://live2d-hyde.netlify.app/查看效果
L2D
简介
提示
l2d
是 Live2D 的缩写. 同时也是我设法得到的足够简短的名称. 顾名思义, 它是一个应用于浏览器的 Live2D 模型加载工具, 你可以利用 l2d
很轻松的将 Live2D 模型加载到你的个人网站中, 这仅需几步.
通过 stackblitz 在线游玩 l2d
安装
pnpm install l2d
npm install l2d
yarn install l2d
使用
之后在浏览器中加载 Live2D 模型仅需两步, 假设 DOM 中存在一个 id 为 l2d-canvas 的 canvas 元素
<canvas id="l2d-canvas"></canvas>
初始化画布
import { init } from "l2d";
const l2d = init(document.getElementById("canvas") as HTMLCanvasElement);
调用 init() 方法初始化成功后, 它将返回一个画布实例对象, 用于加载模型, 以及画布相关操作.
创建模型
在画布中创建和加载一个模型, 只需要调用l2d
实例下的 create
方法, 调用时可以传入 options 来定义模型地址和模型样式, 同时 create
是一个异步函数, 当 then
方法被调用时表示模型创建成功.