|
@@ -17,28 +17,50 @@
|
|
|
:style="{ width: answerPaperScale }"
|
|
|
:class="[`rotate-board-${rotateBoard}`]"
|
|
|
>
|
|
|
- <div
|
|
|
+ <template
|
|
|
v-for="(item, index) in sliceImagesWithTrackList"
|
|
|
:key="index"
|
|
|
- class="single-image-container"
|
|
|
>
|
|
|
- <img
|
|
|
- :src="item.url"
|
|
|
- draggable="false"
|
|
|
- @click="(event) => innerMakeTrack(event, item)"
|
|
|
- @contextmenu="showBigImage"
|
|
|
- />
|
|
|
- <MarkDrawTrack
|
|
|
- :trackList="item.trackList"
|
|
|
- :specialTagList="item.tagList"
|
|
|
- :sliceImageHeight="item.originalImageHeight"
|
|
|
- :sliceImageWidth="item.originalImageWidth"
|
|
|
- :dx="item.dx"
|
|
|
- :dy="item.dy"
|
|
|
- @deleteSpecialtag="(tag) => deleteSpecialtag(item, tag)"
|
|
|
- />
|
|
|
+ <div class="single-image-container">
|
|
|
+ <img
|
|
|
+ :src="item.url"
|
|
|
+ draggable="false"
|
|
|
+ @click="(event) => innerMakeTrack(event, item)"
|
|
|
+ @contextmenu="showBigImage"
|
|
|
+ />
|
|
|
+ <MarkDrawTrack
|
|
|
+ :trackList="item.trackList"
|
|
|
+ :specialTagList="item.tagList"
|
|
|
+ :sliceImageHeight="item.originalImageHeight"
|
|
|
+ :sliceImageWidth="item.originalImageWidth"
|
|
|
+ :dx="item.dx"
|
|
|
+ :dy="item.dy"
|
|
|
+ @delete-specialtag="(tag) => deleteSpecialtag(item, tag)"
|
|
|
+ @click-specialtag="(event) => clickSpecialtag(event, item)"
|
|
|
+ />
|
|
|
+ <div
|
|
|
+ v-if="isCustomSpecialTag"
|
|
|
+ class="image-canvas"
|
|
|
+ v-ele-move-directive.stop.prevent="{
|
|
|
+ moveStart: (event) => specialMouseStart(event, item),
|
|
|
+ moveElement: specialMouseMove,
|
|
|
+ moveStop: specialMouseStop,
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <template v-if="curSliceImagesWithTrackItem?.url === item.url">
|
|
|
+ <div
|
|
|
+ v-if="store.currentSpecialTagType === 'LINE'"
|
|
|
+ :style="specialLenStyle"
|
|
|
+ ></div>
|
|
|
+ <div
|
|
|
+ v-if="store.currentSpecialTagType === 'CIRCLE'"
|
|
|
+ :style="specialCircleStyle"
|
|
|
+ ></div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
<hr class="image-seperator" />
|
|
|
- </div>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
<div v-else-if="store.isMultiMedia">
|
|
|
<MultiMediaMarkBody />
|
|
@@ -61,6 +83,8 @@ import "viewerjs/dist/viewer.css";
|
|
|
import Viewer from "viewerjs";
|
|
|
import { message } from "ant-design-vue";
|
|
|
import EventBus from "@/plugins/eventBus";
|
|
|
+import { vEleMoveDirective } from "../mark/use/eleMove";
|
|
|
+
|
|
|
type MakeTrack = (
|
|
|
event: MouseEvent,
|
|
|
item: SliceImage,
|
|
@@ -99,6 +123,16 @@ const deleteSpecialtag = (item, tag) => {
|
|
|
if (stagIndex === -1) return;
|
|
|
store.currentTaskEnsured.markResult.specialTagList.splice(tagIndex, 1);
|
|
|
};
|
|
|
+const clickSpecialtag = (event: MouseEvent, item: SliceImage) => {
|
|
|
+ // console.log(event);
|
|
|
+ const e = {
|
|
|
+ target: event.target.offsetParent.childNodes[0],
|
|
|
+ offsetX: event.offsetX + event.target.offsetLeft,
|
|
|
+ offsetY: event.offsetY + event.target.offsetTop,
|
|
|
+ };
|
|
|
+
|
|
|
+ makeTrack(e as MouseEvent, item, maxImageWidth, theFinalHeight);
|
|
|
+};
|
|
|
|
|
|
const clearEmptySpecialTag = (item) => {
|
|
|
item.tagList
|
|
@@ -402,6 +436,118 @@ const innerMakeTrack = (event: MouseEvent, item: SliceImage) => {
|
|
|
};
|
|
|
//#endregion : 评分
|
|
|
|
|
|
+//#region : 特殊标记:画线、框
|
|
|
+const isCustomSpecialTag = $computed(() => {
|
|
|
+ return ["CIRCLE", "LINE"].includes(store.currentSpecialTagType);
|
|
|
+});
|
|
|
+
|
|
|
+let specialPoint = $ref({ x: 0, y: 0, ex: 0, ey: 0 });
|
|
|
+let curImageTarget: HTMLElement = null;
|
|
|
+let curSliceImagesWithTrackItem: SliceImage = $ref(null);
|
|
|
+
|
|
|
+const specialLenStyle = $computed(() => {
|
|
|
+ if (specialPoint.ex <= specialPoint.x) return { display: "none" };
|
|
|
+
|
|
|
+ const width =
|
|
|
+ specialPoint.ex > specialPoint.x ? specialPoint.ex - specialPoint.x : 0;
|
|
|
+ return {
|
|
|
+ top: specialPoint.y + "px",
|
|
|
+ left: specialPoint.x + "px",
|
|
|
+ width: width + "px",
|
|
|
+ position: "absolute",
|
|
|
+ borderTop: "1px solid red",
|
|
|
+ zIndex: 9,
|
|
|
+ };
|
|
|
+});
|
|
|
+const specialCircleStyle = $computed(() => {
|
|
|
+ if (specialPoint.ex <= specialPoint.x || specialPoint.ey <= specialPoint.y)
|
|
|
+ return { display: "none" };
|
|
|
+
|
|
|
+ const width =
|
|
|
+ specialPoint.ex > specialPoint.x ? specialPoint.ex - specialPoint.x : 0;
|
|
|
+ const height =
|
|
|
+ specialPoint.ey > specialPoint.y ? specialPoint.ey - specialPoint.y : 0;
|
|
|
+ return {
|
|
|
+ top: specialPoint.y + "px",
|
|
|
+ left: specialPoint.x + "px",
|
|
|
+ width: width + "px",
|
|
|
+ height: height + "px",
|
|
|
+ position: "absolute",
|
|
|
+ border: "1px solid red",
|
|
|
+ borderRadius: "50%",
|
|
|
+ zIndex: 9,
|
|
|
+ };
|
|
|
+});
|
|
|
+
|
|
|
+function specialMouseStart(e: MouseEvent, item: SliceImage) {
|
|
|
+ curImageTarget = e.target.parentElement.childNodes[0];
|
|
|
+ curSliceImagesWithTrackItem = item;
|
|
|
+ specialPoint.x = e.offsetX;
|
|
|
+ specialPoint.y = e.offsetY;
|
|
|
+}
|
|
|
+function specialMouseMove({ left, top }) {
|
|
|
+ specialPoint.ex = left + specialPoint.x;
|
|
|
+ specialPoint.ey = top + specialPoint.y;
|
|
|
+}
|
|
|
+function specialMouseStop(e: MouseEvent) {
|
|
|
+ if (
|
|
|
+ store.currentSpecialTagType === "LINE" &&
|
|
|
+ specialPoint.ex <= specialPoint.x
|
|
|
+ ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (
|
|
|
+ store.currentSpecialTagType === "CIRCLE" &&
|
|
|
+ (specialPoint.ex <= specialPoint.x || specialPoint.ey <= specialPoint.y)
|
|
|
+ ) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const track: SpecialTag = {
|
|
|
+ tagName: "",
|
|
|
+ tagType: store.currentSpecialTagType,
|
|
|
+ offsetIndex: curSliceImagesWithTrackItem.indexInSliceUrls,
|
|
|
+ offsetX:
|
|
|
+ specialPoint.x * (curImageTarget.naturalWidth / curImageTarget.width) +
|
|
|
+ curSliceImagesWithTrackItem.dx,
|
|
|
+ offsetY:
|
|
|
+ specialPoint.y * (curImageTarget.naturalHeight / curImageTarget.height) +
|
|
|
+ curSliceImagesWithTrackItem.dy,
|
|
|
+ positionX: -1,
|
|
|
+ positionY: -1,
|
|
|
+ };
|
|
|
+ track.positionX =
|
|
|
+ (specialPoint.x - curSliceImagesWithTrackItem.dx) / maxImageWidth;
|
|
|
+ track.positionY =
|
|
|
+ (specialPoint.y -
|
|
|
+ curSliceImagesWithTrackItem.dy +
|
|
|
+ curSliceImagesWithTrackItem.accumTopHeight) /
|
|
|
+ theFinalHeight;
|
|
|
+
|
|
|
+ if (store.currentSpecialTagType === "LINE") {
|
|
|
+ track.tagName = JSON.stringify({
|
|
|
+ len:
|
|
|
+ (specialPoint.ex - specialPoint.x) *
|
|
|
+ (curImageTarget.naturalWidth / curImageTarget.width),
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (store.currentSpecialTagType === "CIRCLE") {
|
|
|
+ track.tagName = JSON.stringify({
|
|
|
+ width:
|
|
|
+ (specialPoint.ex - specialPoint.x) *
|
|
|
+ (curImageTarget.naturalWidth / curImageTarget.width),
|
|
|
+ height:
|
|
|
+ (specialPoint.ey - specialPoint.y) *
|
|
|
+ (curImageTarget.naturalHeight / curImageTarget.height),
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ store.currentTaskEnsured.markResult.specialTagList.push(track);
|
|
|
+ curSliceImagesWithTrackItem.tagList.push(track);
|
|
|
+ specialPoint = { x: 0, y: 0, ex: 0, ey: 0 };
|
|
|
+}
|
|
|
+//#endregion
|
|
|
+
|
|
|
//#region : 显示大图,供查看和翻转
|
|
|
const showBigImage = (event: MouseEvent) => {
|
|
|
event.preventDefault();
|
|
@@ -529,3 +675,14 @@ function scrollToFirstScore() {
|
|
|
}
|
|
|
//#endregion
|
|
|
</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.image-canvas {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ z-index: 9;
|
|
|
+}
|
|
|
+</style>
|