前言
<请务必不要偷懒使用下文提到的此站自建的api>
实现此功能需要您有一定的HTML,PHP,JS等基础,以便于对出现问题的调试。
本文所用代码,远程调用等可能存在未知安全漏洞,请及时自检。
本文章“Photoshop”和”动画制作“部分只用作制作demo和认识live2d,为保证人物模型质量请自行解决。
本文章“Web端制作”部分基于撰稿时最新版本ps与live2d cubism,并以moc3文件为例。适用于源码理解或者高校学生工程实践任务充数。
远程部署篇章中“HTML demo”部分适用于并不复杂的网站框架下使用,可以作为新手尝试使用,也可以提供为前端大佬自行修改。
远程部署篇章中“博客部署”部分皆以wordpress+Sakura环境为例,想要建站的可以自行通过“资料来源”进行配置。
远程部署篇章中“博客部署准备(1)”部分基于大多数博客网站所用的看板娘(旧版moc),并将几乎所有的js和css都移植到自己github或者服务器,适合”新手和学习前端搭建“使用。
远程部署篇章中“博客部署准备(2)”部分为基于live2d cubism新版(即导出文件为moc3),并将几乎所有的js和css都移植到自己github或者服务器,适合”对人物模型有自制需求“使用。
另外,本文所有代码都只是基于”资料来源“的博主所提供的代码进行分析和略微调整以适应自身需求,自身能力有限,可能并不能满足所有情况。
资料来源
bilibili@洛北家的鼠鼠提供的live2d相关支持
(38条消息) 笔记:live2d4.0 sdk 博客园网页动画_weixin_44128558的博客-CSDN博客_live2d生成纹理集
本物品请放置在熊孩子抓不到的地方的个人空间_哔哩哔哩_bilibili
live2d web端加载moc3模型 - 麻辣猪仔 - 博客园 (cnblogs.com)
【Live2D】15分钟学会如何制作一个网页动态看板娘 官方原生SDK开发_哔哩哔哩_bilibili
https://github.com/fghrsh/live2d_api
Sakura博客主题添加Live2D看板娘 | 流年,谁给过的倾城 | Yremp
jsdelivr 出现 Failed to fetch version info for 原因分析 | 唐瑞平 (tangruiping.com)
以及下文随教程附上的链接
安装部分
live2d cubism
Live2D免费下载 - Live2D Cubism【官网】
cubism sdk for web 下载
Live2D Cubism SDK for Web下载 - Live2D Cubism【官网】
准备好vscode,photoshop
download一下大佬的sdk前端修改代码里面的live2d文件夹
链接: https://pan.baidu.com/s/1SV-R3OCGlQ37BrPqKzo7lg 提取码: xg29
photoshop部分(简略)
调整角度或者大小,然后选择主体

通过画笔调整边界,抠图分出各个部分(头发,脸部,身体等)。调整完成后ctrl s保存为psd版本
动画制作部分(简略)
可以直接把psd拖入live2d软件
在model模式下选择要编辑的部分,在参数处制作动画

在animation模式下,将项目拖入进度条,分别添加关键帧

animation下导出运作档,会保存为json文件


在model模式下,在保存纹理后,导出moc3文件。
(在实际使用模型中,通常需要物理模拟设定文件,动态文件,moc3文件,还有纹理集)这里就不详细介绍了。
动画预览
将moc3和json文件拖入live2d cubism viewer,会自动生成motions

添加组名为idle(闲置动画组)
web端制作
npm环境搭建
用vscode打开之前准备的cubism sdk for web

在终端中作如下命令

确保进入demo目录,cnpm install
在npm脚本中运行simple\server,build脚本。(没有的NPM脚本自行百度)

一、修改变量
将变量ResourcesPath、BackImageName、ModelDir、ModelDirSize的变量类型改成let

