mirror of
				https://github.com/gpxstudio/gpx.studio.git
				synced 2025-11-04 05:21:09 +00:00 
			
		
		
		
	highway, sac_scale and mtb:scale coloring
This commit is contained in:
		@@ -25,40 +25,137 @@ export const surfaceColors: { [key: string]: string } = {
 | 
			
		||||
    "stone": "#ffd991",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function getSurfaceColor(surface: string): string {
 | 
			
		||||
    return surfaceColors[surface] ? surfaceColors[surface] : surfaceColors.missing;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const highwayColors: { [key: string]: string } = {
 | 
			
		||||
    "missing": "#d1d1d1",
 | 
			
		||||
    "residential": "#73b2ff",
 | 
			
		||||
    "service": "#b3b3cc",
 | 
			
		||||
    "track": "#946f43",
 | 
			
		||||
    "unclassified": "#e0e0e0",
 | 
			
		||||
    "footway": "#a3c989",
 | 
			
		||||
    "tertiary": "#ffdd7f",
 | 
			
		||||
    "path": "#a3c989",
 | 
			
		||||
    "secondary": "#ffd75f",
 | 
			
		||||
    "primary": "#ff6e5c",
 | 
			
		||||
    "cycleway": "#ffbb6e",
 | 
			
		||||
    "trunk": "#ff5e4d",
 | 
			
		||||
    "living_street": "#9de2ff",
 | 
			
		||||
    "motorway": "#ff4d33",
 | 
			
		||||
    "motorway_link": "#ff947f",
 | 
			
		||||
    "steps": "#8d91a2",
 | 
			
		||||
    "road": "#e0e0e0",
 | 
			
		||||
    "pedestrian": "#c1c8e4",
 | 
			
		||||
    "motorway_link": "#ff4d33",
 | 
			
		||||
    "trunk": "#ff5e4d",
 | 
			
		||||
    "trunk_link": "#ff947f",
 | 
			
		||||
    "primary_link": "#ff8d7b",
 | 
			
		||||
    "secondary_link": "#ffcb66",
 | 
			
		||||
    "tertiary_link": "#ffdd8b",
 | 
			
		||||
    "primary": "#ff6e5c",
 | 
			
		||||
    "primary_link": "#ff6e5c",
 | 
			
		||||
    "secondary": "#ff8d7b",
 | 
			
		||||
    "secondary_link": "#ff8d7b",
 | 
			
		||||
    "tertiary": "#ffd75f",
 | 
			
		||||
    "tertiary_link": "#ffd75f",
 | 
			
		||||
    "unclassified": "#f1f2a5",
 | 
			
		||||
    "road": "#f1f2a5",
 | 
			
		||||
    "residential": "#73b2ff",
 | 
			
		||||
    "living_street": "#73b2ff",
 | 
			
		||||
    "service": "#9c9cd9",
 | 
			
		||||
    "track": "#a8e381",
 | 
			
		||||
    "footway": "#a8e381",
 | 
			
		||||
    "path": "#a8e381",
 | 
			
		||||
    "pedestrian": "#a8e381",
 | 
			
		||||
    "cycleway": "#9de2ff",
 | 
			
		||||
    "construction": "#e09a4a",
 | 
			
		||||
    "bridleway": "#a3c989",
 | 
			
		||||
    "platform": "#c4c4c4",
 | 
			
		||||
    "proposed": "#e0e0e0",
 | 
			
		||||
    "bridleway": "#946f43",
 | 
			
		||||
    "raceway": "#ff0000",
 | 
			
		||||
    "rest_area": "#73b2ff",
 | 
			
		||||
    "abandoned": "#e0e0e0",
 | 
			
		||||
    "services": "#ffe066",
 | 
			
		||||
    "corridor": "#c4c4c4",
 | 
			
		||||
    "bus_stop": "#ffe6e6",
 | 
			
		||||
    "busway": "#ffe6e6",
 | 
			
		||||
    "elevator": "#c4c4c4",
 | 
			
		||||
    "via_ferrata": "#8d91a2"
 | 
			
		||||
};  
 | 
			
		||||
    "rest_area": "#9c9cd9",
 | 
			
		||||
    "services": "#9c9cd9",
 | 
			
		||||
    "corridor": "#474747",
 | 
			
		||||
    "elevator": "#474747",
 | 
			
		||||
    "steps": "#474747",
 | 
			
		||||
    "bus_stop": "#8545a3",
 | 
			
		||||
    "busway": "#8545a3",
 | 
			
		||||
    "via_ferrata": "#474747"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const sacScaleColors: { [key: string]: string } = {
 | 
			
		||||
    "hiking": "#007700",
 | 
			
		||||
    "mountain_hiking": "#1843ad",
 | 
			
		||||
    "demanding_mountain_hiking": "#ffff00",
 | 
			
		||||
    "alpine_hiking": "#ff9233",
 | 
			
		||||
    "demanding_alpine_hiking": "#ff0000",
 | 
			
		||||
    "difficult_alpine_hiking": "#000000",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const mtbScaleColors: { [key: string]: string } = {
 | 
			
		||||
    "0-": "#007700",
 | 
			
		||||
    "0": "#007700",
 | 
			
		||||
    "0+": "#007700",
 | 
			
		||||
    "1-": "#1843ad",
 | 
			
		||||
    "1": "#1843ad",
 | 
			
		||||
    "1+": "#1843ad",
 | 
			
		||||
    "2-": "#ffff00",
 | 
			
		||||
    "2": "#ffff00",
 | 
			
		||||
    "2+": "#ffff00",
 | 
			
		||||
    "3": "#ff0000",
 | 
			
		||||
    "4": "#00ff00",
 | 
			
		||||
    "5": "#000000",
 | 
			
		||||
    "6": "#b105eb",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function createPattern(backgroundColor: string, sacScaleColor: string | undefined, mtbScaleColor: string | undefined, size: number = 16, lineWidth: number = 4) {
 | 
			
		||||
    let canvas = document.createElement('canvas');
 | 
			
		||||
    canvas.width = size;
 | 
			
		||||
    canvas.height = size;
 | 
			
		||||
    let ctx = canvas.getContext('2d');
 | 
			
		||||
    if (ctx) {
 | 
			
		||||
        ctx.fillStyle = backgroundColor;
 | 
			
		||||
        ctx.fillRect(0, 0, size, size);
 | 
			
		||||
        ctx.lineWidth = lineWidth;
 | 
			
		||||
 | 
			
		||||
        const halfSize = size / 2;
 | 
			
		||||
        const halfLineWidth = lineWidth / 2;
 | 
			
		||||
        if (sacScaleColor) {
 | 
			
		||||
            ctx.strokeStyle = sacScaleColor;
 | 
			
		||||
            ctx.beginPath();
 | 
			
		||||
            ctx.moveTo(halfSize - halfLineWidth, - halfLineWidth);
 | 
			
		||||
            ctx.lineTo(size + halfLineWidth, halfSize + halfLineWidth);
 | 
			
		||||
            ctx.stroke();
 | 
			
		||||
            ctx.beginPath();
 | 
			
		||||
            ctx.moveTo(- halfLineWidth, halfSize - halfLineWidth);
 | 
			
		||||
            ctx.lineTo(halfSize + halfLineWidth, size + halfLineWidth);
 | 
			
		||||
            ctx.stroke();
 | 
			
		||||
        }
 | 
			
		||||
        if (mtbScaleColor) {
 | 
			
		||||
            ctx.strokeStyle = mtbScaleColor;
 | 
			
		||||
            ctx.beginPath();
 | 
			
		||||
            ctx.moveTo(halfSize - halfLineWidth, size + halfLineWidth);
 | 
			
		||||
            ctx.lineTo(size + halfLineWidth, halfSize - halfLineWidth);
 | 
			
		||||
            ctx.stroke();
 | 
			
		||||
            ctx.beginPath();
 | 
			
		||||
            ctx.moveTo(- halfLineWidth, halfSize + halfLineWidth);
 | 
			
		||||
            ctx.lineTo(halfSize + halfLineWidth, - halfLineWidth);
 | 
			
		||||
            ctx.stroke();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return ctx?.createPattern(canvas, 'repeat') || backgroundColor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const patterns: Record<string, string | CanvasPattern> = {};
 | 
			
		||||
export function getHighwayColor(highway: string, sacScale: string | undefined, mtbScale: string | undefined) {
 | 
			
		||||
    let backgroundColor = highwayColors[highway] ? highwayColors[highway] : highwayColors.missing;
 | 
			
		||||
    let sacScaleColor = sacScale ? sacScaleColors[sacScale] : undefined;
 | 
			
		||||
    let mtbScaleColor = mtbScale ? mtbScaleColors[mtbScale] : undefined;
 | 
			
		||||
    if (sacScale || mtbScale) {
 | 
			
		||||
        let patternId = `${backgroundColor}-${[sacScale, mtbScale].filter(x => x).join('-')}`;
 | 
			
		||||
        if (!patterns[patternId]) {
 | 
			
		||||
            patterns[patternId] = createPattern(backgroundColor, sacScaleColor, mtbScaleColor);
 | 
			
		||||
        }
 | 
			
		||||
        return patterns[patternId];
 | 
			
		||||
    }
 | 
			
		||||
    return backgroundColor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const maxSlope = 20;
 | 
			
		||||
export function getSlopeColor(slope: number): string {
 | 
			
		||||
    if (slope > maxSlope) {
 | 
			
		||||
        slope = maxSlope;
 | 
			
		||||
    } else if (slope < -maxSlope) {
 | 
			
		||||
        slope = -maxSlope;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let v = slope / maxSlope;
 | 
			
		||||
    v = 1 / (1 + Math.exp(-6 * v));
 | 
			
		||||
    v = v - 0.5;
 | 
			
		||||
 | 
			
		||||
    let hue = ((0.5 - v) * 120).toString(10);
 | 
			
		||||
    let lightness = 90 - Math.abs(v) * 70;
 | 
			
		||||
 | 
			
		||||
    return `hsl(${hue},70%,${lightness}%)`;
 | 
			
		||||
}
 | 
			
		||||
@@ -19,7 +19,7 @@
 | 
			
		||||
		ChartNoAxesColumn,
 | 
			
		||||
		Construction
 | 
			
		||||
	} from 'lucide-svelte';
 | 
			
		||||
	import { surfaceColors, highwayColors } from '$lib/assets/colors';
 | 
			
		||||
	import { getSlopeColor, getSurfaceColor, getHighwayColor } from '$lib/assets/colors';
 | 
			
		||||
	import { _, locale } from 'svelte-i18n';
 | 
			
		||||
	import {
 | 
			
		||||
		getCadenceWithUnits,
 | 
			
		||||
@@ -443,33 +443,20 @@
 | 
			
		||||
		chart.update();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	let maxSlope = 20;
 | 
			
		||||
	function slopeFillCallback(context) {
 | 
			
		||||
		let slope = context.p0.raw.slope.segment;
 | 
			
		||||
		if (slope > maxSlope) {
 | 
			
		||||
			slope = maxSlope;
 | 
			
		||||
		} else if (slope < -maxSlope) {
 | 
			
		||||
			slope = -maxSlope;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		let v = slope / maxSlope;
 | 
			
		||||
		v = 1 / (1 + Math.exp(-6 * v));
 | 
			
		||||
		v = v - 0.5;
 | 
			
		||||
 | 
			
		||||
		let hue = ((0.5 - v) * 120).toString(10);
 | 
			
		||||
		let lightness = 90 - Math.abs(v) * 70;
 | 
			
		||||
 | 
			
		||||
		return ['hsl(', hue, ',70%,', lightness, '%)'].join('');
 | 
			
		||||
		return getSlopeColor(context.p0.raw.slope.segment);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function surfaceFillCallback(context) {
 | 
			
		||||
		let surface = context.p0.raw.extensions.surface;
 | 
			
		||||
		return surfaceColors[surface] ? surfaceColors[surface] : surfaceColors.missing;
 | 
			
		||||
		return getSurfaceColor(context.p0.raw.extensions.surface);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function highwayFillCallback(context) {
 | 
			
		||||
		let highway = context.p0.raw.extensions.highway;
 | 
			
		||||
		return highwayColors[highway] ? highwayColors[highway] : highwayColors.missing;
 | 
			
		||||
		return getHighwayColor(
 | 
			
		||||
			context.p0.raw.extensions.highway,
 | 
			
		||||
			context.p0.raw.extensions.sac_scale,
 | 
			
		||||
			context.p0.raw.extensions['mtb:scale']
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	$: if (chart) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user