Procházet zdrojové kódy

编辑素材位置及控制台

dev_YWQ
congzc před 1 rokem
rodič
revize
354d1b65bc
8 změnil soubory, kde provedl 914 přidání a 52 odebrání
  1. +26
    -0
      src/apis/createVideo.js
  2. +21
    -1
      src/apis/myCreating.js
  3. binární
      src/assets/img/delete2.png
  4. +339
    -6
      src/components/EditPosition copy.vue
  5. +319
    -29
      src/components/EditPosition.vue
  6. +3
    -3
      src/layout/index.vue
  7. +1
    -0
      src/types/components.d.ts
  8. +205
    -13
      src/views/createVideo/index.vue

+ 26
- 0
src/apis/createVideo.js Zobrazit soubor

@@ -150,3 +150,29 @@ export function personPatchApi(id) {
method: 'get'
})
}

/**
* @description:保存或修改用户作品
* @param {object} data
* @return data
*/
export function saveOrUpdateApi(data) {
return request({
url: `/api/userVideo/saveOrUpdate`,
method: 'post',
data: data
})
}

/**
* @description 生成视频
* @param {object} id
* @returns id
*/
export function createVideoApi(id) {
return request({
url: `/api/userVideo/createVideo`,
method: 'post',
data: { id }
})
}

+ 21
- 1
src/apis/myCreating.js Zobrazit soubor

@@ -6,9 +6,16 @@ import request from "@/utils/request.js";
* @params pageNum, pageSize
* @returns data
*/
// export function userPhotoVideoList(pageNum, pageSize, title) {
// return request({
// url: `/api/userPhotoVideo/list?pageNum=${pageNum}&pageSize=${pageSize}&title=${title}`,
// method: 'get'
// })
// }
export function userPhotoVideoList(pageNum, pageSize, title) {
let videoStatuss = [1, 2, 3, 4, 5, 6]
return request({
url: `/api/userPhotoVideo/list?pageNum=${pageNum}&pageSize=${pageSize}&title=${title}`,
url: `/api/userVideo/list?pageNum=${pageNum}&pageSize=${pageSize}&title=${title}&videoType=-1&videoStatuss=${videoStatuss}`,
method: 'get'
})
}
@@ -23,4 +30,17 @@ export function delUserPhotoVideoByID(videoID) {
url: `/api/userPhotoVideo/del?id=${videoID}`,
method: 'get'
})
}


/**
* @description 获取作品列表
* @param {number} pageParams (pageNum, pageSize)
* @returns data
*/
export function getVideoList(pageNum, pageSize, videoType, videoStatuss) {
return request({
url: `/api/userVideo/list?pageNum=${pageNum}&pageSize=${pageSize}&videoType=${videoType}&videoStatuss=${videoStatuss}`,
method: 'get'
})
}

binární
src/assets/img/delete2.png Zobrazit soubor

Před Za
Šířka: 128  |  Výška: 128  |  Velikost: 3.6 KiB

+ 339
- 6
src/components/EditPosition copy.vue Zobrazit soubor

