83 lines
2.2 KiB
TypeScript
83 lines
2.2 KiB
TypeScript
import { Ref } from "vue";
|
|
|
|
import { createTypedChart } from "vue-chartjs";
|
|
import { LineController } from "chart.js";
|
|
|
|
const lineAlign = 8;
|
|
|
|
type GetMapPlugin = {
|
|
mapX: Ref<Array<number>>;
|
|
};
|
|
|
|
class LineWithLineController extends LineController {
|
|
static override id = "line-with-line";
|
|
|
|
private getMapX(): Array<number> {
|
|
if (!this.chart.config.plugins) {
|
|
return [];
|
|
}
|
|
if (this.chart.isZoomedOrPanned()) {
|
|
return [];
|
|
}
|
|
for (const i in this.chart.config.plugins) {
|
|
if (this.chart.config.plugins[i].id != "yandexMapLine") {
|
|
continue;
|
|
}
|
|
// @ts-expect-error — chart.js plugin config is loosely typed; cast via known shape
|
|
const pluginProps: GetMapPlugin = this.chart.config.plugins[i];
|
|
return pluginProps.mapX.value;
|
|
}
|
|
return [];
|
|
}
|
|
|
|
public override draw() {
|
|
super.draw();
|
|
const ctx = this.chart.ctx;
|
|
const topY = this.chart.scales.linearAxis.top;
|
|
const bottomY = this.chart.scales.linearAxis.bottom;
|
|
const xVertical = this.getMapX();
|
|
// The X axis is a time scale with irregular intervals (pauses), so the
|
|
// pixel position must come from Chart.js itself, not from index * zoom.
|
|
const meta = this.chart.getDatasetMeta(0);
|
|
for (const i in xVertical) {
|
|
const idx = Number(xVertical[i]);
|
|
const point = meta.data[idx] as { x?: number } | undefined;
|
|
const x = point?.x ?? NaN;
|
|
if (!Number.isFinite(x)) {
|
|
continue;
|
|
}
|
|
ctx.save();
|
|
ctx.beginPath();
|
|
ctx.moveTo(x, topY);
|
|
ctx.lineTo(x, bottomY);
|
|
ctx.lineWidth = 3;
|
|
ctx.strokeStyle = "#666";
|
|
ctx.stroke();
|
|
ctx.restore();
|
|
}
|
|
if (this.chart?.tooltip && this.chart.tooltip.opacity > 0) {
|
|
let x = this.chart.tooltip.x - lineAlign;
|
|
if (this.chart.tooltip.xAlign === "right") {
|
|
x = this.chart.tooltip.x + this.chart.tooltip.width + lineAlign;
|
|
}
|
|
|
|
// draw line
|
|
ctx.save();
|
|
ctx.beginPath();
|
|
ctx.moveTo(x, topY);
|
|
ctx.lineTo(x, bottomY);
|
|
ctx.lineWidth = 1;
|
|
ctx.strokeStyle = "#07C";
|
|
ctx.stroke();
|
|
ctx.restore();
|
|
}
|
|
}
|
|
}
|
|
|
|
const LineWithLineChart = createTypedChart(
|
|
"line-with-line" as "line",
|
|
LineWithLineController,
|
|
);
|
|
|
|
export default LineWithLineChart;
|