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

<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>