Replace Daira glyphs with normalized weather icons

This commit is contained in:
b0txec
2026-08-20 10:46:26 +03:00
parent 6c9290bbfc
commit 0d641bd38f
57 changed files with 113 additions and 112 deletions
+4
View File
@@ -8,12 +8,14 @@ import { cityCoords } from "../cityCoords";
import { MapResolution, resolutionProps, windProps, WindProps } from "./mapConsts";
import { CityData, drawOnMap } from "./canvasDraw";
import { IconInputs } from "../weatherIcons/IconInputs";
import { preloadWeatherIcons } from "../weatherIcons/weatherIconAssets";
import { download } from '../../helpers/download'
export const MapView: Component<{ type: MapResolution, data: () => ResultKeyVal[], mode?: "temperature" | "faktiska", productionTemplate?: boolean }> = ({ type, data, mode = "temperature", productionTemplate = false }) => {
const [getCanvas, setCanvas] = createSignal<HTMLCanvasElement>();
const [getImg, setImg] = createSignal(new Image());
const [fontReady, setFontReady] = createSignal(false);
const [iconsReady, setIconsReady] = createSignal(mode !== "faktiska");
const weatherIconsSignal = createSignal<{[key: string]: string;}>({});
const [getWeatherIcons] = weatherIconsSignal;
const [getTitle, setTitle] = createSignal("");
@@ -44,6 +46,7 @@ export const MapView: Component<{ type: MapResolution, data: () => ResultKeyVal[
onMount(() => {
void document.fonts.load(`700 ${props.fontSize}px Monda`).then(() => setFontReady(true));
if (mode === "faktiska") void preloadWeatherIcons().then(() => setIconsReady(true));
const ctx = getCanvas()!.getContext("2d")!;
const img = new Image();
img.onload = () => {
@@ -63,6 +66,7 @@ export const MapView: Component<{ type: MapResolution, data: () => ResultKeyVal[
createEffect(() => {
fontReady();
iconsReady();
const ctx = getCanvas()!.getContext("2d")!;
const weatherIcons = getWeatherIcons();
const coordsAndData: CityData[] = data()
+14 -21
View File
@@ -1,6 +1,7 @@
import { ResolutionPropsValue, WindProps, windProps } from "./mapConsts";
import { drawRotatedImage, getAngleFromString } from "./windAngles";
import { faktiskaMarkerLayout, FaktiskaStation } from "../../pages/map-graphics/faktiskaConfig";
import { getLoadedWeatherIcon } from "../weatherIcons/weatherIconAssets";
// cityName, {x, y}, weatherValue, icon
export type CityData = [cityName: string, {x: number, y: number }, weatherValue: number, icon: string | undefined]
@@ -48,11 +49,10 @@ export function drawOnMap(
ctx.fillText(stringValue, localX, localY);
if (icon) {
ctx.fillStyle = "#FFFFFF";
ctx.font = `normal ${props.fontSize * (productionTemplate ? 4.2 : 5)}px Daira by LTV grafika`;
const iconMetrics = ctx.measureText(icon);
const glyphWidth = iconMetrics.actualBoundingBoxLeft + iconMetrics.actualBoundingBoxRight;
const badgeWidth = getBadgeWidth(ctx, stringValue, props, true);
const iconImage = getLoadedWeatherIcon(icon);
if (!iconImage) return;
const iconSize = productionTemplate ? 190 : props.boxSize * 1.35;
const badgeWidth = getBadgeWidth(ctx, stringValue, props);
if (productionTemplate) {
const layout = faktiskaMarkerLayout[city as FaktiskaStation];
@@ -61,11 +61,11 @@ export function drawOnMap(
const offsetX = layout?.iconOffsetX ?? 0;
const offsetY = layout?.iconOffsetY ?? 0;
const iconCenterX = side === "right"
? localX + badgeWidth / 2 + gap + glyphWidth / 2 + offsetX
: localX - badgeWidth / 2 - gap - glyphWidth / 2 + offsetX;
drawOpticallyCenteredGlyph(ctx, icon, iconCenterX, localY + offsetY);
? localX + badgeWidth / 2 + gap + iconSize / 2 + offsetX
: localX - badgeWidth / 2 - gap - iconSize / 2 + offsetX;
drawWeatherIcon(ctx, iconImage, iconCenterX, localY + offsetY, iconSize);
} else {
drawOpticallyCenteredGlyph(ctx, icon, localX + props.boxSize / 2 + 10 + iconMetrics.width / 2, localY);
drawWeatherIcon(ctx, iconImage, localX + badgeWidth / 2 + 10 + iconSize / 2, localY, iconSize);
}
}
});
@@ -98,20 +98,13 @@ export function drawOnMap(
ctx.fillText("M/S", windProp.offsetX + boxMiddleX + gustsWidth / 2 - 22, (windProp.offsetY + 805)*windProp.scaleY);
}
function getBadgeWidth(ctx: CanvasRenderingContext2D, value: string, props: ResolutionPropsValue, restoreValueFont = false): number {
if (restoreValueFont) ctx.font = `bold ${props.fontSize}px Monda`;
const width = Math.max(props.boxSize, Math.ceil(ctx.measureText(value).width + props.fontSize * 0.8));
if (restoreValueFont) ctx.font = `normal ${props.fontSize * 4.2}px Daira by LTV grafika`;
return width;
function getBadgeWidth(ctx: CanvasRenderingContext2D, value: string, props: ResolutionPropsValue): number {
ctx.font = `bold ${props.fontSize}px Monda`;
return Math.max(props.boxSize, Math.ceil(ctx.measureText(value).width + props.fontSize * 0.8));
}
function drawOpticallyCenteredGlyph(ctx: CanvasRenderingContext2D, glyph: string, centerX: number, centerY: number): void {
const metrics = ctx.measureText(glyph);
ctx.textAlign = "left";
ctx.textBaseline = "alphabetic";
const x = centerX + (metrics.actualBoundingBoxLeft - metrics.actualBoundingBoxRight) / 2;
const y = centerY + (metrics.actualBoundingBoxAscent - metrics.actualBoundingBoxDescent) / 2;
ctx.fillText(glyph, x, y);
export function drawWeatherIcon(ctx: CanvasRenderingContext2D, image: HTMLImageElement, centerX: number, centerY: number, size: number): void {
ctx.drawImage(image, centerX - size / 2, centerY - size / 2, size, size);
}
function drawTitleOverlay(ctx: CanvasRenderingContext2D, title: string, source: string, canvasWidth: number): void {