| @@ -6,4 +6,4 @@ NODE_ENV='development' | |||||
| VITE_APP_TITLE = 'Metavatar-PC' | VITE_APP_TITLE = 'Metavatar-PC' | ||||
| VITE_APP_PORT = 3000 | VITE_APP_PORT = 3000 | ||||
| ## VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' | ## VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' | ||||
| VITE_APP_BASE_API = 'https://mtest.metavatar.cc/C' | |||||
| VITE_APP_BASE_API = 'https://test.metavatar.cc/C' | |||||
| @@ -6,4 +6,4 @@ NODE_ENV='test' | |||||
| VITE_APP_TITLE = 'Metavatar-PC' | VITE_APP_TITLE = 'Metavatar-PC' | ||||
| VITE_APP_PORT = 3000 | VITE_APP_PORT = 3000 | ||||
| # VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' | # VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' | ||||
| VITE_APP_BASE_API = 'https://mtest.metavatar.cc/C' | |||||
| VITE_APP_BASE_API = 'https://test.metavatar.cc/C' | |||||
| @@ -5,7 +5,7 @@ | |||||
| <meta charset="UTF-8" /> | <meta charset="UTF-8" /> | ||||
| <link rel="icon" href="/favicon.ico" /> | <link rel="icon" href="/favicon.ico" /> | ||||
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
| <title>Metavatar-PC</title> | |||||
| <title>Metavatar-慧影</title> | |||||
| </head> | </head> | ||||
| <body> | <body> | ||||
| @@ -90,6 +90,16 @@ | |||||
| /> | /> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <!-- 字幕 --> | |||||
| <div | |||||
| v-show="props.Subtitles.SubtitlesSwitch" | |||||
| class="subtitles" | |||||
| :class="showBorderActive == 'subtitles' ? 'border' : ''" | |||||
| :style="SubtitlesStyle" | |||||
| @mousedown.stop="handleDragSubtitles" | |||||
| > | |||||
| {{ $t("createVideo.SubtitlesTip") }} | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </template> | </template> | ||||
| @@ -118,6 +128,9 @@ const props = defineProps({ | |||||
| showImgInfo: { | showImgInfo: { | ||||
| required: true, | required: true, | ||||
| }, | }, | ||||
| Subtitles: { | |||||
| required: true, | |||||
| }, | |||||
| }); | }); | ||||
| //#endregion -------------------------- | //#endregion -------------------------- | ||||
| @@ -148,6 +161,14 @@ const virtualStyle = computed(() => { | |||||
| }); | }); | ||||
| // 拖动盒子 | // 拖动盒子 | ||||
| const showBorderActive = ref(-1); //判断显示边框 | const showBorderActive = ref(-1); //判断显示边框 | ||||
| watch( | |||||
| () => props.materialList.virtual.id, | |||||
| (newValue, oldValue) => { | |||||
| showBorderActive.value = props.materialList.virtual.id; | |||||
| }, | |||||
| { deep: true } | |||||
| ); | |||||
| const fatherBox = ref(null); | const fatherBox = ref(null); | ||||
| const handleDrag = (item, event) => { | const handleDrag = (item, event) => { | ||||
| realImgUrl.value = item.material; | realImgUrl.value = item.material; | ||||
| @@ -188,45 +209,6 @@ const touchOver = ref({ | |||||
| }); | }); | ||||
| const scaleNum = ref(0.004); | const scaleNum = ref(0.004); | ||||
| // 改动版 | |||||
| // function changeScale(event) { | |||||
| // event.preventDefault(); | |||||
| // const x = event.clientX; | |||||
| // const y = event.clientY; | |||||
| // touchStart.pageX = x; | |||||
| // touchStart.pageY = y; | |||||
| // // 鼠标移动 | |||||
| // const onMouseMove = (event) => { | |||||
| // const MoveX = event.clientX; | |||||
| // const MoveY = event.clientY; | |||||
| // let flag = Math.sign(x - touchStart.pageX) == -1 ? true : false; | |||||
| // if (flag) { | |||||
| // // 限制最大缩放系数 | |||||
| // if (props.materialList.virtual.w > 1.3) return; | |||||
| // props.materialList.virtual.w += scaleNum.value; | |||||
| // // 更新坐标位置 | |||||
| // touchStart.pageX = MoveX; | |||||
| // touchStart.pageY = MoveY; | |||||
| // } else { | |||||
| // // 限制最小缩放系数 | |||||
| // if (props.materialList.virtual.w < 0.4) return; | |||||
| // props.materialList.virtual.w -= scaleNum.value; | |||||
| // // 更新坐标位置 | |||||
| // touchStart.pageX = MoveX; | |||||
| // touchStart.pageY = MoveY; | |||||
| // } | |||||
| // }; | |||||
| // // 鼠标抬起 | |||||
| // const onMouseUp = () => { | |||||
| // document.removeEventListener("mousemove", onMouseMove); | |||||
| // document.removeEventListener("mouseup", onMouseUp); | |||||
| // }; | |||||
| // document.addEventListener("mousemove", onMouseMove); | |||||
| // document.addEventListener("mouseup", onMouseUp); | |||||
| // } | |||||
| // 距离版 | // 距离版 | ||||
| function changeScale(event) { | function changeScale(event) { | ||||
| event.stopPropagation(); | event.stopPropagation(); | ||||
| @@ -400,6 +382,72 @@ watch( | |||||
| ); | ); | ||||
| //#endregion -------------------------- | //#endregion -------------------------- | ||||
| //#region 字幕 | |||||
| const SubtitlesStyle = computed(() => { | |||||
| let leftX = null; | |||||
| if (props.videoType == 1) { | |||||
| leftX = | |||||
| (1080 / 2 - props.Subtitles.SubtitlesWidth / 2) / props.proportion + "px"; | |||||
| } else if (props.videoType == 2) { | |||||
| leftX = | |||||
| (1920 / 2 - props.Subtitles.SubtitlesWidth / 2) / props.proportion + "px"; | |||||
| } | |||||
| console.log(props.Subtitles.SubtitlesWidth); | |||||
| return { | |||||
| width: props.Subtitles.SubtitlesWidth / props.proportion + "px", | |||||
| top: props.Subtitles.SubtitlesTop / props.proportion + "px", | |||||
| left: leftX, | |||||
| fontSize: props.Subtitles.SubtitlesSize / props.proportion + "px", | |||||
| fontFamily: props.Subtitles.SubtitlesFontFamily, | |||||
| color: props.Subtitles.SubtitlesColor, | |||||
| zIndex: 99, | |||||
| }; | |||||
| }); | |||||
| const handleDragSubtitles = (event) => { | |||||
| showBorderActive.value = "subtitles"; | |||||
| event.preventDefault(); | |||||
| // const startX = event.clientX; //保存初始值,避免闪烁 | |||||
| const startY = event.clientY; | |||||
| const startTop = props.Subtitles.SubtitlesTop; | |||||
| // 鼠标移动 | |||||
| const onMouseMove = (event) => { | |||||
| const deltaY = event.clientY - startY; | |||||
| props.Subtitles.SubtitlesTop = startTop + deltaY * props.proportion; | |||||
| }; | |||||
| // 鼠标抬起 | |||||
| const onMouseUp = () => { | |||||
| document.removeEventListener("mousemove", onMouseMove); | |||||
| document.removeEventListener("mouseup", onMouseUp); | |||||
| }; | |||||
| document.addEventListener("mousemove", onMouseMove); | |||||
| document.addEventListener("mouseup", onMouseUp); | |||||
| }; | |||||
| function rgbaToBgra(hexColor) { | |||||
| // 去除颜色前缀 | |||||
| hexColor = hexColor.replace("#", ""); | |||||
| // 分割颜色分量 | |||||
| const red = hexColor.substring(0, 2); | |||||
| const green = hexColor.substring(2, 4); | |||||
| const blue = hexColor.substring(4, 6); | |||||
| // 组合为新的颜色字符串 | |||||
| const convertedColor = `&H${blue}${green}${red}`; | |||||
| return convertedColor; | |||||
| } | |||||
| function BgraToRgba(hexColor) { | |||||
| // 去除颜色前缀 | |||||
| hexColor = hexColor.replace("&H", ""); | |||||
| // 分割颜色分量 | |||||
| const blue = hexColor.substring(0, 2); | |||||
| const green = hexColor.substring(2, 4); | |||||
| const red = hexColor.substring(4, 6); | |||||
| // 组合为新的颜色字符串 | |||||
| const convertedColor = `#${red}${green}${blue}`; | |||||
| return convertedColor; | |||||
| } | |||||
| //#endregion -------------------------- | |||||
| //#region | //#region | ||||
| //#endregion -------------------------- | //#endregion -------------------------- | ||||
| @@ -446,6 +494,16 @@ watch( | |||||
| user-select: none; | user-select: none; | ||||
| border: rgba(0, 0, 0, 0) 5px solid; | border: rgba(0, 0, 0, 0) 5px solid; | ||||
| } | } | ||||
| .subtitles { | |||||
| position: absolute; | |||||
| user-select: none; | |||||
| border: rgba(0, 0, 0, 0) 5px solid; | |||||
| padding: 20px; | |||||
| text-align: center; | |||||
| white-space: nowrap; | |||||
| overflow: hidden; | |||||
| text-overflow: ellipsis; | |||||
| } | |||||
| .border { | .border { | ||||
| border: 5px solid #00ff00; | border: 5px solid #00ff00; | ||||
| .stretchBox { | .stretchBox { | ||||
| @@ -13,7 +13,8 @@ export default { | |||||
| }, | }, | ||||
| // 登录页面国际化 | // 登录页面国际化 | ||||
| login: { | login: { | ||||
| title: "Metavatar-PC", | |||||
| // title: "Metavatar-MetaTalker", | |||||
| title: "MetaTalker", | |||||
| username: "Username", | username: "Username", | ||||
| email: "Phone", | email: "Phone", | ||||
| password: "Password", | password: "Password", | ||||
| @@ -98,6 +99,7 @@ export default { | |||||
| ratio:'ratio', | ratio:'ratio', | ||||
| entered:'entered', | entered:'entered', | ||||
| tooltip2:'Add Pause', | tooltip2:'Add Pause', | ||||
| SubtitlesTip:"Subtitles will be shown here", | |||||
| }, | }, | ||||
| // 我的视频 | // 我的视频 | ||||
| @@ -13,7 +13,7 @@ export default { | |||||
| }, | }, | ||||
| // 登录页面国际化 | // 登录页面国际化 | ||||
| login: { | login: { | ||||
| title: "Metavatar-PC", | |||||
| title: "慧影", | |||||
| username: "用户名", | username: "用户名", | ||||
| email: "手机号", | email: "手机号", | ||||
| password: "密码", | password: "密码", | ||||
| @@ -100,6 +100,7 @@ export default { | |||||
| ratio:'缩放倍率', | ratio:'缩放倍率', | ||||
| entered:'已输入', | entered:'已输入', | ||||
| tooltip2:'添加停顿', | tooltip2:'添加停顿', | ||||
| SubtitlesTip:"字幕将在此处展示", | |||||
| }, | }, | ||||
| // 我的视频 | // 我的视频 | ||||
| @@ -42,7 +42,7 @@ interface DefaultSettings { | |||||
| } | } | ||||
| const defaultSettings: DefaultSettings = { | const defaultSettings: DefaultSettings = { | ||||
| title: "Metavatar-PC", | |||||
| title: "Metavatar-慧影", | |||||
| showSettings: false, | showSettings: false, | ||||
| tagsView: false, | tagsView: false, | ||||
| fixedHeader: false, | fixedHeader: false, | ||||
| @@ -97,11 +97,13 @@ | |||||
| class="" | class="" | ||||
| > | > | ||||
| <EditPosition | <EditPosition | ||||
| ref="EditPositionDom" | |||||
| id="editPosition" | id="editPosition" | ||||
| :materialList="materialList" | :materialList="materialList" | ||||
| :videoType="videoType" | :videoType="videoType" | ||||
| :proportion="proportion" | :proportion="proportion" | ||||
| :showImgInfo="showImgInfo" | :showImgInfo="showImgInfo" | ||||
| :Subtitles="Subtitles" | |||||
| > | > | ||||
| </EditPosition> | </EditPosition> | ||||
| </div> | </div> | ||||
| @@ -463,15 +465,55 @@ | |||||
| </div> | </div> | ||||
| <!-- 字幕 --> | <!-- 字幕 --> | ||||
| <div v-if="tabItemActive == 4" class="tabContent tab4"> | <div v-if="tabItemActive == 4" class="tabContent tab4"> | ||||
| <!-- <div class="tab4Item"> | |||||
| <div v-if="imgUrl" class="SubtitlesSwitch"> | |||||
| <!-- 开关 --> | |||||
| <div class="tab4Item"> | |||||
| <div v-if="materialList.BGI.material" class="SubtitlesSwitch"> | |||||
| <p>{{ $t("createVideo.subtitles") }}</p> | <p>{{ $t("createVideo.subtitles") }}</p> | ||||
| <el-switch | <el-switch | ||||
| v-model="SubtitlesSwitch" | |||||
| v-model="Subtitles.SubtitlesSwitch" | |||||
| style="--el-switch-on-color: #000" | style="--el-switch-on-color: #000" | ||||
| /> | /> | ||||
| </div> | </div> | ||||
| </div> --> | |||||
| </div> | |||||
| <!-- 字体系列 --> | |||||
| <div class="tab4Item"> | |||||
| <div v-if="materialList.BGI.material" class="SubtitlesSwitch"> | |||||
| <p> | |||||
| {{ lanChange == "zh-cn" ? `字体` : `Font Family` }} | |||||
| </p> | |||||
| <el-select | |||||
| v-model="Subtitles.SubtitlesFontFamily" | |||||
| style="width: 80px" | |||||
| placeholder=" " | |||||
| size="default" | |||||
| > | |||||
| <el-option | |||||
| v-for="item in fontFamilyList" | |||||
| :key="item.value" | |||||
| :label="item.label" | |||||
| :value="item.value" | |||||
| /> | |||||
| </el-select> | |||||
| </div> | |||||
| </div> | |||||
| <!-- y轴 --> | |||||
| <div class="tab4Item"> | |||||
| <div v-if="materialList.BGI.material" class="SubtitlesSwitch"> | |||||
| <p> | |||||
| {{ lanChange == "zh-cn" ? `Y轴` : `Y-axis` }} | |||||
| </p> | |||||
| <el-input v-model="Subtitles.SubtitlesTop" width="30" /> | |||||
| </div> | |||||
| </div> | |||||
| <!-- 字号大小 --> | |||||
| <div class="tab4Item"> | |||||
| <div v-if="materialList.BGI.material" class="SubtitlesSwitch"> | |||||
| <p> | |||||
| {{ lanChange == "zh-cn" ? `字号大小` : `Font Size` }} | |||||
| </p> | |||||
| <el-input v-model="Subtitles.SubtitlesTop" width="30" /> | |||||
| </div> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <!-- 试听的mp3 --> | <!-- 试听的mp3 --> | ||||
| @@ -952,6 +994,44 @@ function delImg(id) { | |||||
| //#endregion ---------------------------- | //#endregion ---------------------------- | ||||
| //#region 字幕 | //#region 字幕 | ||||
| const Subtitles = reactive({ | |||||
| SubtitlesSwitch: false, //开关 | |||||
| SubtitlesFontFamily: "仿宋", //字体系列 | |||||
| SubtitlesTop: 400, //Y轴 | |||||
| SubtitlesSize: 70, //字号大小 | |||||
| SubtitlesColor: "#FFFFFF", //字色 | |||||
| SubtitlesWidth: 500, //宽度 | |||||
| colorList: [ | |||||
| "#FFFFFF", | |||||
| "#FF8080", | |||||
| "#000000", | |||||
| "#FF80FF", | |||||
| "#FF0000", | |||||
| "#00FF80", | |||||
| "#FF00FF", | |||||
| "#0080FF", | |||||
| "#00FF00", | |||||
| "#0000FF", | |||||
| "#000080", | |||||
| "#FFFF00", | |||||
| "#FF0080", | |||||
| "#FF8000", | |||||
| "#80FF00", | |||||
| "#00FFFF", | |||||
| ], | |||||
| fontFamilyList: [ | |||||
| { label: "仿宋", value: "仿宋" }, | |||||
| { label: "微软雅黑", value: "微软雅黑" }, | |||||
| { label: "新宋体", value: "新宋体" }, | |||||
| { label: "黑体", value: "黑体" }, | |||||
| { label: "楷体", value: "楷体" }, | |||||
| { label: "等线", value: "等线" }, | |||||
| { label: "Corbel", value: "Corbel" }, | |||||
| { label: "Terminal", value: "Terminal" }, | |||||
| { label: "Times New Roman", value: "Times New Roman" }, | |||||
| { label: "Verdana", value: "Verdana" }, | |||||
| ], | |||||
| }); | |||||
| //#endregion ---------------------------- | //#endregion ---------------------------- | ||||
| @@ -961,18 +1041,24 @@ const elementWidth = ref(null); | |||||
| onMounted(() => { | onMounted(() => { | ||||
| elementWidth.value = document.getElementById("editPosition").clientWidth; | elementWidth.value = document.getElementById("editPosition").clientWidth; | ||||
| }); | }); | ||||
| const EditPositionDom = ref(null); | |||||
| watch( | watch( | ||||
| () => videoType.value, | () => videoType.value, | ||||
| (newValue, oldValue) => { | |||||
| async (newValue, oldValue) => { | |||||
| // 根据横竖屏来确定比例 1竖2横 | // 根据横竖屏来确定比例 1竖2横 | ||||
| await nextTick(); | |||||
| elementWidth.value = document.getElementById("editPosition").clientWidth; | |||||
| console.log(elementWidth.value); | |||||
| if (videoType.value == 1) { | if (videoType.value == 1) { | ||||
| // proportion.value = 1080 / elementWidth.value; | |||||
| proportion.value = 1080 / 432; | |||||
| proportion.value = 1080 / elementWidth.value; | |||||
| // proportion.value = 1080 / 432; | |||||
| } else if (videoType.value == 2) { | } else if (videoType.value == 2) { | ||||
| proportion.value = 1920 / 768; | |||||
| // proportion.value = 1920 / 768; | |||||
| proportion.value = 1920 / elementWidth.value; | proportion.value = 1920 / elementWidth.value; | ||||
| } | } | ||||
| console.log(proportion.value); | |||||
| Subtitles.SubtitlesWidth = elementWidth.value * 0.7 * proportion.value; | |||||
| // console.log(EditPositionDom.value); | |||||
| console.log(proportion.value, "比例"); | |||||
| }, | }, | ||||
| { deep: true } | { deep: true } | ||||
| ); | ); | ||||
| @@ -993,9 +1079,9 @@ async function getPersonPatch() { | |||||
| materialList.virtual = { | materialList.virtual = { | ||||
| ...materialList.virtual, | ...materialList.virtual, | ||||
| x: 50, | x: 50, | ||||
| y: 50, | |||||
| y: 10, | |||||
| z: 0, | z: 0, | ||||
| w: 1, | |||||
| w: 0.55, | |||||
| h: 1, | h: 1, | ||||
| }; | }; | ||||
| // } | // } | ||||
| @@ -1689,8 +1775,23 @@ onMounted(async () => { | |||||
| .tab4 { | .tab4 { | ||||
| display: flex; | display: flex; | ||||
| justify-content: flex-start; | justify-content: flex-start; | ||||
| align-content: flex-start; | |||||
| flex-wrap: wrap; | |||||
| .tab4Item { | .tab4Item { | ||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| width: 30%; | width: 30%; | ||||
| background-color: #f1e5e5; | |||||
| text-align: center; | |||||
| padding: 10px; | |||||
| height: 80px; | |||||
| border-radius: 10px; | |||||
| margin: auto; | |||||
| margin-bottom: 10px; | |||||
| display: none; | |||||
| } | |||||
| .SubtitlesSwitch { | |||||
| width: 100%; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||