二、修改index.html
网上的那位师傅用的是flask框架用来引入资源,这里贴下不用flask的代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=1900">
<title>TypeScript HTML App</title>
<link rel="stylesheet" type="text/css" href="./static/live2d/css/live2d.css"/>
<style>
html, body {
margin: 0;
background-color: #22d7dd;
}
</style>
<script type="text/javascript" src="./static/live2d/js/jquery.js"></script>
<!-- Pollyfill script -->
<script src="<https://unpkg.com/core-js-bundle@3.6.1/minified.js>"></script>
<!-- Live2DCubismCore script -->
<script src="./static/live2d/js/live2dcubismcore.js"></script>
<!-- Build script -->
<script src="./dist/bundle.js"></script>
</head>
<body>
1234567890
<div class="live2d-main">
<div class="live2d-tips"></div>
<!-- 这里可以定义画布的大小位置 -->
<canvas id="live2d" width="280" height="250" class="live2d"></canvas>
<div class="tool">
<span class="fui-home"></span>
<span class="fui-chat"></span>
<span class="fui-eye"></span>
<span class="fui-user"></span>
<span class="fui-photo"></span>
<span class="fui-info-circle"></span>
<span class="fui-cross"></span>
</div>
</div>
</body>
<script src="./static/live2d/js/message.js"></script>
<script type="text/javascript">
var resourcesPath = './static/live2d/js/message.js'; // 指定资源文件(模型)保存的路径
var backImageName = ''; // 指定背景图片
var modelDir = 'Haru,Hiyori,Mark,Natori,Rice,zwt'; // 指定需要加载的模型
init(); // 初始化模型,属于message.js文件
</script>
</html>
三、处理压缩包live2d.zip/static
把static目录复制到sdk里demo里面

删除boudle.js

