UNPKG

@tomiaa/live2d

Version:

开箱即用的 Live2d

169 lines (168 loc) 10.8 kB
import './style.css'; var f = Object.defineProperty; var y = (l, i, t) => i in l ? f(l, i, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[i] = t; var o = (l, i, t) => (y(l, typeof i != "symbol" ? i + "" : i, t), t); import { Hitokoto as x } from "@tomiaa/hitokoto"; import { createNamespacs as I, drag as P, loadAsyncJs as h, randomInteger as C } from "@tomiaa/utils"; import { Live2d_3_ModelList as M, Live2dModelList as S } from "./modelList.js"; import "./index.scss.js"; const r = I("live2d"), _ = '<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" ><path fill="currentColor" d="M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32zm0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32zm448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32zm-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32zM195.2 195.2a32 32 0 0 1 45.248 0L376.32 331.008a32 32 0 0 1-45.248 45.248L195.2 240.448a32 32 0 0 1 0-45.248zm452.544 452.544a32 32 0 0 1 45.248 0L828.8 783.552a32 32 0 0 1-45.248 45.248L647.744 692.992a32 32 0 0 1 0-45.248zM828.8 195.264a32 32 0 0 1 0 45.184L692.992 376.32a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0zm-452.544 452.48a32 32 0 0 1 0 45.248L240.448 828.8a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0z"></path></svg>', b = '<svg width="30" height="30" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M42 19H5.99998" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" /> <path d="M30 7L42 19" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" /> <path d="M6.79897 29H42.799" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" /> <path d="M6.79895 29L18.799 41" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" /> </svg>', H = '<svg width="30" height="30" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" > <path fill-rule="evenodd" clip-rule="evenodd" d="M20.7301 27.1255C22.7185 25.833 25.2815 25.833 27.2699 27.1255L42.8202 37.2331C43.556 37.7114 44 38.5295 44 39.4071C44 40.8391 42.8391 42 41.4071 42H6.59288C5.16087 42 4 40.8391 4 39.4071C4 38.5295 4.44395 37.7114 5.17979 37.2331L20.7301 27.1255Z" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" /> <path d="M24 25C24 25 30 16.3137 30 13C30 9.68629 27.3137 7 24 7C20.6863 7 18 9.68629 18 13" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" /> </svg>'; class E { constructor(i) { o(this, "options", { el: "#live2d", loadLive2d_2: !0, loadLive2d_3: !0, playLoadingAnimation: !0, showLoading: !0, showControl: !0, iApplicationOptions: {}, maxWidth: 400, minWidth: 200, aspectRatio: [10, 9], randomPeople: !0, allowDrag: !0, hitokoto: !0 }); o(this, "el"); o(this, "canvas"); o(this, "Live2DModel"); o(this, "app"); o(this, "loading", !1); o(this, "model"); o(this, "modelList", []); o(this, "currentModelOption"); o(this, "personIndex", 0); o(this, "clothingIndex", 0); o(this, "elLoading"); o(this, "elControl"); o(this, "elSwitchPerson"); o(this, "elSwitchClothing"); o(this, "elHitokoto"); o(this, "hitokoto"); Object.assign(this.options, i); const { el: t } = this.options; typeof t == "string" ? this.el = document.querySelector(t) : this.el = t, this.el.classList.add(r.b()), this.init(); } get getJsBaseURL() { return this.options.jsBaseURL || "https://tomiaa12.github.io/live2d/public"; } get getLive2d_2_ModelBaseURL() { return this.options.live2d_2_ModelBaseURL || this.getJsBaseURL; } get getLive2d_3_ModelBaseURL() { return this.options.live2d_2_ModelBaseURL || this.getJsBaseURL; } async init() { var i, t, s, e; await ((t = (i = this.options).beforeInit) == null ? void 0 : t.call(i, { options: this.options, modelList: this.modelList })), this.options.allowDrag && P({ el: this.el }), await this.loadJS(), this.createPIXI(), await this.loadModelList(), this.addLoadingSvg(), this.addControls(), this.setPersonIndex(), await this.loadModel(), window.addEventListener("resize", this.onresize.bind(this)), this.createHitokoto(), (e = (s = this.options).afterInit) == null || e.call(s, { options: this.options, modelList: this.modelList, currentModelOption: this.currentModelOption, Live2DModel: this.Live2DModel, app: this.app }); } async loadJS() { await Promise.all([ h(this.getJsBaseURL + "/js/pixi.min.js"), h(this.getJsBaseURL + "/js/live2d.min.js"), h(this.getJsBaseURL + "/js/live2dcubismcore.min.js") ]), await h(this.getJsBaseURL + "/js/index.min.js"), this.Live2DModel = window.PIXI.live2d.Live2DModel; } createPIXI() { this.canvas || (this.canvas = document.createElement("canvas"), this.el.appendChild(this.canvas), this.canvas.addEventListener("click", this.animation.bind(this))), this.app = new window.PIXI.Application({ view: this.canvas, width: 400, height: 300, backgroundAlpha: 0, ...this.options.iApplicationOptions }); } async loadModelList() { if (!this.options.loadLive2d_2 && !this.options.loadLive2d_3) return console.error("loadLive2d_2与loadLive2d_3至少加载一种!"), Promise.reject(); this.options.loadLive2d_3 && (this.modelList = [...this.modelList, ...M]), this.options.loadLive2d_2 && (this.modelList = [...this.modelList, ...S]); } addLoadingSvg() { this.options.showLoading && (this.elLoading = document.createElement("i"), this.elLoading.innerHTML = _, this.elLoading.classList.add(r.e("loading")), this.el.appendChild(this.elLoading)); } addControls() { this.options.showControl && (this.elControl = document.createElement("div"), this.elControl.classList.add(r.e("control")), this.elSwitchPerson = document.createElement("i"), this.elSwitchPerson.innerHTML = b, this.elSwitchPerson.setAttribute("data-tip", "切换人物"), this.elSwitchPerson.addEventListener("click", this.switchPerson.bind(this)), this.elControl.appendChild(this.elSwitchPerson), this.elSwitchClothing = document.createElement("i"), this.elSwitchClothing.innerHTML = H, this.elSwitchClothing.setAttribute("data-tip", "更换服装"), this.elSwitchClothing.addEventListener( "click", this.switchClothing.bind(this) ), this.elControl.appendChild(this.elSwitchClothing), this.el.appendChild(this.elControl)); } async loadModel() { var t, s, e; this.loading = !0, this.el.style.pointerEvents = "none", this.elLoading && (this.elLoading.style.display = "block"), this.elControl && (this.elControl.style.display = "none"), this.elHitokoto && (this.elHitokoto.style.display = "none", (t = this.hitokoto) == null || t.getData()), (e = (s = this.model) == null ? void 0 : s.destroy) == null || e.call(s); const i = this.currentModelOption.version === 3 ? this.getLive2d_3_ModelBaseURL : this.getLive2d_2_ModelBaseURL; try { this.model = await this.Live2DModel.from( i + this.currentModelOption.list[this.clothingIndex] ); } catch { this.elLoading && (this.elLoading.style.display = "none"); } this.loading = !1, this.el.style.pointerEvents = "auto", this.elLoading && (this.elLoading.style.display = "none"), this.elControl && (this.elControl.style.display = "block"), this.elHitokoto && (this.elHitokoto.style.display = "block"), this.app.stage.addChild(this.model), this.onresize(), this.options.playLoadingAnimation && this.animation("login"); } setPersonIndex() { this.options.randomPeople ? this.personIndex = C(0, this.modelList.length - 1) : ++this.personIndex >= this.modelList.length && (this.personIndex = 0), this.currentModelOption = this.modelList[this.personIndex], this.elSwitchClothing.style.display = this.currentModelOption.list.length > 1 ? "block" : "none"; } onresize() { var p, g, L, w, m, v, k, u; const i = this.model; if (!i) return; const t = this.currentModelOption, s = this.app; let e = window.innerWidth * 0.3; e > this.options.maxWidth && (e = this.options.maxWidth), e < this.options.minWidth && (e = this.options.minWidth); const n = e / (((p = t == null ? void 0 : t.aspectRatio) == null ? void 0 : p[0]) || this.options.aspectRatio[0]) * (((g = t == null ? void 0 : t.aspectRatio) == null ? void 0 : g[1]) || this.options.aspectRatio[1]); s.view.style.width = e + "px", s.view.style.height = n + "px", s.renderer.resize(e, n); const c = i.width > i.height ? e / i.width : n / i.height; i.width *= c, i.height *= c; let a, d; typeof (t == null ? void 0 : t.scale) == "number" ? a = d = t == null ? void 0 : t.scale : (a = (L = t == null ? void 0 : t.scale) == null ? void 0 : L.x, d = (w = t == null ? void 0 : t.scale) == null ? void 0 : w.y), i.width *= ((m = t == null ? void 0 : t.stretch) == null ? void 0 : m.width) || 1, i.height *= ((v = t == null ? void 0 : t.stretch) == null ? void 0 : v.height) || 1, i.scale = new window.PIXI.Point( i.scale.x * (a || 1), i.scale.y * (d || 1) ), i.position = new window.PIXI.Point( e - i.width + (((k = t == null ? void 0 : t.position) == null ? void 0 : k.x) || 0), n - i.height + (((u = t == null ? void 0 : t.position) == null ? void 0 : u.y) || 0) ); } animation(i) { const t = this.model; if (typeof i == "string") { t.motion(i); return; } const [s] = t.hitTest((i == null ? void 0 : i.offsetX) || 0, (i == null ? void 0 : i.offsetY) || 0), e = Object.keys( t.internalModel.motionManager.definitions ).filter((n) => n !== "login"); s ? t.motion(e.filter((n) => n.includes(s))[0]) : t.motion(e[C(0, e.length - 1)]); } switchPerson() { event == null || event.stopPropagation(), this.clothingIndex = 0, this.setPersonIndex(), this.loadModel(); } switchClothing() { event == null || event.stopPropagation(), ++this.clothingIndex >= this.currentModelOption.list.length && (this.clothingIndex = 0), this.loadModel(); } createHitokoto() { this.options.hitokoto && (this.elHitokoto = document.createElement("div"), this.el.appendChild(this.elHitokoto), this.elHitokoto.addEventListener("mousedown", (i) => { i.stopPropagation(); }), this.hitokoto = new x({ el: this.elHitokoto, ...this.options.hitokotoOptions })); } destroy() { window.removeEventListener("resize", this.onresize), this.el.innerHTML = ""; } } export { E as Live2d, E as default };