欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue3中如何使用live2D

 更新時(shí)間:2024年10月10日 11:09:51   作者:Jinuss  
本文介紹了如何在Vue3項(xiàng)目中整合Live2D技術(shù),從Live2D的基本介紹到在Vue3中的具體實(shí)現(xiàn)方法,Live2D技術(shù)允許開(kāi)發(fā)者將二維圖像轉(zhuǎn)化為可動(dòng)畫(huà)的三維模型,主要應(yīng)用于游戲、虛擬角色等領(lǐng)域,文章詳細(xì)說(shuō)明了在vue3項(xiàng)目中使用Live2D的步驟,感興趣的朋友一起看看吧

概述

本文將介紹如何在vue3項(xiàng)目中使用Live2D

Live2D 介紹

Live2D 是什么

Live2D 是一種用于將二維圖像轉(zhuǎn)化為可動(dòng)畫(huà)三維模型的技術(shù),主要應(yīng)用于游戲、虛擬角色和互動(dòng)應(yīng)用中。它允許開(kāi)發(fā)者通過(guò)對(duì)靜態(tài)圖像進(jìn)行分層和建模,使角色在不同角度下能夠進(jìn)行流暢的動(dòng)作和表情變化。

Live2D 主要特點(diǎn)

  • 動(dòng)態(tài)表現(xiàn):Live2D 可以讓角色在不改變?cè)紙D像的情況下,實(shí)現(xiàn)多種動(dòng)作和表情,例如眨眼、微笑、轉(zhuǎn)頭等。
  • 用戶(hù)交互:它可以與用戶(hù)的輸入進(jìn)行互動(dòng),比如鼠標(biāo)移動(dòng)或觸摸屏幕時(shí),角色會(huì)作出相應(yīng)的反饋。
  • 應(yīng)用廣泛:被廣泛應(yīng)用于手機(jī)游戲、動(dòng)畫(huà)、虛擬直播、社交軟件等領(lǐng)域。
  • 易于使用:通過(guò) Live2D 提供的工具(如 Live2D Cubism),藝術(shù)家可以方便地創(chuàng)建和編輯模型,無(wú)需深入的編程知識(shí)。

Live2D 效果

vue3 中使用 Live2D

如果前端項(xiàng)目是用vite搭建,則需要在index.html中引入live2d.min.js庫(kù),因?yàn)樵?vue 組件中引入會(huì)報(bào)錯(cuò)。

封裝 Live 組件

template

template部分如下:

<template>
  <div
    :class="{
      'vue-live2d': true,
      'vue-live2d-on-left': true,
      // 'vue-live2d-on-right': direction === 'right',
    }"
    :style="{
      width: `300px`,
      height: `300px`,
      position: 'absolute',
      left: '10px',
      bottom: '20px',
    }"
    @mouseover="openLive2dTool"
    @mouseout="closeLive2dTool"
  >
    <div
      v-show="true"
      v-html="data.tipText"
      :class="{
        'vue-live2d-tip': true,
        'vue-live2d-tip-on-top': true,
        // 'vue-live2d-tip-on-bottom': tipPosition === 'bottom',
      }"
    ></div>
    <canvas
      :id="customId"
      v-show="mainShow"
      :class="{
        'vue-live2d-main': true,
        'vue-live2d-main-on-left': true,
        // 'vue-live2d-main-on-right': direction === 'right',
      }"
      width="300"
      height="300"
    >
    </canvas>
    <div v-show="toolShow" class="vue-live2d-tool">
      <span
        v-for="(tool, index) in tools"
        :key="index"
        :class="tool.className"
        v-html="tool.svg"
        @click="tool.click"
      />
    </div>
    <div
      v-show="toggleShow"
      @click="openLive2dMain"
      :class="{
        'vue-live2d-toggle': true,
        'vue-live2d-toggle-on-left': true,
        // 'vue-live2d-toggle-on-right': direction === 'right',
      }"
    >
      <span>Kanban girl</span>
    </div>
  </div>
</template>

template部分主要是定義 UI 部分,以及綁定界面點(diǎn)擊和hove的事件,Live2d的模型是在 canvas 中繪制的。

核心邏輯
核心邏輯主要就是加載Live2D的模型以及定義事件,其實(shí)現(xiàn)如下:

