|
@@ -4,14 +4,14 @@
|
|
|
<v-line
|
|
|
v-for="p in line.points"
|
|
|
:config="{
|
|
|
- stroke: stroke,
|
|
|
- strokeWidth: strokeWidth,
|
|
|
+ stroke: style.stroke,
|
|
|
+ strokeWidth: style.strokeWidth / 2,
|
|
|
points: flatPositions(p),
|
|
|
}"
|
|
|
/>
|
|
|
<v-textPath
|
|
|
:config="{
|
|
|
- fill: stroke,
|
|
|
+ fill: style.stroke,
|
|
|
align: 'center',
|
|
|
fontSize,
|
|
|
textBaseline: 'middle',
|
|
@@ -24,7 +24,6 @@
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
import { computed } from "vue";
|
|
|
-import { LineData } from "../line";
|
|
|
import {
|
|
|
getPolygonDirection,
|
|
|
getVectorLine,
|
|
@@ -40,53 +39,77 @@ import { TextPathConfig } from "konva/lib/shapes/TextPath";
|
|
|
|
|
|
const props = withDefaults(
|
|
|
defineProps<{
|
|
|
- data: Required<Pick<LineData, "points" | "strokeWidth">>;
|
|
|
+ points: Pos[];
|
|
|
stroke?: string;
|
|
|
strokeWidth?: number;
|
|
|
closed?: boolean;
|
|
|
+ margin?: number;
|
|
|
}>(),
|
|
|
{ stroke: "#999", strokeWidth: 1 }
|
|
|
);
|
|
|
|
|
|
-const fontSize = computed(() => 10 + props.strokeWidth * 2);
|
|
|
+const style = computed(() => ({ stroke: "#999", strokeWidth: 1 }));
|
|
|
+const fontSize = computed(() => 10 + style.value.strokeWidth * 2);
|
|
|
const len = computed(() =>
|
|
|
- props.closed ? props.data.points.length : props.data.points.length - 1
|
|
|
+ props.closed ? props.points.length : props.points.length - 1
|
|
|
);
|
|
|
const getLine = (ndx: number) =>
|
|
|
[
|
|
|
- props.data.points[ndx % props.data.points.length],
|
|
|
- props.data.points[(ndx + 1) % props.data.points.length],
|
|
|
+ props.points[ndx % props.points.length],
|
|
|
+ props.points[(ndx + 1) % props.points.length],
|
|
|
] as [Pos, Pos];
|
|
|
-const isClockwise = computed(() => getPolygonDirection(props.data.points) <= 0);
|
|
|
+const isClockwise = computed(() => getPolygonDirection(props.points) <= 0);
|
|
|
|
|
|
const proportion = useProportion();
|
|
|
-const margin = computed(() => -(props.data.strokeWidth + 10));
|
|
|
+const margin = computed(() =>
|
|
|
+ props.margin !== undefined ? props.margin! : -10 - style.value.strokeWidth * 2
|
|
|
+);
|
|
|
const lines = computed(() => {
|
|
|
const lines: { points: Pos[][]; textConfig: TextPathConfig }[] = [];
|
|
|
for (let i = 0; i < len.value; i++) {
|
|
|
- const line = getLine(i);
|
|
|
- const lineOffset = isClockwise.value ? margin.value : -margin.value;
|
|
|
- const vv = lineVerticalVector(line);
|
|
|
- const offset = vv.multiplyScalar(lineOffset);
|
|
|
- const p = [vector(line[0]).add(offset), vector(line[1]).add(offset)];
|
|
|
- const text = proportion.transform(lineLen(...line));
|
|
|
- const w = fontSize.value * text.length;
|
|
|
- const lw = lineLen(p[0], p[1]);
|
|
|
- if (w > lw) {
|
|
|
+ const baseLine = getLine(i).map(vector);
|
|
|
+ const baseLineVV = lineVerticalVector(baseLine);
|
|
|
+ const sizeMargin = isClockwise.value ? margin.value : -margin.value;
|
|
|
+ const sizeOffset = baseLineVV.clone().multiplyScalar(sizeMargin);
|
|
|
+ const sizeTextStr = proportion.transform(lineLen(baseLine[0], baseLine[1]));
|
|
|
+ const sizeTextW = (fontSize.value * sizeTextStr.length) / 1.5;
|
|
|
+ const baseLineW = lineLen(baseLine[0], baseLine[1]);
|
|
|
+
|
|
|
+ if (sizeTextW > baseLineW) {
|
|
|
continue;
|
|
|
}
|
|
|
- const lv = lineVector(p);
|
|
|
- const line1 = getVectorLine(lv, p[0], (lw - w) / 2);
|
|
|
- const [_, start2] = getVectorLine(lv, line1[1], w);
|
|
|
- const line2 = getVectorLine(lv, start2, (lw - w) / 2);
|
|
|
+
|
|
|
+ const sizeLine = [
|
|
|
+ baseLine[0].clone().add(sizeOffset),
|
|
|
+ baseLine[1].clone().add(sizeOffset),
|
|
|
+ ];
|
|
|
+ const sizeLineV = lineVector(baseLine);
|
|
|
+ const splitLineW = (baseLineW - sizeTextW) / 2;
|
|
|
+
|
|
|
+ const splitLine1 = getVectorLine(sizeLineV, sizeLine[0], splitLineW);
|
|
|
+ const [_, splitLine2Start] = getVectorLine(sizeLineV, splitLine1[1], sizeTextW);
|
|
|
+ const splitLine2 = getVectorLine(sizeLineV, splitLine2Start, splitLineW);
|
|
|
+
|
|
|
+ const padOffset1 = sizeOffset.clone().multiplyScalar(0.3);
|
|
|
+ const padOffset2 = sizeOffset.clone().multiplyScalar(-0.3);
|
|
|
+ const showLine1 = [
|
|
|
+ vector(splitLine1[0]).add(padOffset1),
|
|
|
+ vector(splitLine1[0]).add(padOffset2),
|
|
|
+ ...splitLine1,
|
|
|
+ ];
|
|
|
+ const showLine2 = [
|
|
|
+ ...splitLine2,
|
|
|
+ vector(splitLine2[1]).add(padOffset1),
|
|
|
+ vector(splitLine2[1]).add(padOffset2),
|
|
|
+ ];
|
|
|
|
|
|
lines.push({
|
|
|
- points: [line1, line2],
|
|
|
+ points: [showLine1, showLine2],
|
|
|
textConfig: {
|
|
|
- text: proportion.transform(lineLen(...line)),
|
|
|
+ text: sizeTextStr,
|
|
|
x: 0,
|
|
|
y: 0,
|
|
|
- data: `M${p[0].x},${p[0].y} L${p[1].x},${p[1].y}`,
|
|
|
+ data: `M${sizeLine[0].x},${sizeLine[0].y} L${sizeLine[1].x},${sizeLine[1].y}`,
|
|
|
},
|
|
|
});
|
|
|
}
|