fixes elevation profile for drawing
This commit is contained in:
@@ -8,7 +8,7 @@ import type {
|
|||||||
Position,
|
Position,
|
||||||
} from "geojson";
|
} from "geojson";
|
||||||
|
|
||||||
import { Chart, registerables } from "chart.js";
|
import { Chart, registerables, type ScriptableContext } from "chart.js";
|
||||||
import zoomPlugin from "chartjs-plugin-zoom";
|
import zoomPlugin from "chartjs-plugin-zoom";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { CrosshairPlugin } from "chartjs-plugin-crosshair";
|
import { CrosshairPlugin } from "chartjs-plugin-crosshair";
|
||||||
@@ -369,6 +369,26 @@ export class ElevationProfile {
|
|||||||
private cumulatedTime: number[] = []
|
private cumulatedTime: number[] = []
|
||||||
private speed: number[] = [];
|
private speed: number[] = [];
|
||||||
|
|
||||||
|
private gradeColor = [
|
||||||
|
"#0d0887", // 0% and less
|
||||||
|
"#3e049c", // 1
|
||||||
|
"#6300a7", // 2
|
||||||
|
"#8606a6", // 3
|
||||||
|
"#a62098", // 4
|
||||||
|
"#c03a83", // 5
|
||||||
|
"#d5546e", // 6
|
||||||
|
"#e76f5a", // 7
|
||||||
|
"#f68d45", // 8
|
||||||
|
"#fdae32", // 9
|
||||||
|
"#fcd225", // 10
|
||||||
|
"#f0f921", // more than 10%
|
||||||
|
]
|
||||||
|
|
||||||
|
private width?: number
|
||||||
|
private height?: number
|
||||||
|
private gradient?: CanvasGradient;
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
/**
|
/**
|
||||||
* DIV element to place the chart into
|
* DIV element to place the chart into
|
||||||
@@ -399,26 +419,10 @@ export class ElevationProfile {
|
|||||||
...options,
|
...options,
|
||||||
};
|
};
|
||||||
|
|
||||||
const gradeColor = [
|
|
||||||
"#0d0887", // 0% and less
|
|
||||||
"#3e049c", // 1
|
|
||||||
"#6300a7", // 2
|
|
||||||
"#8606a6", // 3
|
|
||||||
"#a62098", // 4
|
|
||||||
"#c03a83", // 5
|
|
||||||
"#d5546e", // 6
|
|
||||||
"#e76f5a", // 7
|
|
||||||
"#f68d45", // 8
|
|
||||||
"#fdae32", // 9
|
|
||||||
"#fcd225", // 10
|
|
||||||
"#f0f921", // more than 10%
|
|
||||||
]
|
|
||||||
|
|
||||||
const distanceUnit = this.settings.unit === "imperial" ? "mi" : "km";
|
const distanceUnit = this.settings.unit === "imperial" ? "mi" : "km";
|
||||||
const elevationUnit = this.settings.unit === "imperial" ? "ft" : "m";
|
const elevationUnit = this.settings.unit === "imperial" ? "ft" : "m";
|
||||||
Chart.defaults.font.size = this.settings.fontSize;
|
Chart.defaults.font.size = this.settings.fontSize;
|
||||||
|
|
||||||
let width: number, height: number, gradient: CanvasGradient;
|
|
||||||
this.chart = new Chart<"line", Array<number>, number>(this.canvas, {
|
this.chart = new Chart<"line", Array<number>, number>(this.canvas, {
|
||||||
type: "line",
|
type: "line",
|
||||||
|
|
||||||
@@ -432,47 +436,8 @@ export class ElevationProfile {
|
|||||||
pointRadius: 0,
|
pointRadius: 0,
|
||||||
fill: !!this.settings.profileBackgroundColor,
|
fill: !!this.settings.profileBackgroundColor,
|
||||||
borderColor: (context) => {
|
borderColor: (context) => {
|
||||||
const { ctx, chartArea } = context.chart;
|
const chart = context.chart;
|
||||||
|
return this.gradientFromElevation(chart)
|
||||||
if (!chartArea) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const chartWidth = chartArea.right - chartArea.left;
|
|
||||||
const chartHeight = chartArea.bottom - chartArea.top;
|
|
||||||
if (!gradient || width !== chartWidth || height !== chartHeight) {
|
|
||||||
width = chartWidth;
|
|
||||||
height = chartHeight;
|
|
||||||
|
|
||||||
gradient = ctx.createLinearGradient(chartArea.left, 0, chartArea.right, 0);
|
|
||||||
|
|
||||||
gradient.addColorStop(0, gradeColor[0])
|
|
||||||
|
|
||||||
let prevColor = gradeColor[0];
|
|
||||||
for (let i = 0; i < this.grade.length; i++) {
|
|
||||||
const grade = ~~(Math.abs(this.grade[i]) / 2.5);
|
|
||||||
|
|
||||||
let color;
|
|
||||||
if (grade < 1) {
|
|
||||||
color = gradeColor[0]
|
|
||||||
}
|
|
||||||
else if (grade > 10) {
|
|
||||||
color = gradeColor[11];
|
|
||||||
} else {
|
|
||||||
color = gradeColor[grade];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (color !== prevColor) {
|
|
||||||
const percentDone = this.cumulatedDistance[i] / this.cumulatedDistance[this.cumulatedDistance.length - 1]
|
|
||||||
gradient.addColorStop(percentDone, color);
|
|
||||||
prevColor = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return gradient;
|
|
||||||
},
|
},
|
||||||
// borderColor: this.settings.profileLineColor ?? "#0000",
|
// borderColor: this.settings.profileLineColor ?? "#0000",
|
||||||
backgroundColor: this.settings.profileBackgroundColor ?? "#0000",
|
backgroundColor: this.settings.profileBackgroundColor ?? "#0000",
|
||||||
@@ -720,7 +685,7 @@ export class ElevationProfile {
|
|||||||
this.waypointPositions.forEach((position: number, index: number) => {
|
this.waypointPositions.forEach((position: number, index: number) => {
|
||||||
|
|
||||||
const xPos = xScale.getPixelForValue(position); // X-axis pixel for tick
|
const xPos = xScale.getPixelForValue(position); // X-axis pixel for tick
|
||||||
|
|
||||||
// Create custom HTML tick
|
// Create custom HTML tick
|
||||||
const wpDiv = document.createElement("div");
|
const wpDiv = document.createElement("div");
|
||||||
wpDiv.className = "wp-marker absolute -translate-x-1/2 w-6 aspect-square bg-background-inverse rounded-full flex justify-center items-center text-content-inverse cursor-pointer hover:scale-110";
|
wpDiv.className = "wp-marker absolute -translate-x-1/2 w-6 aspect-square bg-background-inverse rounded-full flex justify-center items-center text-content-inverse cursor-pointer hover:scale-110";
|
||||||
@@ -785,6 +750,55 @@ export class ElevationProfile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gradientFromElevation(chart: Chart, force: boolean = false) {
|
||||||
|
const ctx = chart.ctx;
|
||||||
|
const chartArea = chart.chartArea;
|
||||||
|
|
||||||
|
if (!chartArea) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chartWidth = chartArea.right - chartArea.left;
|
||||||
|
const chartHeight = chartArea.bottom - chartArea.top;
|
||||||
|
|
||||||
|
if (chartWidth == 0 || chartHeight == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.gradient || this.width !== chartWidth || this.height !== chartHeight || force) {
|
||||||
|
this.width = chartWidth;
|
||||||
|
this.height = chartHeight;
|
||||||
|
|
||||||
|
this.gradient = ctx.createLinearGradient(chartArea.left, 0, chartArea.right, 0) as CanvasGradient;
|
||||||
|
|
||||||
|
this.gradient.addColorStop(0, this.gradeColor[0])
|
||||||
|
|
||||||
|
let prevColor = this.gradeColor[0];
|
||||||
|
for (let i = 0; i < this.grade.length; i++) {
|
||||||
|
const grade = ~~(Math.abs(this.grade[i]) / 2.5);
|
||||||
|
|
||||||
|
let color;
|
||||||
|
if (grade < 1) {
|
||||||
|
color = this.gradeColor[0]
|
||||||
|
}
|
||||||
|
else if (grade > 10) {
|
||||||
|
color = this.gradeColor[11];
|
||||||
|
} else {
|
||||||
|
color = this.gradeColor[grade];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (color !== prevColor) {
|
||||||
|
const percentDone = this.cumulatedDistance[i] / this.cumulatedDistance[this.cumulatedDistance.length - 1]
|
||||||
|
this.gradient.addColorStop(percentDone, color);
|
||||||
|
prevColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.gradient;
|
||||||
|
}
|
||||||
|
|
||||||
createWindowExtractLineString(): LineString {
|
createWindowExtractLineString(): LineString {
|
||||||
const scaleMin = this.chart.scales.x.min;
|
const scaleMin = this.chart.scales.x.min;
|
||||||
const scaleMax = this.chart.scales.x.max;
|
const scaleMax = this.chart.scales.x.max;
|
||||||
@@ -849,7 +863,7 @@ export class ElevationProfile {
|
|||||||
|
|
||||||
this.times = times;
|
this.times = times;
|
||||||
|
|
||||||
this.elevatedPositions = smoothElevations(positions, positions.length / 100);
|
this.elevatedPositions = smoothElevations(positions, Math.ceil(positions.length / 100));
|
||||||
|
|
||||||
this.cumulatedDistance = haversineCumulatedDistanceWgs84(
|
this.cumulatedDistance = haversineCumulatedDistanceWgs84(
|
||||||
this.elevatedPositions
|
this.elevatedPositions
|
||||||
@@ -984,6 +998,11 @@ export class ElevationProfile {
|
|||||||
(pos) => pos[2]
|
(pos) => pos[2]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const gradient = this.gradientFromElevation(this.chart, true);
|
||||||
|
if (gradient) {
|
||||||
|
this.chart.data.datasets[0].borderColor = gradient
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.chart.options.scales &&
|
this.chart.options.scales &&
|
||||||
this.chart.options.scales.x &&
|
this.chart.options.scales.x &&
|
||||||
|
|||||||
@@ -636,6 +636,7 @@
|
|||||||
$form.distance = totals.distance;
|
$form.distance = totals.distance;
|
||||||
$form.duration = totals.duration;
|
$form.duration = totals.duration;
|
||||||
$form.elevation_gain = totals.elevationGain;
|
$form.elevation_gain = totals.elevationGain;
|
||||||
|
$form.elevation_loss = totals.elevationLoss;
|
||||||
$form.expand.gpx_data = route.toString();
|
$form.expand.gpx_data = route.toString();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user