<script setup>
import { onMounted, nextTick, ref, computed } from "vue";
import tips from "./options/tips";
// const model = ["Potion-Maker/Pio", "school-2017-costume-yellow"];
const model = ["ShizukuTalk/shizuku-48", "default"];
const apiPath = "https://evgo2017.com/api/live2d-static-api/indexes";
let [modelPath, modelTexturesId] = model;
const customId = "vue-live2d-main";
let messageTimer = null;
const data = ref({
  containerDisplay: {
    tip: false,
    main: true,
    tool: false,
    toggle: false,
  },
  tipText: "vue-live2d Kanban girl",
  modelTexturesId: modelTexturesId,
});
const changeLive2dSize = () => {
  document.querySelector(
    `#${customId}`
  ).outerHTML = `<canvas id=${customId} width="300" height="300" class="vue-live2d-main"></canvas>`;
  loadModel();
};
const loadModel = () => {
  window.loadlive2d(
    customId,
    `${apiPath}/${modelPath}/${data.value.modelTexturesId}.json`
  );
  console.log(
    `Live2D 模型 ${modelPath},服裝 ${data.value.modelTexturesId} 加載完成`
  );
};
const loadRandModel = () => {
  http({
    url: `${apiPath}/models.json`,
    success: (data) => {
      const models = data.filter(({ modelPath: i }) => i !== modelPath);
      const { modelPath: j, modelIntroduce } =
        models[Math.floor(Math.random() * models.length)];
      modelPath = j;
      showMessage(`${modelIntroduce}`, 4000);
      loadRandTextures(true);
    },
  });
};
const loadRandTextures = (isAfterRandModel = false) => {
  http({
    url: `${apiPath}/${modelPath}/textures.json`,
    success: (resp) => {
      const modelTexturesIds = resp.filter(
        (modelTexturesId) => modelTexturesId !== data.value.modelTexturesId
      );
      data.value.modelTexturesId =
        modelTexturesIds[Math.floor(Math.random() * modelTexturesIds.length)];
      loadModel();
      if (!isAfterRandModel) {
        showMessage("我的新衣服好看嘛?", 4000);
      }
    },
  });
};
const showMessage = (msg = "", timeout = 6000) => {
  if (messageTimer) {
    clearTimeout(messageTimer);
    messageTimer = null;
  } else {
    data.value.containerDisplay.tip = true;
  }
  data.value.tipText = msg;
  messageTimer = setTimeout(() => {
    data.value.containerDisplay.tip = false;
    messageTimer = null;
  }, timeout);
};
const takePhoto = () => {
  showMessage("照好了嘛,留個(gè)紀(jì)念吖~");
  window.Live2D.captureName = "photo.png";
  window.Live2D.captureFrame = true;
};
const showHitokoto = () => {
  http({
    url: "https://v1.hitokoto.cn",
    success: ({ hitokoto, id, creator, from }) => {
      showMessage(
        `${hitokoto} <br> - by <a  rel="external nofollow" >${creator}</a> from 《${from} 》`
      );
    },
  });
};
const closeLive2dMain = () => {
  data.value.containerDisplay.main = false;
};
const openLive2dMain = () => {
  data.value.containerDisplay.main = true;
};
const closeLive2dTool = () => {
  data.value.containerDisplay.tool = false;
};
const openLive2dTool = () => {
  data.value.containerDisplay.tool = true;
};
const loadEvent = () => {
  for (const event in tips) {
    for (const { selector, texts } of tips[event]) {
      const dom =
        selector === "document" ? document : document.querySelector(selector);
      if (dom == null) {
        continue;
      }
      dom.addEventListener(event, () => {
        const msg = texts[Math.floor(Math.random() * texts.length)];
        showMessage(msg, 2000);
      });
    }
  }
};
const http = ({ url, success }) => {
  const xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if (xhr.status >= 200 || xhr.status < 300 || xhr.status === 304) {
        success && xhr.response && success(JSON.parse(xhr.response));
      } else {
        console.error(xhr);
      }
    }
  };
  xhr.open("GET", url);
  xhr.send(null);
};
nextTick(() => {
  loadEvent();
});
onMounted(() => {
  loadModel();
});
defineProps({
  tips: {
    default: () => tips,
    type: Object,
  },
  width: {
    default: 0,
    type: Number,
  },
  height: {
    default: 0,
    type: Number,
  },
  size: {
    default: 255,
    type: Number,
  },
});
const tipShow = computed(() => {
  return mainShow && data.value.containerDisplay.tip;
});
const mainShow = computed(() => {
  return data.value.containerDisplay.main;
});
const toolShow = computed(() => {
  return mainShow && data.value.containerDisplay.tool;
});
const toggleShow = computed(() => {
  return !mainShow;
});
const tools = ref([
  {
    className: "custom-fa-comment",
    svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" height="20px" width="20px"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M256 32C114.6 32 0 125.1 0 240c0 49.6 21.4 95 57 130.7C44.5 421.1 2.7 466 2.2 466.5c-2.2 2.3-2.8 5.7-1.5 8.7S4.8 480 8 480c66.3 0 116-31.8 140.6-51.4 32.7 12.3 69 19.4 107.4 19.4 141.4 0 256-93.1 256-208S397.4 32 256 32z"/></svg>',
    click: showHitokoto,
  },
  {
    className: "custom-fa-user-circle",
    svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512" fill="currentColor" height="20px" width="20px"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 96c48.6 0 88 39.4 88 88s-39.4 88-88 88-88-39.4-88-88 39.4-88 88-88zm0 344c-58.7 0-111.3-26.6-146.5-68.2 18.8-35.4 55.6-59.8 98.5-59.8 2.4 0 4.8.4 7.1 1.1 13 4.2 26.6 6.9 40.9 6.9 14.3 0 28-2.7 40.9-6.9 2.3-.7 4.7-1.1 7.1-1.1 42.9 0 79.7 24.4 98.5 59.8C359.3 421.4 306.7 448 248 448z"/></svg>',
    click: loadRandModel,
  },
  {
    className: "custom-fa-street-view",
    svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" height="20px" width="20px"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M367.9 329.76c-4.62 5.3-9.78 10.1-15.9 13.65v22.94c66.52 9.34 112 28.05 112 49.65 0 30.93-93.12 56-208 56S48 446.93 48 416c0-21.6 45.48-40.3 112-49.65v-22.94c-6.12-3.55-11.28-8.35-15.9-13.65C58.87 345.34 0 378.05 0 416c0 53.02 114.62 96 256 96s256-42.98 256-96c0-37.95-58.87-70.66-144.1-86.24zM256 128c35.35 0 64-28.65 64-64S291.35 0 256 0s-64 28.65-64 64 28.65 64 64 64zm-64 192v96c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-96c17.67 0 32-14.33 32-32v-96c0-26.51-21.49-48-48-48h-11.8c-11.07 5.03-23.26 8-36.2 8s-25.13-2.97-36.2-8H208c-26.51 0-48 21.49-48 48v96c0 17.67 14.33 32 32 32z"/></svg>',
    click: loadRandTextures,
  },
  {
    className: "custom-fa-camera-retro",
    svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" height="20px" width="20px"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M48 32C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48H48zm0 32h106c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H38c-3.3 0-6-2.7-6-6V80c0-8.8 7.2-16 16-16zm426 96H38c-3.3 0-6-2.7-6-6v-36c0-3.3 2.7-6 6-6h138l30.2-45.3c1.1-1.7 3-2.7 5-2.7H464c8.8 0 16 7.2 16 16v74c0 3.3-2.7 6-6 6zM256 424c-66.2 0-120-53.8-120-120s53.8-120 120-120 120 53.8 120 120-53.8 120-120 120zm0-208c-48.5 0-88 39.5-88 88s39.5 88 88 88 88-39.5 88-88-39.5-88-88-88zm-48 104c-8.8 0-16-7.2-16-16 0-35.3 28.7-64 64-64 8.8 0 16 7.2 16 16s-7.2 16-16 16c-17.6 0-32 14.4-32 32 0 8.8-7.2 16-16 16z"/></svg>',
    click: takePhoto,
  },
  {
    className: "custom-fa-info-circle",
    svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" height="20px" width="20px"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z"/></svg>',
    click: () => {},
  },
  {
    className: "custom-fa-times",
    svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="-40 -40 432 592" fill="currentColor" height="20px" width="20px"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"/></svg>',
    click: closeLive2dMain,
  },
]);
</script>

