Change wordings, align text.
<template>
<g>
<path ref="path" v-bind:d="path" stroke="#000000" fill="#bdc3c7"
v-bind:stroke-width="handlerRadius / 2"
v-bind:stroke-dasharray="(handlerRadius / 3) + ',' + (handlerRadius / 3)" style="opacity: 0.6;"></path>
<circle ref="handlers"
v-for="(point, key) in points"
:key="key"
v-show="!readonly"
v-bind:data-key="key"
v-bind:cx="point.x"
v-bind:cy="point.y"
v-bind:r="handlerRadius"
v-bind:stroke-width="handlerRadius / 2"
v-bind:class="{ handler: true, 'handler--first': key === 0 && !closed }"></circle>
</g>
</template>
<script>
import Snap from 'snapsvg'
import tooltip from './mixins/tooltip'
import save from './mixins/save'
export default {
mixins: [ tooltip, save ],
props: [
'paper',
'original-annotation',
'readonly',
],
data() {
return {
path: '',
closed: false,
points: [],
handlerRadius: 30
}
},
mounted() {
},
watch: {
closed: function(closed) {
if (closed) {
this.path += ' Z';
}
},
// Redraw the path when the points have changed
points: function(points) {
var path = "M";
if (points.length <= 1) {
return;
}
path += points[0].x + ',' + points[0].y;
for (var i = 0; i < points.length; i++) {
if (i == 0) continue;
var pointInfos = points[i];
var lPath = "L" + pointInfos.x + "," + pointInfos.y;
path += " " + lPath;
}
if (this.closed) { path += ' Z'; }
this.path = path;
}
},
methods: {
addPoint: function(x, y) {
this.points.push({ x: x, y: y });
// Attach events to last point once DOM has been refreshed
// @link https://vuejs.org/v2/guide/reactivity.html
this.$nextTick(() => {
var handler = this.$refs.handlers[this.$refs.handlers.length - 1];
this.addResizeHandler(handler);
});
},
clear: function() {
this.destroyTooltip();
Object.assign(this, {
points: [],
closed: false,
path: ''
});
},
getTooltipTarget: function() {
return this.$refs.path;
},
fromSVGPath: function(pathString, tooltip) {
var segments = Snap.parsePathString(pathString);
var points = [];
// Don't use this.addPoint to avoid
// race condition when registering events
segments.map((segment) => {
if (segment[0] !== 'Z') {
points.push({ x: segment[1], y: segment[2] });
}
});
this.points = points;
this.closed = true;
this.$nextTick(() => {
this.addResizeHandlers();
if (tooltip) {
// FIXME Race condition with destroy
setTimeout(() => this.addTooltip(), 250);
}
});
},
toSVGPath: function() {
return this.$parent.normalizePath(this.path) + ';FREE'
},
addResizeHandler: function(handler) {
var self = this;
var circle = new Snap(handler);
var isDragged = false;
circle.click((e) => {
var key = parseInt(circle.attr('data-key'), 10);
if (key === 0 && this.points.length > 2) {
this.closed = true;
this.$nextTick(() => {
// FIXME Race condition with destroy
setTimeout(() => this.addTooltip(), 250);
});
}
});
// Remove point on double click
circle.dblclick((e) => {
var circle = new Snap(e.target);
var key = parseInt(circle.attr('data-key'), 10);
this.points.splice(key, 1);
});
var dragEvents = {
onMove: function(dx, dy, x, y, e) {
isDragged = true;
var offset = self.$parent.computeOffset(e);
this.attr({ cx: offset.x, cy: offset.y });
var key = parseInt(this.attr('data-key'), 10);
// Must use splice for reactivity to work
// @see https://vuejs.org/v2/guide/list.html#Mutation-Methods
self.points.splice(key, 1, { x: offset.x, y: offset.y });
},
onStart: () => this.hideTooltip(),
onEnd: function(e) {
if (!isDragged) { return; }
isDragged = false;
self.showTooltip();
}
}
circle.drag(dragEvents.onMove, dragEvents.onStart, dragEvents.onEnd);
},
addResizeHandlers: function() {
this.$refs.handlers.forEach((handler) => this.addResizeHandler(handler));
}
}
}
</script>
<style scoped>
.handler {
fill: #fff;
stroke: #000;
opacity: 0.9;
}
.handler--first {
fill: yellow;
}
</style>