|
@@ -32,11 +32,12 @@
|
|
>
|
|
>
|
|
<img
|
|
<img
|
|
:src="item.url"
|
|
:src="item.url"
|
|
- @click="(event) => makeScoreTrack(event, item)"
|
|
|
|
|
|
+ @click="(event) => makeTrack(event, item)"
|
|
draggable="false"
|
|
draggable="false"
|
|
/>
|
|
/>
|
|
<MarkDrawTrack
|
|
<MarkDrawTrack
|
|
:track-list="item.trackList"
|
|
:track-list="item.trackList"
|
|
|
|
+ :special-tag-list="item.tagList"
|
|
:original-image="item.originalImage"
|
|
:original-image="item.originalImage"
|
|
:slice-image="item.sliceImage"
|
|
:slice-image="item.sliceImage"
|
|
:dx="item.dx"
|
|
:dx="item.dx"
|
|
@@ -49,7 +50,11 @@
|
|
</div>
|
|
</div>
|
|
<div class="cursor">
|
|
<div class="cursor">
|
|
<div class="cursor-border">
|
|
<div class="cursor-border">
|
|
- <span class="text">{{ store.currentScore }}</span>
|
|
|
|
|
|
+ <span class="text">{{
|
|
|
|
+ store.setting.uiSetting["specialTag.modal"]
|
|
|
|
+ ? store.currentSpecialTag
|
|
|
|
+ : store.currentScore
|
|
|
|
+ }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
@@ -68,7 +73,7 @@ import {
|
|
import { findCurrentTaskMarkResult, getMarkStatus, store } from "./store";
|
|
import { findCurrentTaskMarkResult, getMarkStatus, store } from "./store";
|
|
import filters from "@/filters";
|
|
import filters from "@/filters";
|
|
import MarkDrawTrack from "./MarkDrawTrack.vue";
|
|
import MarkDrawTrack from "./MarkDrawTrack.vue";
|
|
-import { ModeEnum, Track } from "@/types";
|
|
|
|
|
|
+import { ModeEnum, SpecialTag, Track } from "@/types";
|
|
import { useTimers } from "@/setups/useTimers";
|
|
import { useTimers } from "@/setups/useTimers";
|
|
import {
|
|
import {
|
|
getDataUrlForSliceConfig,
|
|
getDataUrlForSliceConfig,
|
|
@@ -85,6 +90,7 @@ interface SliceImage {
|
|
url: string;
|
|
url: string;
|
|
indexInSliceUrls: number;
|
|
indexInSliceUrls: number;
|
|
trackList: Array<Track>;
|
|
trackList: Array<Track>;
|
|
|
|
+ tagList: Array<SpecialTag>;
|
|
originalImage: HTMLImageElement;
|
|
originalImage: HTMLImageElement;
|
|
sliceImage: HTMLImageElement;
|
|
sliceImage: HTMLImageElement;
|
|
dx: number;
|
|
dx: number;
|
|
@@ -158,6 +164,9 @@ export default defineComponent({
|
|
const thisImageTrackList = markResult.trackList.filter(
|
|
const thisImageTrackList = markResult.trackList.filter(
|
|
(v) => v.offsetIndex === sliceConfig.i
|
|
(v) => v.offsetIndex === sliceConfig.i
|
|
);
|
|
);
|
|
|
|
+ const thisImageTagList = markResult.specialTagList.filter(
|
|
|
|
+ (v) => v.offsetIndex === sliceConfig.i
|
|
|
|
+ );
|
|
const sliceImage = new Image();
|
|
const sliceImage = new Image();
|
|
sliceImage.src = dataUrl;
|
|
sliceImage.src = dataUrl;
|
|
sliceImagesWithTrackList.push({
|
|
sliceImagesWithTrackList.push({
|
|
@@ -169,6 +178,11 @@ export default defineComponent({
|
|
t.positionY >= accumTopHeight / theFinalHeight &&
|
|
t.positionY >= accumTopHeight / theFinalHeight &&
|
|
t.positionY < accumBottomHeight / theFinalHeight
|
|
t.positionY < accumBottomHeight / theFinalHeight
|
|
),
|
|
),
|
|
|
|
+ tagList: thisImageTagList.filter(
|
|
|
|
+ (t) =>
|
|
|
|
+ t.positionY >= accumTopHeight / theFinalHeight &&
|
|
|
|
+ t.positionY < accumBottomHeight / theFinalHeight
|
|
|
|
+ ),
|
|
originalImage: image,
|
|
originalImage: image,
|
|
sliceImage,
|
|
sliceImage,
|
|
dx: sliceConfig.x,
|
|
dx: sliceConfig.x,
|
|
@@ -228,6 +242,12 @@ export default defineComponent({
|
|
(store.currentTask &&
|
|
(store.currentTask &&
|
|
store.currentTask.sliceUrls.indexOf(url) + 1)
|
|
store.currentTask.sliceUrls.indexOf(url) + 1)
|
|
);
|
|
);
|
|
|
|
+ const thisImageTagList = markResult.specialTagList.filter(
|
|
|
|
+ (t) =>
|
|
|
|
+ t.offsetIndex ===
|
|
|
|
+ (store.currentTask &&
|
|
|
|
+ store.currentTask.sliceUrls.indexOf(url) + 1)
|
|
|
|
+ );
|
|
const sliceImage = new Image();
|
|
const sliceImage = new Image();
|
|
sliceImage.src = dataUrl;
|
|
sliceImage.src = dataUrl;
|
|
sliceImagesWithTrackList.push({
|
|
sliceImagesWithTrackList.push({
|
|
@@ -238,6 +258,11 @@ export default defineComponent({
|
|
t.positionY >= accumTopHeight / theFinalHeight &&
|
|
t.positionY >= accumTopHeight / theFinalHeight &&
|
|
t.positionY < accumBottomHeight / theFinalHeight
|
|
t.positionY < accumBottomHeight / theFinalHeight
|
|
),
|
|
),
|
|
|
|
+ tagList: thisImageTagList.filter(
|
|
|
|
+ (t) =>
|
|
|
|
+ t.positionY >= accumTopHeight / theFinalHeight &&
|
|
|
|
+ t.positionY < accumBottomHeight / theFinalHeight
|
|
|
|
+ ),
|
|
originalImage: image,
|
|
originalImage: image,
|
|
sliceImage,
|
|
sliceImage,
|
|
dx: image.naturalWidth * config[0],
|
|
dx: image.naturalWidth * config[0],
|
|
@@ -409,6 +434,57 @@ export default defineComponent({
|
|
item.trackList.push(track);
|
|
item.trackList.push(track);
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ const makeSpecialTagTrack = (event: MouseEvent, item: SliceImage) => {
|
|
|
|
+ // console.log(item);
|
|
|
|
+ if (!store.currentTask || typeof store.currentSpecialTag === "undefined")
|
|
|
|
+ return;
|
|
|
|
+ const target = event.target as HTMLImageElement;
|
|
|
|
+ const track = {} as SpecialTag;
|
|
|
|
+ track.tagName = store.currentSpecialTag;
|
|
|
|
+ track.offsetIndex = item.indexInSliceUrls;
|
|
|
|
+ track.offsetX = Math.round(
|
|
|
|
+ event.offsetX * (target.naturalWidth / target.width) + item.dx
|
|
|
|
+ );
|
|
|
|
+ track.offsetY = Math.round(
|
|
|
|
+ event.offsetY * (target.naturalHeight / target.height) + item.dy
|
|
|
|
+ );
|
|
|
|
+ track.positionX = (track.offsetX - item.dx) / maxSliceWidth;
|
|
|
|
+ track.positionY =
|
|
|
|
+ (track.offsetY - item.dy + item.accumTopHeight) / theFinalHeight;
|
|
|
|
+ if (track.offsetX > item.effectiveWidth + item.dx) {
|
|
|
|
+ console.log("不在有效宽度内,轨迹不生效");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (
|
|
|
|
+ item.tagList.some((t) => {
|
|
|
|
+ return (
|
|
|
|
+ Math.pow(Math.abs(t.offsetX - track.offsetX), 2) +
|
|
|
|
+ Math.pow(Math.abs(t.offsetY - track.offsetY), 2) <
|
|
|
|
+ 500
|
|
|
|
+ );
|
|
|
|
+ })
|
|
|
|
+ ) {
|
|
|
|
+ console.log("两个轨迹相距过近");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ const markResult = findCurrentTaskMarkResult();
|
|
|
|
+ if (markResult) {
|
|
|
|
+ markResult.specialTagList.push(track);
|
|
|
|
+ }
|
|
|
|
+ item.tagList.push(track);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const makeTrack = (event: MouseEvent, item: SliceImage) => {
|
|
|
|
+ if (
|
|
|
|
+ store.setting.uiSetting["specialTag.modal"] &&
|
|
|
|
+ store.currentSpecialTag
|
|
|
|
+ ) {
|
|
|
|
+ makeSpecialTagTrack(event, item);
|
|
|
|
+ } else {
|
|
|
|
+ makeScoreTrack(event, item);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
// 清除分数轨迹
|
|
// 清除分数轨迹
|
|
watchEffect(() => {
|
|
watchEffect(() => {
|
|
for (const track of store.removeScoreTracks) {
|
|
for (const track of store.removeScoreTracks) {
|
|
@@ -427,6 +503,27 @@ export default defineComponent({
|
|
store.removeScoreTracks.splice(0);
|
|
store.removeScoreTracks.splice(0);
|
|
});
|
|
});
|
|
|
|
|
|
|
|
+ // 清除特殊标记轨迹
|
|
|
|
+ watchEffect(() => {
|
|
|
|
+ for (const track of store.currentMarkResult?.specialTagList || []) {
|
|
|
|
+ for (const sliceImage of sliceImagesWithTrackList) {
|
|
|
|
+ sliceImage.tagList = sliceImage.tagList.filter((t) =>
|
|
|
|
+ store.currentMarkResult?.specialTagList.find(
|
|
|
|
+ (st) =>
|
|
|
|
+ st.offsetIndex === t.offsetIndex &&
|
|
|
|
+ st.offsetX === t.offsetX &&
|
|
|
|
+ st.offsetY === t.offsetY
|
|
|
|
+ )
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (store.currentMarkResult?.specialTagList.length === 0) {
|
|
|
|
+ for (const sliceImage of sliceImagesWithTrackList) {
|
|
|
|
+ sliceImage.tagList = [];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
// 轨迹模式下,添加轨迹,更新分数
|
|
// 轨迹模式下,添加轨迹,更新分数
|
|
watch(
|
|
watch(
|
|
() => store.currentMarkResult?.trackList,
|
|
() => store.currentMarkResult?.trackList,
|
|
@@ -554,7 +651,7 @@ export default defineComponent({
|
|
rendering,
|
|
rendering,
|
|
sliceImagesWithTrackList,
|
|
sliceImagesWithTrackList,
|
|
answerPaperScale,
|
|
answerPaperScale,
|
|
- makeScoreTrack,
|
|
|
|
|
|
+ makeTrack,
|
|
markStatus,
|
|
markStatus,
|
|
};
|
|
};
|
|
},
|
|
},
|