四、处理lappdefine.ts
在最下面添加代码
export const win: any=window
win.initDefine=function(resourcesPath: string, backImageName: string,modelDir:string[]){
ResourcesPath=resourcesPath;
BackImageName=backImageName;
ModelDir=modelDir;
ModelDirSize=modelDir.length;
}
五、处理main.ts
看着别人的帖子是把下面注释了
/**
* Process when changing screen size.
*/
// window.onresize = () => {
// if (LAppDefine.CanvasSize === 'auto') {
// LAppDelegate.getInstance().onResize();
// }
// };
六、处理lappdelegate.ts的initialize()函数
经过报错处理后的initialize()代码
/**
* APPに必要な物を初期化する。
*/
public initialize(): boolean {
// 创建画布
// canvas = document.createElement('canvas');
// canvas.width = LAppDefine.RenderTargetWidth;
// canvas.height = LAppDefine.RenderTargetHeight;
// 原来是用js动态在网页上创建画布,画布的长宽在lappdefine.ts指定,现在直接在html中已经有了画布直接拿过来使用就行
canvas = <HTMLCanvasElement>document.getElementById("live2d"); // index.html中的id为live2d的画布
canvas.width = canvas.width;
canvas.height = canvas.height;
canvas.toDataURL("image/png");
// 这个是index.html工具栏中的眼睛图标,点击眼睛图标就切换下一个模型
// 正规来说应该留个切换模型的口子,在message.js中调用,因为懒就直接在这里写了
const fui_eye = <HTMLSpanElement>document.getElementsByClassName("fui-eye")[0];
// 初始化gl上下文 (代码段结束后有解释)
// @ts-ignore
gl = canvas.getContext('webgl',{alpha: true }) || canvas.getContext('experimental-webgl');
if (!gl) {
alert('Cannot initialize WebGL. This browser does not support.\\n不能初始化WebGL,该浏览器不支持WebGL,请切换浏览器重试');
gl = null;
document.body.innerHTML =
'该浏览器不支持 <code><canvas></code> 标签元素,请切换浏览器重试 .';
// gl初期化失敗
return false;
}
// 向DOM添加画布
// document.body.appendChild(canvas);
if (!frameBuffer) {
frameBuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
}
// 透明设置
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
const supportTouch: boolean = 'ontouchend' in canvas; //是否支持触碰(触摸屏)
if (supportTouch) { // 没有触屏电脑(两种事件都要注册)
// 注册触摸相关的回掉函数 (触摸屏)
canvas.ontouchstart = onTouchBegan;
canvas.ontouchmove = onTouchMoved;
canvas.ontouchend = onTouchEnded;
canvas.ontouchcancel = onTouchCancel;
} else {
// 注册鼠标相关的回呼函数
canvas.onmousedown = onClickBegan;
// canvas.onmousemove = onMouseMoved; //原来是在画布上注册鼠标移动事件,鼠标移出画布就监听不到
window.onmousemove = onMouseMoved; //对整个window窗口监听,是角色跟随鼠标,需要对鼠标坐标获取做调整
canvas.onmouseup = onClickEnded;
fui_eye.onmousedown = (): void => { // 工具栏眼睛图标点击事件
const live2DManager: LAppLive2DManager = LAppLive2DManager.getInstance();
live2DManager.nextScene();
};
}
// AppView的初始化
this._view.initialize();
// Cubism SDK的初始化
this.initializeCubism();
return true;
}
七、处理lappdelegate.ts的onMouseMove()函数
function onMouseMoved(e: MouseEvent): void {
// if (!LAppDelegate.getInstance()._captured) { // 判断是否单击,原来是要按住鼠标左键图像才会跟着鼠标动
// return;
// }
if (!LAppDelegate.getInstance()._view) { //获得lappview.ts的实例对象
LAppPal.printMessage('view notfound');
return;
}
// e.clientX和e.clientY获取的坐标点都是以左上角为原点
const rect = (e.target as Element).getBoundingClientRect();
// const posX: number = e.clientX - rect.left;
// const posY: number = e.clientY - rect.top;
let posX: number = e.clientX;
let posY: number = e.clientY - window.innerHeight + canvas.height;
// 图像在网页的坐下角,简单处理坐标将超过画布边界坐标就等与边界坐标
posX = (posX > canvas.width) ? canvas.width : posX;
posY = (posY < 0) ? 0 : posY;
LAppDelegate.getInstance()._view.onTouchesMoved(posX, posY);// 这个就不做解释,就是转换坐标,调用LAppLive2DManager类重新绘制图像
}
八、处理lappdelegate.ts的initializeCubism()函数
public initializeCubism(): void {
// setup cubism 设置cubism
this._cubismOption.logFunction = LAppPal.printMessage; //初始化控制台打印信息工具,就是console.log
this._cubismOption.loggingLevel = LAppDefine.CubismLoggingLevel; //指定打印日志的等级
CubismFramework.startUp(this._cubismOption);
// initialize cubism 初始化设置cubism
CubismFramework.initialize();
// load model 加载模型
LAppLive2DManager.getInstance();
// 更新时间
LAppPal.updateTime();
this._view.initializeSprite();
}
九、处理lappview.ts的initializeSprite()函数
// 进行图像的初始化,一些不重要的元素初始化。这里有一个齿轮设置的图像,里面的内容替换成了眼睛的图标,没用所以注释掉,还加了一个背景图片加载的判断,没有背景图片就不加载
public initializeSprite(): void {
const width: number = canvas.width;
const height: number = canvas.height;
const textureManager = LAppDelegate.getInstance().getTextureManager(); // 从LAppDelegate类中得到纹理管理器
const resourcesPath = LAppDefine.ResourcesPath;
let imageName = '';
// 背景图像初始化
imageName = LAppDefine.BackImageName;
if(imageName != "" && imageName != null){ //如果指定了背景图片,就加载
// 由于异步,创建回调函数
const initBackGroundTexture = (textureInfo: TextureInfo): void => {
const x: number = width * 0.5; //背景图片出现宽度的位置
const y: number = height * 0.5; //背景图片出现高度的位置
const fwidth = textureInfo.width * 2.0; //背景图片的宽度
const fheight = height * 0.95; //背景图片的高度
this._back = new LAppSprite(x, y, fwidth, fheight, textureInfo.id); //绘制背景图片
};
textureManager.createTextureFromPngFile( //回掉函数
resourcesPath + imageName,
false,
initBackGroundTexture
);
}
// 齿轮图像初始化 (原来是右上角有一个齿轮的图片,点击齿轮图片切换模型)
// imageName = LAppDefine.GearImageName;
// // 齿轮初始化后的回掉函数
// const initGearTexture = (textureInfo: TextureInfo): void => {
// const x = width - textureInfo.width * 0.5; //出现在右上角
// const y = height - textureInfo.height * 0.5;
// const fwidth = textureInfo.width;
// const fheight = textureInfo.height;
// this._gear = new LAppSprite(x, y, fwidth, fheight, textureInfo.id);
// };
// textureManager.createTextureFromPngFile(
// resourcesPath + imageName,
// false,
// initGearTexture
// );
// 创建阴影
if (this._programId == null) {
this._programId = LAppDelegate.getInstance().createShader();
}
}
十、处理lappdelegate.ts的run()函数
// 执行处理
public run(): void {
// 主循环
const loop = (): void => {
// 确认有无实例
if (s_instance == null) {
return;
}
// 更新时间
LAppPal.updateTime();
// 画面的初始化
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 启动深度测试
gl.enable(gl.DEPTH_TEST);
// 附近的物体将远处的物体遮盖起来
gl.depthFunc(gl.LEQUAL);
// 清除彩色缓冲区和深度缓冲区 (加上这一句会导致有些浏览器背景变成黑色,而不是透明)
// gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.clearDepth(1.0);
// 透明设置
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
// 绘图更新
this._view.render();
// 循环递归调用
requestAnimationFrame(loop);
};
loop();
}
十一、处理live2d文件
将由live2d cubism产生的文件全部放入static/model/[人物名]中

