|
228 | 228 | <!-- LINES --> |
229 | 229 | <g v-for="(serie, i) in lineSet" :key="`serie_line_${i}`" :class="`serie_line_${i}`"> |
230 | 230 | <g v-if="serie.useArea"> |
231 | | - <path :d="`M${serie.area}Z`" :fill="chartConfig.line.area.useGradient ? `url(#areaGradient_${i}_${uniqueId})` : `${serie.color}${opacity[chartConfig.line.area.opacity]}`"/> |
| 231 | + <path v-if="serie.smooth" :d="`M ${serie.plots[0].x},${drawingArea.bottom} ${serie.curve} L ${serie.plots.at(-1).x},${drawingArea.bottom} Z`" :fill="chartConfig.line.area.useGradient ? `url(#areaGradient_${i}_${uniqueId})` : `${serie.color}${opacity[chartConfig.line.area.opacity]}`"/> |
| 232 | + |
| 233 | + <path v-else :d="`M${serie.area}Z`" :fill="chartConfig.line.area.useGradient ? `url(#areaGradient_${i}_${uniqueId})` : `${serie.color}${opacity[chartConfig.line.area.opacity]}`"/> |
232 | 234 | </g> |
233 | | - <g v-for="(plot, j) in serie.plots" :key="`line_${i}_${j}`"> |
234 | | - <line |
235 | | - v-if="j < serie.plots.length - 1 && canShowValue(plot.value) && canShowValue(serie.plots[j+1].value)" |
236 | | - :x1="plot.x" |
237 | | - :x2="serie.plots[j+1].x" |
238 | | - :y1="plot.y" |
239 | | - :y2="serie.plots[j+1].y" |
240 | | - :stroke="serie.color" |
241 | | - :stroke-width="chartConfig.line.strokeWidth" |
242 | | - :stroke-dasharray="serie.dashed ? chartConfig.line.strokeWidth * 2 : 0" |
243 | | - stroke-linejoin="round" |
244 | | - stroke-linecap="round" |
245 | | - /> |
| 235 | + <path v-if="serie.smooth" :d="`M${serie.curve}`" :stroke="serie.color" :stroke-width="chartConfig.line.strokeWidth" :stroke-dasharray="serie.dashed ? chartConfig.line.strokeWidth * 2 : 0" fill="none" /> |
| 236 | + <g v-else> |
| 237 | + <g v-for="(plot, j) in serie.plots" :key="`line_${i}_${j}`"> |
| 238 | + <line |
| 239 | + v-if="j < serie.plots.length - 1 && canShowValue(plot.value) && canShowValue(serie.plots[j+1].value)" |
| 240 | + :x1="plot.x" |
| 241 | + :x2="serie.plots[j+1].x" |
| 242 | + :y1="plot.y" |
| 243 | + :y2="serie.plots[j+1].y" |
| 244 | + :stroke="serie.color" |
| 245 | + :stroke-width="chartConfig.line.strokeWidth" |
| 246 | + :stroke-dasharray="serie.dashed ? chartConfig.line.strokeWidth * 2 : 0" |
| 247 | + stroke-linejoin="round" |
| 248 | + stroke-linecap="round" |
| 249 | + /> |
| 250 | + </g> |
246 | 251 | </g> |
247 | 252 | <g v-for="(plot, j) in serie.plots" |
248 | 253 | :key="`circle_line_${i}_${j}`"> |
@@ -757,8 +762,10 @@ export default { |
757 | 762 | value: datapoint.absoluteValues[j], |
758 | 763 | } |
759 | 764 | }); |
| 765 | + const curve = this.createSmoothPath(plots); |
760 | 766 | return { |
761 | 767 | ...datapoint, |
| 768 | + curve, |
762 | 769 | plots, |
763 | 770 | area: !datapoint.useArea ? '' : this.createArea(plots) |
764 | 771 | } |
@@ -1076,6 +1083,40 @@ export default { |
1076 | 1083 | }); |
1077 | 1084 | return [ start.x, start.y, ...path, end.x, end.y].toString(); |
1078 | 1085 | }, |
| 1086 | + createSmoothPath(points) { |
| 1087 | + const smoothing = 0.2; |
| 1088 | + function line(pointA, pointB) { |
| 1089 | + const lengthX = pointB.x - pointA.x; |
| 1090 | + const lengthY = pointB.y - pointA.y; |
| 1091 | + return { |
| 1092 | + length: Math.sqrt(Math.pow(lengthX, 2) + Math.pow(lengthY, 2)), |
| 1093 | + angle: Math.atan2(lengthY, lengthX) |
| 1094 | + }; |
| 1095 | + } |
| 1096 | + function controlPoint(current, previous, next, reverse) { |
| 1097 | + const p = previous || current; |
| 1098 | + const n = next || current; |
| 1099 | + const o = line(p, n); |
| 1100 | +
|
| 1101 | + const angle = o.angle + (reverse ? Math.PI : 0); |
| 1102 | + const length = o.length * smoothing; |
| 1103 | +
|
| 1104 | + const x = current.x + Math.cos(angle) * length; |
| 1105 | + const y = current.y + Math.sin(angle) * length; |
| 1106 | + return { x, y }; |
| 1107 | + } |
| 1108 | + function bezierCommand(point, i, a) { |
| 1109 | + const cps = controlPoint(a[i - 1], a[i - 2], point); |
| 1110 | + const cpe = controlPoint(point, a[i - 1], a[i + 1], true); |
| 1111 | + return `C ${cps.x},${cps.y} ${cpe.x},${cpe.y} ${point.x},${point.y}`; |
| 1112 | + } |
| 1113 | + const d = points.reduce((acc, point, i, a) => i === 0 |
| 1114 | + ? `${point.x},${point.y} ` |
| 1115 | + : `${acc} ${bezierCommand(point, i, a)} ` |
| 1116 | + , ''); |
| 1117 | +
|
| 1118 | + return d; |
| 1119 | + }, |
1079 | 1120 | /////////////////////////////// CANVAS ///////////////////////////////// |
1080 | 1121 | createCanvasArea(plots) { |
1081 | 1122 | const start = { x: plots[0].x, y: this.zero }; |
|
0 commit comments