mirror of https://github.com/doccano/doccano.git
pythondatasetsactive-learningtext-annotationdatasetnatural-language-processingdata-labelingmachine-learningannotation-tool
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
4.8 KiB
193 lines
4.8 KiB
<template>
|
|
<v-group>
|
|
<v-polygon
|
|
:polygon="writablePolygon"
|
|
:closed="true"
|
|
:color="color"
|
|
:draggable="true"
|
|
:highlight-id="highlightId"
|
|
:max-height="maxHeight"
|
|
:max-width="maxWidth"
|
|
:scale="scale"
|
|
@click="$emit('click-polygon', writablePolygon)"
|
|
@dragstart="onDragStart"
|
|
@dragend="onDragEnd"
|
|
/>
|
|
<v-circle
|
|
ref="anchorRef"
|
|
:config="{
|
|
x: -10,
|
|
y: -10,
|
|
radius: 5,
|
|
fill: 'white',
|
|
stroke: 'black',
|
|
scaleX: 1 / (scale || 1),
|
|
scaleY: 1 / (scale || 1)
|
|
}"
|
|
/>
|
|
<template v-if="isSelected && !isMoving">
|
|
<v-line
|
|
v-for="(lineSegment, insertIndex) in writablePolygon.lineSegments"
|
|
:key="insertIndex"
|
|
:config="{
|
|
draggable: false,
|
|
hitStrokeWidth: 10,
|
|
lineJoin: 'round',
|
|
opacity: 1,
|
|
points: lineSegment.points,
|
|
stroke: 'transparent',
|
|
strokeWidth: 5,
|
|
strokeScaleEnabled: false
|
|
}"
|
|
@mousemove="onMouseMoveLine($event, lineSegment)"
|
|
@mouseleave="hideAnchorPoint"
|
|
@click="handleClickLine($event, writablePolygon, insertIndex + 1)"
|
|
/>
|
|
<v-point
|
|
v-for="(point, index) in writablePolygon.toPoints()"
|
|
:key="`${writablePolygon.id}-${index}`"
|
|
:color="index === selectedPoint ? color : 'white'"
|
|
:point="point"
|
|
:index="index"
|
|
:max-width="maxWidth"
|
|
:max-height="maxHeight"
|
|
:scale="scale"
|
|
@click="$emit('click-point', index)"
|
|
@dragstart="hideAnchorPoint"
|
|
@dragmove="handleDragMovePoint"
|
|
@dragend="handleDragEndPoint"
|
|
@dblclick="handleDoubleClickPoint"
|
|
/>
|
|
</template>
|
|
</v-group>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import Vue from 'vue'
|
|
import Konva from 'konva'
|
|
import Flatten from '@flatten-js/core'
|
|
import Polygon from '@/domain/models/tasks/segmentation/Polygon'
|
|
import LineSegment from '@/domain/models/tasks/segmentation/LineSegment'
|
|
import { transform } from '@/domain/models/tasks/shared/Scaler'
|
|
import VPolygon from './VPolygon.vue'
|
|
import VPoint from './VPoint.vue'
|
|
import Point = Flatten.Point
|
|
|
|
export default Vue.extend({
|
|
components: {
|
|
VPolygon,
|
|
VPoint
|
|
},
|
|
|
|
props: {
|
|
polygon: {
|
|
type: Polygon,
|
|
required: true
|
|
},
|
|
color: {
|
|
type: String,
|
|
default: '#00FF00'
|
|
},
|
|
maxWidth: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
maxHeight: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
scale: {
|
|
type: Number,
|
|
default: 1
|
|
},
|
|
highlightId: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
isSelected: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
selectedPoint: {
|
|
type: Number,
|
|
default: -1
|
|
}
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
isMoving: false,
|
|
writablePolygon: this.polygon
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
anchor() {
|
|
return (this.$refs.anchorRef as Konva.ShapeConfig).getNode()
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
polygon: {
|
|
handler(newPolygon: Polygon) {
|
|
this.writablePolygon = newPolygon
|
|
},
|
|
immediate: true,
|
|
deep: true
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
onDragStart() {
|
|
this.isMoving = true
|
|
},
|
|
|
|
onDragEnd(polygon: Polygon, dx: number, dy: number) {
|
|
this.isMoving = false
|
|
this.$emit('drag-end-polygon', polygon, dx, dy)
|
|
},
|
|
|
|
handleDragMovePoint(index: number, x: number, y: number) {
|
|
this.writablePolygon.movePoint(index, x, y)
|
|
this.writablePolygon = this.writablePolygon.clone()
|
|
},
|
|
|
|
handleDragEndPoint(index: number, x: number, y: number) {
|
|
this.$emit('drag-end-point', this.polygon, index, x, y)
|
|
},
|
|
|
|
handleDoubleClickPoint(index: number) {
|
|
this.$emit('double-click-point', this.polygon, index)
|
|
},
|
|
|
|
onMouseMoveLine(e: Konva.KonvaEventObject<MouseEvent>, lineSegment: LineSegment) {
|
|
const { offsetX, offsetY } = e.evt
|
|
const { x: stageX = 0, y: stageY = 0 } = e.target.getStage()!.attrs
|
|
const x = transform(offsetX, stageX, this.scale)
|
|
const y = transform(offsetY, stageY, this.scale)
|
|
const point = new Point(x, y)
|
|
const closestPoint = lineSegment.getClosestPoint(point)
|
|
this.showAnchorPoint(closestPoint.x, closestPoint.y)
|
|
},
|
|
|
|
handleClickLine(e: Konva.KonvaEventObject<MouseEvent>, polygon: Polygon, index: number) {
|
|
const { offsetX, offsetY } = e.evt
|
|
const { x: stageX = 0, y: stageY = 0 } = e.target.getStage()!.attrs
|
|
const x = transform(offsetX, stageX, this.scale)
|
|
const y = transform(offsetY, stageY, this.scale)
|
|
this.hideAnchorPoint()
|
|
this.$emit('click-line', polygon, index, x, y)
|
|
},
|
|
|
|
showAnchorPoint(x: number, y: number) {
|
|
this.anchor.to({ x, y, duration: 0 })
|
|
this.anchor.show()
|
|
},
|
|
|
|
hideAnchorPoint() {
|
|
this.anchor.to({ x: -10, y: -10, duration: 0 })
|
|
this.anchor.hide()
|
|
}
|
|
}
|
|
})
|
|
</script>
|