邃芒慧影、口播(PC) https://neuver.metavatar.cc/
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

493 líneas
14 KiB

  1. <template>
  2. <div class="myPage">
  3. <!-- 主要显示 -->
  4. <div
  5. :class="props.videoType == 1 ? 'content1' : 'content2'"
  6. id="content"
  7. :style="bgStyle"
  8. ref="fatherBox"
  9. >
  10. <!-- 数字人的图片 -->
  11. <div
  12. class="virtual"
  13. :class="showBorderActive == materialList.virtual.id ? 'border' : ''"
  14. @mousedown="handleDrag(materialList.virtual.id, $event)"
  15. :style="virtualStyle"
  16. >
  17. <img id="virtualImg" :src="materialList.virtual.material" alt="" />
  18. <div ref="box1" class="stretchBox box1"></div>
  19. <div class="stretchBox box2"></div>
  20. <div class="stretchBox box3"></div>
  21. <div
  22. v-show="showBorderActive == materialList.virtual.id"
  23. ref="box4"
  24. @mousedown.stop="changeScale"
  25. class="stretchBox box4"
  26. >
  27. <img
  28. style="width: 100px; height: 100px"
  29. src="../assets/img/Scale.png"
  30. alt=""
  31. />
  32. </div>
  33. </div>
  34. <!-- 素材图的图片 -->
  35. <div
  36. v-for="(item, index) in materialList.scList"
  37. :key="item.id"
  38. class="scListItem"
  39. :class="showBorderActive == item.id ? 'border' : ''"
  40. @mousedown="handleDragSc(item.id, index, $event)"
  41. :style="{
  42. top: item.y + 'px',
  43. left: item.x + 'px',
  44. transform: 'scale(' + item.w / props.proportion + ') ',
  45. transformOrigin: 'top left',
  46. zIndex: item.z,
  47. }"
  48. >
  49. <img id="scListItemImg" :src="item.material" alt="" />
  50. <div ref="box1" class="stretchBox box1"></div>
  51. <div
  52. v-show="showBorderActive == item.id"
  53. class="stretchBox box2"
  54. @click="delScListItem(index)"
  55. >
  56. <img
  57. style="width: 100px; height: 100px"
  58. src="../assets/img/delete2.png"
  59. alt=""
  60. />
  61. </div>
  62. <div class="stretchBox box3"></div>
  63. <div
  64. v-show="showBorderActive == item.id"
  65. ref="box4"
  66. @mousedown.stop="changeScaleSc(index, $event)"
  67. class="stretchBox box4"
  68. >
  69. <img
  70. style="width: 100px; height: 100px"
  71. src="../assets/img/Scale.png"
  72. alt=""
  73. />
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. </template>
  79. <script setup>
  80. //#region 导入
  81. import { useI18n } from "vue-i18n";
  82. //#endregion --------------------------
  83. const { locale } = useI18n();
  84. const lanChange = ref(locale);
  85. //#region 父组件传参
  86. const props = defineProps({
  87. // isLoading: {
  88. // required: true, //是否必传
  89. // },
  90. materialList: {
  91. required: true,
  92. },
  93. videoType: {
  94. required: true,
  95. },
  96. proportion: {
  97. required: true,
  98. },
  99. showImgInfo: {
  100. required: true,
  101. },
  102. });
  103. //#endregion --------------------------
  104. //#region 大盒子样式
  105. const bgStyle = computed(() => {
  106. return {
  107. // width: '1080px',
  108. // height: '1920px',
  109. // transform: 'scale(0.2)',
  110. backgroundImage: `url(${props.materialList.BGI.material})`,
  111. backgroundSize: "cover",
  112. backgroundPosition: "center",
  113. };
  114. });
  115. //#endregion --------------------------
  116. //#region 数字人逻辑
  117. // 计算属性来计算盒子位置和大小
  118. const virtualStyle = computed(() => {
  119. return {
  120. top: props.materialList.virtual.y + "px",
  121. left: props.materialList.virtual.x + "px",
  122. transform:
  123. "scale(" + props.materialList.virtual.w / props.proportion + ") ",
  124. transformOrigin: "top left",
  125. zIndex: props.materialList.virtual.z,
  126. };
  127. });
  128. // 拖动盒子
  129. const showBorderActive = ref(null); //判断显示边框
  130. const fatherBox = ref(null);
  131. const handleDrag = (id, event) => {
  132. showBorderActive.value = id;
  133. event.preventDefault();
  134. const imageElement = fatherBox.value;
  135. const startX = event.clientX; //保存初始值,避免闪烁
  136. const startY = event.clientY;
  137. const startLeft = props.materialList.virtual.x;
  138. const startTop = props.materialList.virtual.y;
  139. // 鼠标移动
  140. const onMouseMove = (event) => {
  141. const deltaX = event.clientX - startX;
  142. const deltaY = event.clientY - startY;
  143. props.materialList.virtual.x = startLeft + deltaX;
  144. props.materialList.virtual.y = startTop + deltaY;
  145. };
  146. // 鼠标抬起
  147. const onMouseUp = () => {
  148. document.removeEventListener("mousemove", onMouseMove);
  149. document.removeEventListener("mouseup", onMouseUp);
  150. };
  151. document.addEventListener("mousemove", onMouseMove);
  152. document.addEventListener("mouseup", onMouseUp);
  153. };
  154. // 缩放盒子
  155. const touchStart = ref({
  156. pageX: null,
  157. pageY: null,
  158. });
  159. const touchOver = ref({
  160. pageX: null,
  161. pageY: null,
  162. });
  163. const scaleNum = ref(0.004);
  164. // 初始版
  165. // function changeScale(event) {
  166. // event.preventDefault();
  167. // const x = event.clientX;
  168. // const y = event.clientY;
  169. // // touchStart = {
  170. // // pageX: x,
  171. // // pageY: y,
  172. // // };
  173. // touchStart.pageX = x;
  174. // touchStart.pageY = y;
  175. // // 鼠标移动
  176. // const onMouseMove = (event) => {
  177. // const MoveX = event.clientX;
  178. // const MoveY = event.clientY;
  179. // const flag = Math.sign(x - touchStart.pageX) == -1 ? true : false;
  180. // if (flag) {
  181. // // 限制最大缩放系数
  182. // if (props.materialList.virtual.w > 1.3) return;
  183. // props.materialList.virtual.w += scaleNum.value;
  184. // // 更新坐标位置
  185. // // touchStart = {
  186. // // pageX: MoveX,
  187. // // pageY: MoveY,
  188. // // };
  189. // touchStart.pageX = MoveX;
  190. // touchStart.pageY = MoveY;
  191. // } else {
  192. // // 限制最小缩放系数
  193. // if (props.materialList.virtual.w < 0.4) return;
  194. // props.materialList.virtual.w -= scaleNum.value;
  195. // // 更新坐标位置
  196. // // touchStart = {
  197. // // pageX: MoveX,
  198. // // pageY: MoveY,
  199. // // };
  200. // touchStart.pageX = MoveX;
  201. // touchStart.pageY = MoveY;
  202. // }
  203. // };
  204. // // 鼠标抬起
  205. // const onMouseUp = () => {
  206. // document.removeEventListener("mousemove", onMouseMove);
  207. // document.removeEventListener("mouseup", onMouseUp);
  208. // };
  209. // document.addEventListener("mousemove", onMouseMove);
  210. // document.addEventListener("mouseup", onMouseUp);
  211. // }
  212. // 改动版
  213. function changeScale(event) {
  214. event.preventDefault();
  215. const x = event.clientX;
  216. const y = event.clientY;
  217. touchStart.pageX = x;
  218. touchStart.pageY = y;
  219. // 鼠标移动
  220. const onMouseMove = (event) => {
  221. const MoveX = event.clientX;
  222. const MoveY = event.clientY;
  223. let flag = Math.sign(x - touchStart.pageX) == -1 ? true : false;
  224. if (flag) {
  225. // 限制最大缩放系数
  226. if (props.materialList.virtual.w > 1.3) return;
  227. props.materialList.virtual.w += scaleNum.value;
  228. // 更新坐标位置
  229. touchStart.pageX = MoveX;
  230. touchStart.pageY = MoveY;
  231. } else {
  232. // 限制最小缩放系数
  233. if (props.materialList.virtual.w < 0.4) return;
  234. props.materialList.virtual.w -= scaleNum.value;
  235. // 更新坐标位置
  236. touchStart.pageX = MoveX;
  237. touchStart.pageY = MoveY;
  238. }
  239. };
  240. // 鼠标抬起
  241. const onMouseUp = () => {
  242. document.removeEventListener("mousemove", onMouseMove);
  243. document.removeEventListener("mouseup", onMouseUp);
  244. };
  245. document.addEventListener("mousemove", onMouseMove);
  246. document.addEventListener("mouseup", onMouseUp);
  247. }
  248. const box1 = ref(null);
  249. const box2 = ref(null);
  250. const box3 = ref(null);
  251. const box4 = ref(null);
  252. // 距离版
  253. // function changeScale(event) {
  254. // const box1Element = box1.value;
  255. // const box4Element = box4.value;
  256. // if (!box1Element || !box4Element) {
  257. // return;
  258. // }
  259. // touchStart.pageX = event.clientX;
  260. // touchStart.pageY = event.clientY;
  261. // const box1Rect = box1Element.getBoundingClientRect();
  262. // const box4Rect = box4Element.getBoundingClientRect();
  263. // const boxDistance = Math.sqrt(
  264. // (box1Rect.left - box4Rect.left) ** 2 + (box1Rect.top - box4Rect.top) ** 2
  265. // ).toFixed(0);
  266. // const onMouseMove = (event) => {
  267. // const x = event.clientX;
  268. // const y = event.clientY;
  269. // const deltaX = touchStart.pageX - x;
  270. // const deltaY = touchStart.pageY - y;
  271. // const boxDistance2 = Math.sqrt(deltaX ** 2 + deltaY ** 2).toFixed(0);
  272. // if (deltaX < 0) {
  273. // props.materialList.virtual.w = Math.min(
  274. // Math.max((boxDistance + boxDistance2) / boxDistance, 0.4),
  275. // 1.3
  276. // );
  277. // } else {
  278. // props.materialList.virtual.w = Math.min(
  279. // Math.max((boxDistance - boxDistance2) / boxDistance, 0.4),
  280. // 1.3
  281. // );
  282. // }
  283. // // touchOver.pageX = event.clientX;
  284. // // touchOver.pageY = event.clientY;
  285. // };
  286. // // 鼠标抬起
  287. // const onMouseUp = () => {
  288. // // touchStart.pageX = touchOver.pageX;
  289. // // touchStart.pageY = touchOver.pageY;
  290. // document.removeEventListener("mousemove", onMouseMove);
  291. // document.removeEventListener("mouseup", onMouseUp);
  292. // };
  293. // document.addEventListener("mousemove", onMouseMove);
  294. // document.addEventListener("mouseup", onMouseUp);
  295. // }
  296. //#endregion --------------------------
  297. //#region 素材图逻辑
  298. const handleDragSc = (id, index, event) => {
  299. showBorderActive.value = id;
  300. event.preventDefault();
  301. const imageElement = fatherBox.value;
  302. const startX = event.clientX; //保存初始值,避免闪烁
  303. const startY = event.clientY;
  304. const startLeft = props.materialList.scList[index].x;
  305. const startTop = props.materialList.scList[index].y;
  306. // 鼠标移动
  307. const onMouseMove = (event) => {
  308. const deltaX = event.clientX - startX;
  309. const deltaY = event.clientY - startY;
  310. props.materialList.scList[index].x = startLeft + deltaX;
  311. props.materialList.scList[index].y = startTop + deltaY;
  312. };
  313. // 鼠标抬起
  314. const onMouseUp = () => {
  315. document.removeEventListener("mousemove", onMouseMove);
  316. document.removeEventListener("mouseup", onMouseUp);
  317. };
  318. document.addEventListener("mousemove", onMouseMove);
  319. document.addEventListener("mouseup", onMouseUp);
  320. };
  321. function changeScaleSc(index, event) {
  322. event.preventDefault();
  323. const x = event.clientX;
  324. const y = event.clientY;
  325. touchStart.pageX = x;
  326. touchStart.pageY = y;
  327. // 鼠标移动
  328. const onMouseMove = (event) => {
  329. let MoveX = event.clientX;
  330. let MoveY = event.clientY;
  331. let flag = Math.sign(x - touchStart.pageX) == -1 ? true : false;
  332. if (flag) {
  333. // 限制最大缩放系数
  334. if (props.materialList.scList[index].w > 1.3) return;
  335. props.materialList.scList[index].w += scaleNum.value;
  336. // 更新坐标位置
  337. touchStart.pageX = MoveX;
  338. touchStart.pageY = MoveY;
  339. } else {
  340. // 限制最小缩放系数
  341. if (props.materialList.scList[index].w < 0.4) return;
  342. props.materialList.scList[index].w -= scaleNum.value;
  343. // 更新坐标位置
  344. touchStart.pageX = MoveX;
  345. touchStart.pageY = MoveY;
  346. }
  347. };
  348. // 鼠标抬起
  349. const onMouseUp = () => {
  350. document.removeEventListener("mousemove", onMouseMove);
  351. document.removeEventListener("mouseup", onMouseUp);
  352. };
  353. document.addEventListener("mousemove", onMouseMove);
  354. document.addEventListener("mouseup", onMouseUp);
  355. }
  356. function delScListItem(index) {
  357. const msg =
  358. lanChange.value == "zh-cn"
  359. ? "确定删除素材吗吗?"
  360. : "Are you sure you want to delete the footage?";
  361. const notice = lanChange.value == "zh-cn" ? "提示" : "Notice";
  362. const confirm = lanChange.value == "zh-cn" ? "确定" : "Confirm";
  363. const cancel = lanChange.value == "zh-cn" ? "取消" : "Cancel";
  364. ElMessageBox.confirm(msg, notice, {
  365. confirmButtonText: confirm,
  366. cancelButtonText: cancel,
  367. }).then(() => {
  368. props.materialList.scList.splice(index, 1);
  369. });
  370. }
  371. //#endregion --------------------------
  372. //#region 控制台回显
  373. watch(
  374. () => showBorderActive.value,
  375. (newValue, oldValue) => {
  376. props.showImgInfo.id = showBorderActive.value;
  377. },
  378. { deep: true }
  379. );
  380. //#endregion --------------------------
  381. //#region
  382. //#endregion --------------------------
  383. </script>
  384. <style lang="scss" scoped>
  385. .myPage {
  386. // height: 768px;
  387. // width: 432px;
  388. }
  389. .content1 {
  390. position: relative;
  391. height: 768px;
  392. width: 432px;
  393. overflow: hidden;
  394. }
  395. .content2 {
  396. position: relative;
  397. height: 432px;
  398. width: 768px;
  399. overflow: hidden;
  400. }
  401. .virtual {
  402. position: absolute;
  403. user-select: none;
  404. border: rgba(0, 0, 0, 0) 5px solid;
  405. }
  406. .scListItem {
  407. position: absolute;
  408. user-select: none;
  409. border: rgba(0, 0, 0, 0) 5px solid;
  410. }
  411. .border {
  412. border: 5px solid #00ff00;
  413. .stretchBox {
  414. opacity: 1;
  415. position: absolute;
  416. width: 20px;
  417. height: 20px;
  418. background-color: #7264f5;
  419. }
  420. .box1 {
  421. top: -10px;
  422. left: -10px;
  423. cursor: nwse-resize;
  424. display: none;
  425. }
  426. .box2 {
  427. top: -50px;
  428. left: 100%;
  429. transform: translateX(-50px);
  430. // cursor: nesw-resize;
  431. cursor: pointer;
  432. background-color: rgba(0, 0, 0, 0);
  433. width: 100px;
  434. height: 100px;
  435. img {
  436. width: 100px;
  437. height: 100px;
  438. }
  439. }
  440. .box3 {
  441. top: 100%;
  442. left: -10px;
  443. transform: translateY(-10px);
  444. cursor: nesw-resize;
  445. display: none;
  446. }
  447. .box4 {
  448. top: 100%;
  449. left: 100%;
  450. transform: translate(-50px, -50px);
  451. cursor: nwse-resize;
  452. // background-color: rgba(0, 0, 0, 0);
  453. background-color: #fff;
  454. width: 100px;
  455. height: 100px;
  456. border-radius: 50px;
  457. img {
  458. position: absolute;
  459. top: 50%;
  460. left: 50%;
  461. transform: translate(-50%, -50%) rotate(90deg);
  462. max-width: 65px;
  463. max-height: 65px;
  464. }
  465. }
  466. }
  467. </style>