在index.html中变量modelDir添加你的[人物名]文件夹名。
如果在这部之后还没有在web端刷新出自己添加的人物,检查lappdefine.ts中新添加的函数名和live2d/js/message.js中调用的函数名是否一致
其他调整
模型大小调整
setheight处调整数值调整模型大小

模型大小调整带来的问题是css参数不一致,调整变小时会导致人物模型不贴页面底部,下图时我调整为1.5后的css参数,感觉还是比较合适的

点击事件调整
在lappdelegate.ts中找到onClickEnded函数
function onClickEnded(e: MouseEvent): void {
LAppDelegate.getInstance()._captured = false;
if (!LAppDelegate.getInstance()._view) {
LAppPal.printMessage('view notfound');
return;
}
const rect = (e.target as Element).getBoundingClientRect();
const posX: number = e.clientX - rect.left;
const posY: number = e.clientY - rect.top;
LAppDelegate.getInstance()._view.onTouchesMoved(posX, posY);//修改处
LAppDelegate.getInstance()._view.onTouchesEnded(posX, posY);
}
视线跟踪调整(在人物模型调整到右边的情况下)
在lappdelegate.ts中找到onMouseMoved函数
let posX: number = e.clientX;
let posY: number = e.clientY - window.innerHeight + canvas.height;
// 图像在网页的坐下角,简单处理坐标将超过画布边界坐标就等与边界坐标
posX = (posX > canvas.width) ? canvas.width : posX;
posY = (posY < 0) ? 0 : posY;
将上面这个代码改成
let posX: number = e.clientX - window.innerHeight + canvas.height;
let posY: number = e.clientY / 2;
// 图像在网页的坐下角,简单处理坐标将超过画布边界坐标就等与边界坐标
posX = (posX < 0) ? 0 : posX;
posY = (posY < 0) ? 0 : posY;
远程部署
HTML demo试验调用
1.将static目录复制到demo文件夹中