Demo地址

Demo地址和具體示例可參考:https://github.com/Jinuss/maps

到此這篇關(guān)于vue3中使用live2D的文章就介紹到這了,更多相關(guān)vue3 使用live2D內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 6種Vue中常用數(shù)據(jù)加密方式的使用詳解

    6種Vue中常用數(shù)據(jù)加密方式的使用詳解

    在Vue.js項(xiàng)目中,你可能需要執(zhí)行數(shù)據(jù)加密以確保敏感信息的安全,這篇文章為大家整理了Vue中常用的6種數(shù)據(jù)加密方式的使用,需要的小伙伴可以參考下
    2024-03-03
  • vue如何限制只能輸入正負(fù)數(shù)及小數(shù)

    vue如何限制只能輸入正負(fù)數(shù)及小數(shù)

    這篇文章主要介紹了vue如何限制只能輸入正負(fù)數(shù)及小數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • 在Flask項(xiàng)目中集成并訪問(wèn)Vue前端項(xiàng)目的流程步驟

    在Flask項(xiàng)目中集成并訪問(wèn)Vue前端項(xiàng)目的流程步驟

    在現(xiàn)代?Web?開(kāi)發(fā)中,前后端分離的架構(gòu)模式越來(lái)越流行,前端通常使用?Vue、React?等框架開(kāi)發(fā),而后端則使用?Flask、Django?等框架提供?API?服務(wù),本文將詳細(xì)介紹如何在一個(gè)?Flask?項(xiàng)目中集成?Vue?前端項(xiàng)目,并確保能夠正確訪問(wèn)和運(yùn)行,需要的朋友可以參考下
    2025-03-03
  • Vue使用Tinymce富文本自定義toolbar按鈕的實(shí)踐

    Vue使用Tinymce富文本自定義toolbar按鈕的實(shí)踐

    本文主要介紹了Vue使用Tinymce富文本自定義toolbar按鈕,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • vue路由三種傳參方式詳細(xì)講解

    vue路由三種傳參方式詳細(xì)講解

    在Vue中有多種方式可以進(jìn)行路由跳轉(zhuǎn)并傳遞參數(shù),這篇文章主要給大家介紹了關(guān)于vue路由三種傳參方式的相關(guān)資料,文中介紹的方法分別包括params傳參、query傳參(顯示傳參)以及props傳參(路由組件傳參),,需要的朋友可以參考下
    2023-10-10
  • 利用v-viewer圖片預(yù)覽插件放大需要預(yù)覽的圖片

    利用v-viewer圖片預(yù)覽插件放大需要預(yù)覽的圖片

    本文介紹了v-viewer插件的安裝和使用步驟,包括npm安裝、在main.js文件中全局引入,以及常用的三種使用方式,文章提供了簡(jiǎn)單的布局頁(yè)面效果,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-10-10
  • vue實(shí)例中data使用return包裹的方法

    vue實(shí)例中data使用return包裹的方法

    今天小編就為大家分享一篇vue實(shí)例中data使用return包裹的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • Vue之表單事件數(shù)據(jù)綁定詳解

    Vue之表單事件數(shù)據(jù)綁定詳解

    這篇文章主要為大家介紹了Vue之表單事件的數(shù)據(jù)綁定,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助,希望能夠給你帶來(lái)幫助
    2021-11-11
  • vue升級(jí)之路之vue-router的使用教程

    vue升級(jí)之路之vue-router的使用教程

    自動(dòng)安裝的vue-router,會(huì)在src 文件夾下有個(gè)一個(gè) router -> index.js 文件 在 index.js 中創(chuàng)建 routers 對(duì)象,引入所需的組件并配置路徑。這篇文章主要介紹了vue-router的使用,需要的朋友可以參考下
    2018-08-08
  • vue3中的ref與reactive使用方法對(duì)比

    vue3中的ref與reactive使用方法對(duì)比

    Vue3 提供了兩個(gè)新的 API:ref 和 reactive,它們可以幫助我們更好地管理和處理響應(yīng)式數(shù)據(jù),這篇文章主要介紹了vue3中的ref與reactive的區(qū)別和使用方法,需要的朋友可以參考下
    2023-04-04

最新評(píng)論