@@ -15,15 +15,74 @@
:style="virtualStyle"
>
<img id="virtualImg" :src="materialList.virtual.material" alt="" />
<div class="stretchBox box1"></div>
<div ref="box1" class="stretchBox box1"></div>
<div class="stretchBox box2"></div>
<div class="stretchBox box3"></div>
<div class="stretchBox box4"></div>
<div
v-show="showBorderActive == materialList.virtual.id"
ref="box4"
@mousedown.stop="changeScale"
class="stretchBox box4"
>
<img
style="width: 100px; height: 100px"
src="../assets/img/Scale.png"
alt=""
/>
</div>
</div>
<!-- 素材图的图片 -->
<div
v-for="(item, index) in materialList.scList"
:key="item.id"
class="scListItem"
:class="showBorderActive == item.id ? 'border' : ''"
@mousedown="handleDragSc(item.id, index, $event)"
:style="{
top: item.y + 'px',
left: item.x + 'px',
transform: 'scale(' + item.w / props.proportion + ') ',
transformOrigin: 'top left',
zIndex: item.z,
}"
>
<img id="scListItemImg" :src="item.material" alt="" />
<div ref="box1" class="stretchBox box1"></div>
<div
v-show="showBorderActive == item.id"
class="stretchBox box2"
@click="delScListItem(index)"
>
<img
style="width: 100px; height: 100px"
src="../assets/img/delete2.png"
alt=""
/>
</div>
<div class="stretchBox box3"></div>
<div
v-show="showBorderActive == item.id"
ref="box4"
@mousedown.stop="changeScaleSc(index, $event)"
class="stretchBox box4"
>
<img
style="width: 100px; height: 100px"
src="../assets/img/Scale.png"
alt=""
/>
</div>
</div>
</div>
</div>
</template>
<script setup>
//#region 导入
import { useI18n } from "vue-i18n";
//#endregion --------------------------
const { locale } = useI18n();
const lanChange = ref(locale);
//#region 父组件传参
const props = defineProps({
// isLoading: {
@@ -38,6 +97,9 @@ const props = defineProps({
proportion: {
required: true,
},
showImgInfo: {
required: true,
},
});
//#endregion --------------------------
@@ -63,6 +125,7 @@ const virtualStyle = computed(() => {
transform:
"scale(" + props.materialList.virtual.w / props.proportion + ") ",
transformOrigin: "top left",
zIndex: props.materialList.virtual.z,
};
});
// 拖动盒子
@@ -94,6 +157,248 @@ const handleDrag = (id, event) => {
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
};
// 缩放盒子
const touchStart = ref({
pageX: null,
pageY: null,
});
const touchOver = ref({
pageX: null,
pageY: null,
});
const scaleNum = ref(0.004);
// 初始版
// function changeScale(event) {
// event.preventDefault();
// const x = event.clientX;
// const y = event.clientY;
// // touchStart = {
// // pageX: x,
// // pageY: y,
// // };
// touchStart.pageX = x;
// touchStart.pageY = y;
// // 鼠标移动
// const onMouseMove = (event) => {
// const MoveX = event.clientX;
// const MoveY = event.clientY;
// const 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,
// // pageY: MoveY,
// // };
// touchStart.pageX = MoveX;
// touchStart.pageY = MoveY;
// } else {
// // 限制最小缩放系数
// if (props.materialList.virtual.w < 0.4) return;
// props.materialList.virtual.w -= scaleNum.value;
// // 更新坐标位置
// // touchStart = {
// // pageX: MoveX,
// // pageY: MoveY,
// // };
// 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) {
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);
}
const box1 = ref(null);
const box2 = ref(null);
const box3 = ref(null);
const box4 = ref(null);
// 距离版
// function changeScale(event) {
// const box1Element = box1.value;
// const box4Element = box4.value;
// if (!box1Element || !box4Element) {
// return;
// }
// touchStart.pageX = event.clientX;
// touchStart.pageY = event.clientY;
// const box1Rect = box1Element.getBoundingClientRect();
// const box4Rect = box4Element.getBoundingClientRect();
// const boxDistance = Math.sqrt(
// (box1Rect.left - box4Rect.left) ** 2 + (box1Rect.top - box4Rect.top) ** 2
// ).toFixed(0);
// const onMouseMove = (event) => {
// const x = event.clientX;
// const y = event.clientY;
// const deltaX = touchStart.pageX - x;
// const deltaY = touchStart.pageY - y;
// const boxDistance2 = Math.sqrt(deltaX ** 2 + deltaY ** 2).toFixed(0);
// if (deltaX < 0) {
// props.materialList.virtual.w = Math.min(
// Math.max((boxDistance + boxDistance2) / boxDistance, 0.4),
// 1.3
// );
// } else {
// props.materialList.virtual.w = Math.min(
// Math.max((boxDistance - boxDistance2) / boxDistance, 0.4),
// 1.3
// );
// }
// // touchOver.pageX = event.clientX;
// // touchOver.pageY = event.clientY;
// };
// // 鼠标抬起
// const onMouseUp = () => {
// // touchStart.pageX = touchOver.pageX;
// // touchStart.pageY = touchOver.pageY;
// document.removeEventListener("mousemove", onMouseMove);
// document.removeEventListener("mouseup", onMouseUp);
// };
// document.addEventListener("mousemove", onMouseMove);
// document.addEventListener("mouseup", onMouseUp);
// }
//#endregion --------------------------
//#region 素材图逻辑
const handleDragSc = (id, index, event) => {
showBorderActive.value = id;
event.preventDefault();
const imageElement = fatherBox.value;
const startX = event.clientX; //保存初始值,避免闪烁
const startY = event.clientY;
const startLeft = props.materialList.scList[index].x;
const startTop = props.materialList.scList[index].y;
// 鼠标移动
const onMouseMove = (event) => {
const deltaX = event.clientX - startX;
const deltaY = event.clientY - startY;
props.materialList.scList[index].x = startLeft + deltaX;
props.materialList.scList[index].y = startTop + deltaY;
};
// 鼠标抬起
const onMouseUp = () => {
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", onMouseUp);
};
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
};
function changeScaleSc(index, event) {
event.preventDefault();
const x = event.clientX;
const y = event.clientY;
touchStart.pageX = x;
touchStart.pageY = y;
// 鼠标移动
const onMouseMove = (event) => {
let MoveX = event.clientX;
let MoveY = event.clientY;
let flag = Math.sign(x - touchStart.pageX) == -1 ? true : false;
if (flag) {
// 限制最大缩放系数
if (props.materialList.scList[index].w > 1.3) return;
props.materialList.scList[index].w += scaleNum.value;
// 更新坐标位置
touchStart.pageX = MoveX;
touchStart.pageY = MoveY;
} else {
// 限制最小缩放系数
if (props.materialList.scList[index].w < 0.4) return;
props.materialList.scList[index].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 delScListItem(index) {
const msg =
lanChange.value == "zh-cn"
? "确定删除素材吗吗?"
: "Are you sure you want to delete the footage?";
const notice = lanChange.value == "zh-cn" ? "提示" : "Notice";
const confirm = lanChange.value == "zh-cn" ? "确定" : "Confirm";
const cancel = lanChange.value == "zh-cn" ? "取消" : "Cancel";
ElMessageBox.confirm(msg, notice, {
confirmButtonText: confirm,
cancelButtonText: cancel,
}).then(() => {
props.materialList.scList.splice(index, 1);
});
}
//#endregion --------------------------
//#region 控制台回显
watch(
() => showBorderActive.value,
(newValue, oldValue) => {
props.showImgInfo.id = showBorderActive.value;
},
{ deep: true }
);
//#endregion --------------------------
//#region
@@ -122,6 +427,11 @@ const handleDrag = (id, event) => {
user-select: none;
border: rgba(0, 0, 0, 0) 5px solid;
}
.scListItem {
position: absolute;
user-select: none;
border: rgba(0, 0, 0, 0) 5px solid;
}
.border {
border: 5px solid #00ff00;
.stretchBox {
@@ -135,25 +445,48 @@ const handleDrag = (id, event) => {
top: -10px;
left: -10px;
cursor: nwse-resize;
display: none;
}
.box2 {
top: -10px;
top: -50px;
left: 100%;
transform: translateX(-10px);
cursor: nesw-resize;
transform: translateX(-50px);
// cursor: nesw-resize;
cursor: pointer;
background-color: rgba(0, 0, 0, 0);
width: 100px;
height: 100px;
img {
width: 100px;
height: 100px;
}
}
.box3 {
top: 100%;
left: -10px;
transform: translateY(-10px);
cursor: nesw-resize;
display: none;
}
.box4 {
top: 100%;
left: 100%;
transform: translate(-10px, -10px);
transform: translate(-50px, -50px);
cursor: nwse-resize;
// background-color: rgba(0, 0, 0, 0);
background-color: #fff;
width: 100px;
height: 100px;
border-radius: 50px;
img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(90deg);
max-width: 65px;
max-height: 65px;
}
}
}
</style>

+ 319
- 29
src/components/EditPosition.vue Zobrazit soubor

@@ -15,15 +15,74 @@
:style="virtualStyle"
>
<img id="virtualImg" :src="materialList.virtual.material" alt="" />
<div class="stretchBox box1"></div>
<div ref="box1" class="stretchBox box1"></div>
<div class="stretchBox box2"></div>
<div class="stretchBox box3"></div>
<div @mousedown.stop="changeScale" class="stretchBox box4"></div>
<div
v-show="showBorderActive == materialList.virtual.id"
ref="box4"
@mousedown.stop="changeScale"
class="stretchBox box4"
>
<img
style="width: 100px; height: 100px"
src="../assets/img/Scale.png"
alt=""
/>
</div>
</div>
<!-- 素材图的图片 -->
<div
v-for="(item, index) in materialList.scList"
:key="item.id"
class="scListItem"
:class="showBorderActive == item.id ? 'border' : ''"
@mousedown="handleDragSc(item.id, index, $event)"
:style="{
top: item.y / props.proportion + 'px',
left: item.x / props.proportion + 'px',
transform: 'scale(' + item.w / props.proportion + ') ',
transformOrigin: 'top left',
zIndex: item.z,
}"
>
<img id="scListItemImg" :src="item.material" alt="" />
<div ref="box1" class="stretchBox box1"></div>
<div
v-show="showBorderActive == item.id"
class="stretchBox box2"
@click="delScListItem(index)"
>
<img
style="width: 100px; height: 100px"
src="../assets/img/delete2.png"
alt=""
/>
</div>
<div class="stretchBox box3"></div>
<div
v-show="showBorderActive == item.id"
ref="box4"
@mousedown.stop="changeScaleSc(index, $event)"
class="stretchBox box4"
>
<img
style="width: 100px; height: 100px"
src="../assets/img/Scale.png"
alt=""
/>
</div>
</div>
</div>
</div>
</template>
<script setup>
//#region 导入
import { useI18n } from "vue-i18n";
//#endregion --------------------------
const { locale } = useI18n();
const lanChange = ref(locale);
//#region 父组件传参
const props = defineProps({
// isLoading: {
@@ -38,6 +97,9 @@ const props = defineProps({
proportion: {
required: true,
},
showImgInfo: {
required: true,
},
});
//#endregion --------------------------
@@ -58,11 +120,12 @@ const bgStyle = computed(() => {
// 计算属性来计算盒子位置和大小
const virtualStyle = computed(() => {
return {
top: props.materialList.virtual.y + "px",
left: props.materialList.virtual.x + "px",
top: props.materialList.virtual.y / props.proportion + "px",
left: props.materialList.virtual.x / props.proportion + "px",
transform:
"scale(" + props.materialList.virtual.w / props.proportion + ") ",
transformOrigin: "top left",
zIndex: props.materialList.virtual.z,
};
});
// 拖动盒子
@@ -81,8 +144,8 @@ const handleDrag = (id, event) => {
const onMouseMove = (event) => {
const deltaX = event.clientX - startX;
const deltaY = event.clientY - startY;
props.materialList.virtual.x = startLeft + deltaX;
props.materialList.virtual.y = startTop + deltaY;
props.materialList.virtual.x = startLeft + deltaX * props.proportion;
props.materialList.virtual.y = startTop + deltaY * props.proportion;
};
// 鼠标抬起
@@ -95,42 +158,92 @@ const handleDrag = (id, event) => {
document.addEventListener("mouseup", onMouseUp);
};
// 缩放盒子
let touchStart = reactive({
const touchStart = ref({
pageX: null,
pageY: null,
});
const touchOver = ref({
pageX: null,
pageY: null,
});
const scaleNum = ref(0.003);
const scaleNum = ref(0.004);
// 初始版
// function changeScale(event) {
// event.preventDefault();
// const x = event.clientX;
// const y = event.clientY;
// // touchStart = {
// // pageX: x,
// // pageY: y,
// // };
// touchStart.pageX = x;
// touchStart.pageY = y;
// // 鼠标移动
// const onMouseMove = (event) => {
// const MoveX = event.clientX;
// const MoveY = event.clientY;
// const 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,
// // pageY: MoveY,
// // };
// touchStart.pageX = MoveX;
// touchStart.pageY = MoveY;
// } else {
// // 限制最小缩放系数
// if (props.materialList.virtual.w < 0.4) return;
// props.materialList.virtual.w -= scaleNum.value;
// // 更新坐标位置
// // touchStart = {
// // pageX: MoveX,
// // pageY: MoveY,
// // };
// 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) {
event.preventDefault();
const x = event.clientX;
const y = event.clientY;
touchStart = {
pageX: x,
pageY: y,
};
touchStart.pageX = x;
touchStart.pageY = y;
// 鼠标移动
const onMouseMove = (event) => {
const MoveX = event.clientX;
const MoveY = event.clientY;
const flag = Math.sign(x - touchStart.pageX) == -1 ? true : false;
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,
pageY: MoveY,
};
touchStart.pageX = MoveX;
touchStart.pageY = MoveY;
} else {
// 限制最小缩放系数
if (props.materialList.virtual.w < 0.4) return;
props.materialList.virtual.w -= scaleNum.value;
// 更新坐标位置
touchStart = {
pageX: MoveX,
pageY: MoveY,
};
touchStart.pageX = MoveX;
touchStart.pageY = MoveY;
}
};
@@ -143,6 +256,149 @@ function changeScale(event) {
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
}
const box1 = ref(null);
const box2 = ref(null);
const box3 = ref(null);
const box4 = ref(null);
// 距离版
// function changeScale(event) {
// const box1Element = box1.value;
// const box4Element = box4.value;
// if (!box1Element || !box4Element) {
// return;
// }
// touchStart.pageX = event.clientX;
// touchStart.pageY = event.clientY;
// const box1Rect = box1Element.getBoundingClientRect();
// const box4Rect = box4Element.getBoundingClientRect();
// const boxDistance = Math.sqrt(
// (box1Rect.left - box4Rect.left) ** 2 + (box1Rect.top - box4Rect.top) ** 2
// ).toFixed(0);
// const onMouseMove = (event) => {
// const x = event.clientX;
// const y = event.clientY;
// const deltaX = touchStart.pageX - x;
// const deltaY = touchStart.pageY - y;
// const boxDistance2 = Math.sqrt(deltaX ** 2 + deltaY ** 2).toFixed(0);
// if (deltaX < 0) {
// props.materialList.virtual.w = Math.min(
// Math.max((boxDistance + boxDistance2) / boxDistance, 0.4),
// 1.3
// );
// } else {
// props.materialList.virtual.w = Math.min(
// Math.max((boxDistance - boxDistance2) / boxDistance, 0.4),
// 1.3
// );
// }
// // touchOver.pageX = event.clientX;
// // touchOver.pageY = event.clientY;
// };
// // 鼠标抬起
// const onMouseUp = () => {
// // touchStart.pageX = touchOver.pageX;
// // touchStart.pageY = touchOver.pageY;
// document.removeEventListener("mousemove", onMouseMove);
// document.removeEventListener("mouseup", onMouseUp);
// };
// document.addEventListener("mousemove", onMouseMove);
// document.addEventListener("mouseup", onMouseUp);
// }
//#endregion --------------------------
//#region 素材图逻辑
const handleDragSc = (id, index, event) => {
showBorderActive.value = id;
event.preventDefault();
const imageElement = fatherBox.value;
const startX = event.clientX; //保存初始值,避免闪烁
const startY = event.clientY;
const startLeft = props.materialList.scList[index].x;
const startTop = props.materialList.scList[index].y;
// 鼠标移动
const onMouseMove = (event) => {
const deltaX = event.clientX - startX;
const deltaY = event.clientY - startY;
props.materialList.scList[index].x = startLeft + deltaX * props.proportion;
props.materialList.scList[index].y = startTop + deltaY * props.proportion;
};
// 鼠标抬起
const onMouseUp = () => {
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", onMouseUp);
};
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
};
function changeScaleSc(index, event) {
event.preventDefault();
const x = event.clientX;
const y = event.clientY;
touchStart.pageX = x;
touchStart.pageY = y;
// 鼠标移动
const onMouseMove = (event) => {
let MoveX = event.clientX;
let MoveY = event.clientY;
let flag = Math.sign(x - touchStart.pageX) == -1 ? true : false;
if (flag) {
// 限制最大缩放系数
if (props.materialList.scList[index].w > 1.3) return;
props.materialList.scList[index].w += scaleNum.value;
// 更新坐标位置
touchStart.pageX = MoveX;
touchStart.pageY = MoveY;
} else {
// 限制最小缩放系数
if (props.materialList.scList[index].w < 0.4) return;
props.materialList.scList[index].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 delScListItem(index) {
const msg =
lanChange.value == "zh-cn"
? "确定删除素材吗吗?"
: "Are you sure you want to delete the footage?";
const notice = lanChange.value == "zh-cn" ? "提示" : "Notice";
const confirm = lanChange.value == "zh-cn" ? "确定" : "Confirm";
const cancel = lanChange.value == "zh-cn" ? "取消" : "Cancel";
ElMessageBox.confirm(msg, notice, {
confirmButtonText: confirm,
cancelButtonText: cancel,
}).then(() => {
props.materialList.scList.splice(index, 1);
});
}
//#endregion --------------------------
//#region 控制台回显
watch(
() => showBorderActive.value,
(newValue, oldValue) => {
props.showImgInfo.id = showBorderActive.value;
},
{ deep: true }
);
//#endregion --------------------------
//#region
@@ -153,17 +409,23 @@ function changeScale(event) {
.myPage {
// height: 768px;
// width: 432px;
width: 100%;
height: 100%;
}
.content1 {
position: relative;
height: 768px;
width: 432px;
// height: 768px;
// width: 432px;
width: 100%;
height: 100%;
overflow: hidden;
}
.content2 {
position: relative;
height: 432px;
width: 768px;
// height: 432px;
// width: 768px;
width: 100%;
height: 100%;
overflow: hidden;
}
.virtual {
@@ -171,6 +433,11 @@ function changeScale(event) {
user-select: none;
border: rgba(0, 0, 0, 0) 5px solid;
}
.scListItem {
position: absolute;
user-select: none;
border: rgba(0, 0, 0, 0) 5px solid;
}
.border {
border: 5px solid #00ff00;
.stretchBox {
@@ -184,25 +451,48 @@ function changeScale(event) {
top: -10px;
left: -10px;
cursor: nwse-resize;
display: none;
}
.box2 {
top: -10px;
top: -50px;
left: 100%;
transform: translateX(-10px);
cursor: nesw-resize;
transform: translateX(-50px);
// cursor: nesw-resize;
cursor: pointer;
background-color: rgba(0, 0, 0, 0);
width: 100px;
height: 100px;
img {
width: 100px;
height: 100px;
}
}
.box3 {
top: 100%;
left: -10px;
transform: translateY(-10px);
cursor: nesw-resize;
display: none;
}
.box4 {
top: 100%;
left: 100%;
transform: translate(-10px, -10px);
transform: translate(-50px, -50px);
cursor: nwse-resize;
// background-color: rgba(0, 0, 0, 0);
background-color: #fff;
width: 100px;
height: 100px;
border-radius: 50px;
img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(90deg);
max-width: 65px;
max-height: 65px;
}
}
}
</style>

+ 3
- 3
src/layout/index.vue Zobrazit soubor

@@ -17,12 +17,12 @@
</div>
{{ $t("createVideo.title") }}
</div>
<div class="myRouter-item" @click="router.push('/moveImg')">
<!-- <div class="myRouter-item" @click="router.push('/myCreating')">
<div class="icon">
<el-icon><i-ep-edit /></el-icon>
</div>
{{ $t("createVideo.title") }}
</div>
{{ $t("myCreating.title") }}
</div> -->
</div>
</div>
<!-- 右边显示部分 -->


+ 1
- 0
src/types/components.d.ts Zobrazit soubor

@@ -24,6 +24,7 @@ declare module '@vue/runtime-core' {
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElRow: typeof import('element-plus/es')['ElRow']


+ 205
- 13
src/views/createVideo/index.vue Zobrazit soubor

@@ -92,20 +92,68 @@
<div class="showModelImgBox">
<!-- <img :src="modelImg" alt="" /> -->
<!-- 编辑图片位置组件 -->
<EditPosition
id="editPosition"
class="EditPosition"
:materialList="materialList"
:videoType="videoType"
:proportion="proportion"
<div
:class="videoType == 1 ? 'EditPositionBox1' : 'EditPositionBox2'"
class=""
>
</EditPosition>
<EditPosition
id="editPosition"
:materialList="materialList"
:videoType="videoType"
:proportion="proportion"
:showImgInfo="showImgInfo"
>
</EditPosition>
</div>
<!-- 控制台 -->
<div v-if="showImgInfo.data" class="showImgInfoBox">
<!-- <div class="infoItem">
</div> -->
<div class="ItemName">横坐标</div>
<div class="ItemValue">
<el-input-number
v-model="showImgInfo.data.x"
size="large"
controls-position="right"
/>
</div>
<div class="ItemName">纵坐标</div>
<div class="ItemValue">
<el-input-number
v-model="showImgInfo.data.y"
size="large"
controls-position="right"
/>
</div>
<div class="ItemName">层级</div>
<div class="ItemValue">
<el-input-number
v-model="showImgInfo.data.z"
:min="1"
:max="10"
size="large"
controls-position="right"
/>
</div>
<div class="ItemName">缩放倍率</div>
<div class="ItemValue">
<el-input-number
v-model="showImgInfo.data.w"
:min="0.4"
:max="1.3"
size="large"
controls-position="right"
/>
</div>
</div>
<!-- 保存视频和生成视频 -->
<div class="btnBox" v-show="!showChooseModel">
<div class="customBtn" style="margin-right: 15px">
{{ $t("createVideo.saveVideo") }}
</div>
<div class="customBtn">{{ $t("createVideo.generateVideo") }}</div>
<div class="customBtn">
{{ $t("createVideo.generateVideo") }}
</div>
</div>
</div>
</div>
@@ -416,6 +464,8 @@ import {
personSCIListApi,
delImgApi,
personPatchApi,
saveOrUpdateApi,
createVideoApi,
} from "@/apis/createVideo";
import { useI18n } from "vue-i18n";
import Recorder from "js-audio-recorder"; //mp3插件
@@ -534,7 +584,8 @@ const tabItemActive = ref(1);
//#endregion ----------------------------

//#region 文案及其音频
const title = ref(null);
const title =
lanChange.value == "zh-cn" ? ref("未定义标题") : ref("Undefined Title");
const textareaContent = ref("");
function insertIcon() {
const textarea = document.getElementById("textInputId");
@@ -743,6 +794,8 @@ async function reGetpersonBGIList() {
const bjImgActive = ref(null);
function selectBjImg(img) {
bjImgActive.value = img.id;
materialList.BGI.material = img.material;
materialList.BGI.id = img.id;
}
//#endregion ----------------------------

@@ -812,6 +865,7 @@ async function reGetpersonSCIList() {
const scImgActive = ref(null);
function selectScImg(img) {
scImgActive.value = img.id;
materialList.scList.push({ ...img, x: 0, y: 0, z: 0, w: 1, h: 1 });
}
// 删除上传的背景或素材
function delImg(id) {
@@ -849,8 +903,10 @@ watch(
(newValue, oldValue) => {
// 根据横竖屏来确定比例 1竖2横
if (videoType.value == 1) {
proportion.value = 1080 / elementWidth.value;
// proportion.value = 1080 / elementWidth.value;
proportion.value = 1080 / 432;
} else if (videoType.value == 2) {
proportion.value = 1920 / 768;
proportion.value = 1920 / elementWidth.value;
}
console.log(proportion.value);
@@ -891,6 +947,101 @@ watch(
);
//#endregion ----------------------------

//#region 编辑区域控制台
const showImgInfo = ref({
id: null,
data: null,
}); //显示素材or数字人的id
// const showImgInfoData = ref(null);
watch(
() => showImgInfo,
(newValue, oldValue) => {
if (materialList.virtual.id == showImgInfo.value.id) {
showImgInfo.value.data = materialList.virtual;
} else {
showImgInfo.value.data = materialList.scList.find(
(item) => item.id == showImgInfo.value.id
);
}
},
{ deep: true }
);
//#endregion ----------------------------

//#region 保存视频和生成草稿
const workId = ref(null); //保存作品完成后会有一个id,用于生成视频
async function saveOrUpdate() {
try {
if (!textareaContent.value) {
ElMessage.error(
lanChange.value == "zh-cn"
? `您还没有输入文案`
: `You have not entered the copy yet`
);
return;
}
if (!sound.value && !soundStyle.value) {
ElMessage.error(
lanChange.value == "zh-cn"
? `您还没有选择声音`
: `You have not selected a sound`
);
return;
}

// 处理数字人
const shuziren = {
id: materialList.virtual.id,
type: 1,
material: materialList.virtual.material,
x: materialList.virtual.x,
y: materialList.virtual.y,
z: materialList.virtual.z,
w: materialList.virtual.w,
h: materialList.virtual.h,
};
// 处理素材
const scList = materialList.scList.map((item) => {
return {
id: item.id,
type: 5,
material: item.material,
x: item.x,
y: item.y,
z: item.z,
w: item.w,
h: item.h,
};
});
// 处理上传数据
const data = {
id: workId.value,
videoType: videoType.value, //横屏竖屏
personMouldId: materialList.virtual.id, //数字人id
voiceMouldIds: [soundStyle.value ? soundStyle.value : sound.value], //声音id
title: title.value, //标题
paperwork: textareaContent.value, //语音内容
backgroundId: materialList.BGI.id + "", //背景id
personJson: JSON.stringify(shuziren), // 数字人
materialAllJson: JSON.stringify([...scList]), // 素材
};

const res = await saveOrUpdateApi(data);
workId.value = res.data.id;
} catch (error) {
ElMessage.error(error);
}
}
async function createVideo() {
try {
await saveOrUpdate();
const res2 = await createVideoApi(workId.value);
} catch (error) {
ElMessage.error(error);
}
}
//#endregion ----------------------------

//#region

//#endregion ----------------------------
@@ -1080,13 +1231,54 @@ onMounted(async () => {
max-width: 800px;
max-height: 800px;
}
.EditPosition {
.EditPositionBox1 {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
max-width: 800px;
max-height: 800px;
height: 768px;
width: 432px;
}
.EditPositionBox2 {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
height: 432px;
width: 768px;
}
.showImgInfoBox {
position: absolute;
top: 200px;
right: 0px;
width: 120px;
background-color: #e9ecf1;
border-radius: 20px;
padding: 10px;
box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px;
.ItemName {
width: 100%;
height: 40px;
text-align: center;
line-height: 40px;
background-color: #fff;
border-radius: 10px;
}
.ItemValue {
margin-bottom: 10px;
width: 100%;
height: 40px;
text-align: center;
line-height: 40px;
background-color: #f5f7fa;
border-radius: 10px;
.el-input-number--large {
width: 100px;
}
.el-input-number__increase {
width: none;
}
}
}
.btnBox {
position: absolute;


Načítá se…
Zrušit
Uložit