2.安装yarn并编译
Windows下安装yarn的三种方法 - 云+社区 - 腾讯云 (tencent.com)
2 - 安装 | Yarn - JavaScript 软件包管理器 | Yarn 中文文档 - Yarn 中文网 (yarnpkg.cn)
在demo目录下终端输入编译的指令yarn build,编译完成后,将dist文件夹中的bundle.js文件复制到Samples\TypeScript\Demo\static\live2d\js 文件夹下面
3.处理index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-compatible" content="IE-edge">
<meta name="viewport" content="width-device-width, initial-scale-1.0">
<link rel="stylesheet" type="text/css" href="./static/live2d/css/live2d.css"/>
<script type="text/javascript" src="./static/live2d/js/jquery.js"></script>
<!-- Pollyfill script -->
<script src="<https://unpkg.com/core-js-bundle@3.6.1/minified.js>"></script>
<!-- Live2DCubismCore script -->
<script src="./static/live2d/js/live2dcubismcore.js"></script>
<!-- Build script -->
<script src="./static/live2d/js/bundle.js"></script>
<title>Hello world</title>
</head>
<body>
Hello world
<div class="live2d-main">
<div class="live2d-tips"></div>
<!-- 这里可以定义画布的大小位置 -->
<canvas id="live2d" width="280" height="250" class="live2d"></canvas>
<div class="tool">
<span class="fui-home"></span>
<span class="fui-chat"></span>
<span class="fui-eye"></span>
<span class="fui-user"></span>
<span class="fui-photo"></span>
<span class="fui-info-circle"></span>
<span class="fui-cross"></span>
</div>
</div>
</body>
<script src="./static/live2d/js/message.js"></script>
<script type="text/javascript">
var resourcesPath = './static/live2d/model/'; // 指定资源文件(模型)保存的路径
var backImageName = ''; // 指定背景图片
var modelDir = 'Eileen,Haru,Hiyori,Mark,Natori,Rice,zwt'; // 指定需要加载的模型
init(); // 初始化模型,属于message.js文件
</script>
</html>
自行调整一下modelDir上面的变量,还有上面的路径
博客部署准备(1)——moc文件
经测试,在wordpress+sakura主题下,将index.html部分代码分别贴入header.php和footer.php,将static放入html目录下会加载资源失败。可能是CORS导致跨域加载失败问题
一般不需要设置:解决跨域加载失败
环境apache+centos
修改/etc/httpd/conf/http.conf

LoadModule headers_module modules/mod_headers.so
#目的是开启apache头信息自定义模块

Header set Access-Control-Allow-Origin *
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type"
Header set X-Content-Type-Options nosniff
*第一步、提前部署API
请务必搭建自己的API
这是整个前端的api,如果要设置自己的模型必须要安置在自己的服务器下
只要把内容down下来,放在www/html下就可以用,最好命名为api,http可以直接访问
第二步、配置jsdelivry+github的CDN
jsdelivry的使用自行搜索
以我自己的github两个repo为例


下面CDN里的static文件夹不需要copy
源代码来自于stevenjoezhang、yremp的github,并在此基础上稍作修改
第三步、修改waifu-tips
将图示60行改为自己github的asteroids.js的CDN地址

将图示73行改为自己github的live2d的地址

第四步、修改autoload.js
改为自己github的CDN地址

api地址请务必改为自己服务器api地址

header.php添加

footer.php添加

第六步、修改waifu.css——人物侧边栏

如图所示将display注释,即可开启人物模型侧边栏

HCLonely Blog - 给你的网页添加一个 moc3 格式的 Live2d 模型
更多设置如上链接
live2d api使用——人物模型修改
在API的module文件夹中按照文件格式添加相应文件,注意文件夹与其中文件命名开头一致。具体用法见上API使用链接
博客部署准备(2)——moc3
demo html
<html><head>
<meta charset="UTF-8">
<title>live2d-demo</title>
<!-- Live2DCubismCore -->
<script src="<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/frame/live2dcubismcore.min.js>"></script>
<!-- Include Pixi. -->
<script src="<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/frame/pixi.min.js>"></script>
<!-- Include Cubism Components. -->
<script src="<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/live2dcubismframework.js>"></script>
<script src="<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/live2dcubismpixi.js>"></script>
<!-- User's Script -->
<script src="<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/l2d.js>"></script>
<!-- <script src="<https://cdn.jsdelivr.net/gh/litstronger/live2d-moc3@master/js/main.js>"></script> -->
<script src="<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/main.js>"></script>
<script>
window.onload = () => {
var config = {
width: 800,
height: 600,
left: '0px',
bottom: '0px',
basePath: '<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/Resources>',
role: 'lafei_4',
opacity: 1,
mobile: false
}
var v = new Viewer(config);
}
</script>
<style>
</style>
</head>
<body>
<!-- Canvas -->
<div class="Canvas" id="L2dCanvas" style="position: fixed; "><canvas width="476" height="1047" style="touch-action: none; cursor: inherit; width: 476px; height: 1047px;"></canvas><canvas width="1144" height="899" style="touch-action: none; cursor: inherit; width: 1144px; height: 899px;"></canvas></div>
</body></html>
第一步、github+jsdelivry
如图构建自己的repo,代码是用usernamefull(github)的l2d repo

第二步、修改html
上述所有src的cdn链接全部改成自己repo
header.php在图示<!—添加live2dv3处添加

<!-- Live2DCubismCore -->
<script src="<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/frame/live2dcubismcore.min.js>"></script>
<!-- Include Pixi. -->
<script src="<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/frame/pixi.min.js>"></script>
<!-- Include Cubism Components. -->
<script src="<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/live2dcubismframework.js>"></script>
<script src="<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/live2dcubismpixi.js>"></script>
<!-- User's Script -->
<script src="<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/l2d.js>"></script>
<!-- <script src="<https://cdn.jsdelivr.net/gh/litstronger/live2d-moc3@master/js/main.js>"></script> -->
<script src="<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/main.js>"></script>
<script>
window.onload = () => {
var config = {
width: 800,
height: 600,
left: '0px',
bottom: '0px',
basePath: '<https://cdn.jsdelivr.net/gh/matoujin/l2d@v0.1/js/Resources>',
role: 'lafei_4',
opacity: 1,
mobile: false
}
var v = new Viewer(config);
}
</script>
其中,最下面的script标签内参数自行修改UsernameFull/l2d: 一个在线的live2d(moc3)预览实现,支持点击事件,后续应该会持续更新 (github.com),通过调整width height left bottom参数达到在页面中位置
footer.php在

在live2dv3处添加
<div class="Canvas" id="L2dCanvas" style="position: fixed; "></div>
此处一般不需要修改
更换人物模型
根据人物模型,在header.php的basepath中修改为想要的文件夹名称,同样也要注意文件命名。文件格式按照格式放好。
END
如有问题,联系QQ 1045939957
补充
最后一种方法存在的问题
在添加个人制作的模型时,容易出现人物模型太小的问题,建议在导出纹理集时使用较大像素可能能够解决问题。经测试,调整画布大小不能解决人物模型问题。
关于static文件夹方法的使用
bundle.js文件处理一定要确认无误,不然会爆出很多错误。模型大小可以通过css调整。
bundle.js文件对比
<script src="https://cdn.jsdelivr.net/gh/wangstong/mycdn/live2d/js/live2dcubismcore.js"></script>
<script src="https://cdn.jsdelivr.net/gh/wangstong/mycdn/live2d/js/bundle.js"></script>
经测试,可以直接用这个,然后模型用自己的库
Comments | 4 条评论
注意live cubism制作动画时使用第二个sdk

大佬,请问部署api的教程能不能发一下啊,网上搜到的都是moc的api,moc3不能用

@youlem 写文当时moc3好像只能用调用github的js项目或者把项目调到本地来用的方案(
后来就没有继续往下研究了
学习到了,哈哈哈跟你用的同一个wordpress模板