@versatiles/png-renderer 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -34
- package/dist/index.d.ts +796 -72
- package/dist/index.js +8192 -3756
- package/package.json +4 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
/// <reference types="geojson" />
|
|
2
|
+
import { Canvas } from '@napi-rs/canvas';
|
|
3
|
+
export { Canvas } from '@napi-rs/canvas';
|
|
4
|
+
|
|
2
5
|
//#endregion
|
|
3
6
|
//#region src/types.g.d.ts
|
|
4
7
|
type ColorSpecification = string;
|
|
@@ -2559,19 +2562,585 @@ type BackgroundLayerSpecification = {
|
|
|
2559
2562
|
};
|
|
2560
2563
|
};
|
|
2561
2564
|
type LayerSpecification = FillLayerSpecification | LineLayerSpecification | SymbolLayerSpecification | CircleLayerSpecification | HeatmapLayerSpecification | FillExtrusionLayerSpecification | RasterLayerSpecification | HillshadeLayerSpecification | ColorReliefLayerSpecification | BackgroundLayerSpecification;
|
|
2565
|
+
//#endregion
|
|
2566
|
+
//#region src/expression/types/color_spaces.d.ts
|
|
2567
|
+
/**
|
|
2568
|
+
* @param r Red component 0..1
|
|
2569
|
+
* @param g Green component 0..1
|
|
2570
|
+
* @param b Blue component 0..1
|
|
2571
|
+
* @param alpha Alpha component 0..1
|
|
2572
|
+
*/
|
|
2573
|
+
type RGBColor = [r: number, g: number, b: number, alpha: number];
|
|
2574
|
+
/**
|
|
2575
|
+
* @param h Hue as degrees 0..360
|
|
2576
|
+
* @param c Chroma 0..~230
|
|
2577
|
+
* @param l Lightness as percentage 0..100
|
|
2578
|
+
* @param alpha Alpha component 0..1
|
|
2579
|
+
*/
|
|
2580
|
+
type HCLColor = [h: number, c: number, l: number, alpha: number];
|
|
2581
|
+
/**
|
|
2582
|
+
* @param l Lightness as percentage 0..100
|
|
2583
|
+
* @param a A axis value -125..125
|
|
2584
|
+
* @param b B axis value -125..125
|
|
2585
|
+
* @param alpha Alpha component 0..1
|
|
2586
|
+
*/
|
|
2587
|
+
type LABColor = [l: number, a: number, b: number, alpha: number];
|
|
2588
|
+
//#endregion
|
|
2589
|
+
//#region src/expression/types/color.d.ts
|
|
2590
|
+
type InterpolationColorSpace = 'rgb' | 'hcl' | 'lab';
|
|
2591
|
+
/**
|
|
2592
|
+
* Color representation used by WebGL.
|
|
2593
|
+
* Defined in sRGB color space and pre-blended with alpha.
|
|
2594
|
+
* @private
|
|
2595
|
+
*/
|
|
2596
|
+
declare class Color {
|
|
2597
|
+
readonly r: number;
|
|
2598
|
+
readonly g: number;
|
|
2599
|
+
readonly b: number;
|
|
2600
|
+
readonly a: number;
|
|
2601
|
+
/**
|
|
2602
|
+
* @param r Red component premultiplied by `alpha` 0..1
|
|
2603
|
+
* @param g Green component premultiplied by `alpha` 0..1
|
|
2604
|
+
* @param b Blue component premultiplied by `alpha` 0..1
|
|
2605
|
+
* @param [alpha=1] Alpha component 0..1
|
|
2606
|
+
* @param [premultiplied=true] Whether the `r`, `g` and `b` values have already
|
|
2607
|
+
* been multiplied by alpha. If `true` nothing happens if `false` then they will
|
|
2608
|
+
* be multiplied automatically.
|
|
2609
|
+
*/
|
|
2610
|
+
constructor(r: number, g: number, b: number, alpha?: number, premultiplied?: boolean);
|
|
2611
|
+
static black: Color;
|
|
2612
|
+
static white: Color;
|
|
2613
|
+
static transparent: Color;
|
|
2614
|
+
static red: Color;
|
|
2615
|
+
/**
|
|
2616
|
+
* Parses CSS color strings and converts colors to sRGB color space if needed.
|
|
2617
|
+
* Officially supported color formats:
|
|
2618
|
+
* - keyword, e.g. 'aquamarine' or 'steelblue'
|
|
2619
|
+
* - hex (with 3, 4, 6 or 8 digits), e.g. '#f0f' or '#e9bebea9'
|
|
2620
|
+
* - rgb and rgba, e.g. 'rgb(0,240,120)' or 'rgba(0%,94%,47%,0.1)' or 'rgb(0 240 120 / .3)'
|
|
2621
|
+
* - hsl and hsla, e.g. 'hsl(0,0%,83%)' or 'hsla(0,0%,83%,.5)' or 'hsl(0 0% 83% / 20%)'
|
|
2622
|
+
*
|
|
2623
|
+
* @param input CSS color string to parse.
|
|
2624
|
+
* @returns A `Color` instance, or `undefined` if the input is not a valid color string.
|
|
2625
|
+
*/
|
|
2626
|
+
static parse(input: Color | string | undefined | null): Color | undefined;
|
|
2627
|
+
/**
|
|
2628
|
+
* Used in color interpolation and by 'to-rgba' expression.
|
|
2629
|
+
*
|
|
2630
|
+
* @returns Gien color, with reversed alpha blending, in sRGB color space.
|
|
2631
|
+
*/
|
|
2632
|
+
get rgb(): RGBColor;
|
|
2633
|
+
/**
|
|
2634
|
+
* Used in color interpolation.
|
|
2635
|
+
*
|
|
2636
|
+
* @returns Gien color, with reversed alpha blending, in HCL color space.
|
|
2637
|
+
*/
|
|
2638
|
+
get hcl(): HCLColor;
|
|
2639
|
+
/**
|
|
2640
|
+
* Used in color interpolation.
|
|
2641
|
+
*
|
|
2642
|
+
* @returns Gien color, with reversed alpha blending, in LAB color space.
|
|
2643
|
+
*/
|
|
2644
|
+
get lab(): LABColor;
|
|
2645
|
+
/**
|
|
2646
|
+
* Lazy getter pattern. When getter is called for the first time lazy value
|
|
2647
|
+
* is calculated and then overwrites getter function in given object instance.
|
|
2648
|
+
*
|
|
2649
|
+
* @example:
|
|
2650
|
+
* const redColor = Color.parse('red');
|
|
2651
|
+
* let x = redColor.hcl; // this will invoke `get hcl()`, which will calculate
|
|
2652
|
+
* // the value of red in HCL space and invoke this `overwriteGetter` function
|
|
2653
|
+
* // which in turn will set a field with a key 'hcl' in the `redColor` object.
|
|
2654
|
+
* // In other words it will override `get hcl()` from its `Color` prototype
|
|
2655
|
+
* // with its own property: hcl = [calculated red value in hcl].
|
|
2656
|
+
* let y = redColor.hcl; // next call will no longer invoke getter but simply
|
|
2657
|
+
* // return the previously calculated value
|
|
2658
|
+
* x === y; // true - `x` is exactly the same object as `y`
|
|
2659
|
+
*
|
|
2660
|
+
* @param getterKey Getter key
|
|
2661
|
+
* @param lazyValue Lazily calculated value to be memoized by current instance
|
|
2662
|
+
* @private
|
|
2663
|
+
*/
|
|
2664
|
+
private overwriteGetter;
|
|
2665
|
+
/**
|
|
2666
|
+
* Used by 'to-string' expression.
|
|
2667
|
+
*
|
|
2668
|
+
* @returns Serialized color in format `rgba(r,g,b,a)`
|
|
2669
|
+
* where r,g,b are numbers within 0..255 and alpha is number within 1..0
|
|
2670
|
+
*
|
|
2671
|
+
* @example
|
|
2672
|
+
* var purple = new Color.parse('purple');
|
|
2673
|
+
* purple.toString; // = "rgba(128,0,128,1)"
|
|
2674
|
+
* var translucentGreen = new Color.parse('rgba(26, 207, 26, .73)');
|
|
2675
|
+
* translucentGreen.toString(); // = "rgba(26,207,26,0.73)"
|
|
2676
|
+
*/
|
|
2677
|
+
toString(): string;
|
|
2678
|
+
static interpolate(from: Color, to: Color, t: number, spaceKey?: InterpolationColorSpace): Color;
|
|
2679
|
+
}
|
|
2680
|
+
//#endregion
|
|
2681
|
+
//#region src/point2d.d.ts
|
|
2682
|
+
interface Point2D$1 {
|
|
2683
|
+
x: number;
|
|
2684
|
+
y: number;
|
|
2685
|
+
}
|
|
2686
|
+
//#endregion
|
|
2687
|
+
//#region src/expression/index.d.ts
|
|
2688
|
+
type Feature$1 = {
|
|
2689
|
+
readonly type: 0 | 1 | 2 | 3 | 'Unknown' | 'Point' | 'MultiPoint' | 'LineString' | 'MultiLineString' | 'Polygon' | 'MultiPolygon';
|
|
2690
|
+
readonly id?: any;
|
|
2691
|
+
readonly properties: {
|
|
2692
|
+
[_: string]: any;
|
|
2693
|
+
};
|
|
2694
|
+
readonly patterns?: {
|
|
2695
|
+
[_: string]: {
|
|
2696
|
+
min: string;
|
|
2697
|
+
mid: string;
|
|
2698
|
+
max: string;
|
|
2699
|
+
};
|
|
2700
|
+
};
|
|
2701
|
+
readonly dashes?: {
|
|
2702
|
+
[_: string]: {
|
|
2703
|
+
min: string;
|
|
2704
|
+
mid: string;
|
|
2705
|
+
max: string;
|
|
2706
|
+
};
|
|
2707
|
+
};
|
|
2708
|
+
readonly geometry?: Array<Array<Point2D$1>>;
|
|
2709
|
+
};
|
|
2710
|
+
|
|
2711
|
+
/** Values of the style's global state, by name, as read by `global-state` expressions. */
|
|
2712
|
+
type GlobalState = Record<string, unknown>;
|
|
2713
|
+
|
|
2714
|
+
type Properties = Record<string, unknown>;
|
|
2715
|
+
type Patterns = Record<string, {
|
|
2716
|
+
min: string;
|
|
2717
|
+
mid: string;
|
|
2718
|
+
max: string;
|
|
2719
|
+
}>;
|
|
2720
|
+
type Geometry = Point2D[][];
|
|
2721
|
+
type Bbox = [number, number, number, number];
|
|
2722
|
+
declare class Point2D implements Point2D$1 {
|
|
2723
|
+
x: number;
|
|
2724
|
+
y: number;
|
|
2725
|
+
constructor(x: number, y: number);
|
|
2726
|
+
isZero(): boolean;
|
|
2727
|
+
scale(factor: number): this;
|
|
2728
|
+
translate(offset: Point2D): this;
|
|
2729
|
+
getProject2Pixel(): Point2D;
|
|
2730
|
+
}
|
|
2731
|
+
declare class Feature implements Feature$1 {
|
|
2732
|
+
#private;
|
|
2733
|
+
readonly type: 'LineString' | 'Point' | 'Polygon';
|
|
2734
|
+
readonly id: unknown;
|
|
2735
|
+
readonly properties: Properties;
|
|
2736
|
+
readonly patterns?: Patterns;
|
|
2737
|
+
readonly geometry: Geometry;
|
|
2738
|
+
/**
|
|
2739
|
+
* The boundary of a polygon for the fill-antialias outline, as open polylines — when it
|
|
2740
|
+
* differs from the polygon's rings, i.e. when the polygon was clipped to its tile: the
|
|
2741
|
+
* clipped edges along the tile border are not part of the outline.
|
|
2742
|
+
*/
|
|
2743
|
+
readonly outline?: Geometry;
|
|
2744
|
+
constructor(opt: {
|
|
2745
|
+
type: 'LineString' | 'Point' | 'Polygon';
|
|
2746
|
+
id?: unknown;
|
|
2747
|
+
properties: Properties;
|
|
2748
|
+
patterns?: Patterns;
|
|
2749
|
+
geometry: Geometry;
|
|
2750
|
+
outline?: Geometry;
|
|
2751
|
+
});
|
|
2752
|
+
getBbox(): Bbox;
|
|
2753
|
+
doesOverlap(bbox: Bbox): boolean;
|
|
2754
|
+
}
|
|
2755
|
+
|
|
2756
|
+
interface ClipCircle {
|
|
2757
|
+
x: number;
|
|
2758
|
+
y: number;
|
|
2759
|
+
radius: number;
|
|
2760
|
+
}
|
|
2761
|
+
type Triangle = [[number, number], [number, number], [number, number]];
|
|
2762
|
+
/** A triangle of a raster tile's mesh on the globe, drawn with its own affine transform. */
|
|
2763
|
+
interface RasterTriangle {
|
|
2764
|
+
/** Corners of the triangle within the tile image, in tile units (0..1). */
|
|
2765
|
+
source: Triangle;
|
|
2766
|
+
/** The same corners on screen, in pixels. */
|
|
2767
|
+
target: Triangle;
|
|
2768
|
+
}
|
|
2769
|
+
/** Space around the map's center, as MapLibre's `padding`, in pixels. */
|
|
2770
|
+
interface Padding {
|
|
2771
|
+
top?: number;
|
|
2772
|
+
right?: number;
|
|
2773
|
+
bottom?: number;
|
|
2774
|
+
left?: number;
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
/**
|
|
2778
|
+
* A drawing surface the render pipeline paints a map onto. It only describes *how* to
|
|
2779
|
+
* draw; how the result is handed back is up to the backend, because those differ in
|
|
2780
|
+
* kind: the SVG backend serializes to a string ({@link StringRenderer}), while a raster
|
|
2781
|
+
* backend produces an encoded image buffer.
|
|
2782
|
+
*/
|
|
2783
|
+
interface Renderer {
|
|
2784
|
+
readonly width: number;
|
|
2785
|
+
readonly height: number;
|
|
2786
|
+
/**
|
|
2787
|
+
* These two may be asynchronous, like {@link Renderer.drawIcons}: a pattern is a sprite
|
|
2788
|
+
* image, which a raster backend has to decode first.
|
|
2789
|
+
*/
|
|
2790
|
+
drawBackgroundFill(style: BackgroundStyle): void | Promise<void>;
|
|
2791
|
+
drawPolygons(id: string, features: [Feature, FillStyle][]): void | Promise<void>;
|
|
2792
|
+
/** May be asynchronous, as a line pattern is a sprite image (see `drawPolygons`). */
|
|
2793
|
+
drawLineStrings(id: string, features: [Feature, LineStyle][]): void | Promise<void>;
|
|
2794
|
+
drawCircles(id: string, features: [Feature, CircleStyle][]): void;
|
|
2795
|
+
/**
|
|
2796
|
+
* Draws text labels, and (below) icons. Each feature is a single point: the pipeline
|
|
2797
|
+
* has already placed the symbol, one per point, line or polygon.
|
|
2798
|
+
*/
|
|
2799
|
+
drawLabels(id: string, features: [Feature, SymbolStyle][]): void;
|
|
2800
|
+
/**
|
|
2801
|
+
* These two may be asynchronous. Their images arrive as data URIs, which a raster
|
|
2802
|
+
* backend has to decode before it can paint them, while the SVG backend simply embeds
|
|
2803
|
+
* the URI and stays synchronous. The pipeline awaits both, so layers keep their order
|
|
2804
|
+
* either way.
|
|
2805
|
+
*/
|
|
2806
|
+
drawIcons(id: string, features: [Feature, IconStyle][], spriteAtlas: SpriteAtlas): void | Promise<void>;
|
|
2807
|
+
drawRasterTiles(id: string, tiles: RasterTile[], style: RasterStyle): void | Promise<void>;
|
|
2808
|
+
/** Restricts all drawing to a circle (the silhouette of the globe). */
|
|
2809
|
+
setClipCircle?(circle: ClipCircle): void;
|
|
2810
|
+
/**
|
|
2811
|
+
* Called once the map is complete: undoes any state set up for drawing it (such as the
|
|
2812
|
+
* clip circle), so that whoever gets the result can keep drawing on it.
|
|
2813
|
+
*/
|
|
2814
|
+
finish?(): void;
|
|
2815
|
+
}
|
|
2816
|
+
/**
|
|
2817
|
+
* How labels and icons are drawn: not at all, as `<text>`, as the style's glyphs traced
|
|
2818
|
+
* into outlines, or as those with invisible text over them.
|
|
2819
|
+
*/
|
|
2820
|
+
type LabelMode = 'none' | 'text' | 'glyphs' | 'glyphs-text';
|
|
2821
|
+
/**
|
|
2822
|
+
* A glyph's outline, in pixels at 24 per em (`GLYPH_EM`), as closed rings (to be filled
|
|
2823
|
+
* even-odd): x from the middle of its advance, y from the middle of its line of text.
|
|
2824
|
+
*/
|
|
2825
|
+
interface GlyphOutline {
|
|
2826
|
+
/** Identifies the outline, for renderers that define each once. */
|
|
2827
|
+
key: string;
|
|
2828
|
+
rings: [number, number][][];
|
|
2829
|
+
/** The glyph's advance, in ems. */
|
|
2830
|
+
advance: number;
|
|
2831
|
+
}
|
|
2832
|
+
/** A glyph of a label drawn as glyphs: its outline, its middle on screen, angle and scale. */
|
|
2833
|
+
interface PlacedGlyph {
|
|
2834
|
+
outline: GlyphOutline;
|
|
2835
|
+
/** Where the middle of the glyph's advance lies, in the middle of its line of text. */
|
|
2836
|
+
x: number;
|
|
2837
|
+
y: number;
|
|
2838
|
+
/** Clockwise, in degrees. */
|
|
2839
|
+
angle: number;
|
|
2840
|
+
/** From the outline's units (24 per em) to pixels: the text size / 24. */
|
|
2841
|
+
scale: number;
|
|
2842
|
+
}
|
|
2843
|
+
interface BackgroundStyle {
|
|
2844
|
+
color: Color;
|
|
2845
|
+
opacity: number;
|
|
2846
|
+
/** `background-pattern`: drawn instead of `color`. */
|
|
2847
|
+
pattern?: FillPattern;
|
|
2848
|
+
}
|
|
2849
|
+
/**
|
|
2850
|
+
* A sprite image repeated over an area (`fill-pattern`, `background-pattern`), at its
|
|
2851
|
+
* display size (`width / pixelRatio`) and anchored to the world, as in MapLibre.
|
|
2852
|
+
*/
|
|
2853
|
+
interface FillPattern {
|
|
2854
|
+
/** The image's name in the sprite. */
|
|
2855
|
+
name: string;
|
|
2856
|
+
sprite: SpriteEntry;
|
|
2857
|
+
/**
|
|
2858
|
+
* A screen point where one copy of the image has its top-left corner: one aligned with
|
|
2859
|
+
* the world's origin, so the pattern moves with the map.
|
|
2860
|
+
*/
|
|
2861
|
+
origin: [number, number];
|
|
2862
|
+
/** How far the pattern turns around `origin`, clockwise in degrees: with the map's bearing. */
|
|
2863
|
+
angle?: number;
|
|
2864
|
+
/**
|
|
2865
|
+
* How much larger than its display size the image is drawn (1 if not given): MapLibre
|
|
2866
|
+
* scales patterns with the map from the zoom level's integer part, as its tiles are.
|
|
2867
|
+
*/
|
|
2868
|
+
scale?: number;
|
|
2869
|
+
}
|
|
2870
|
+
interface FillStyle {
|
|
2871
|
+
color: Color;
|
|
2872
|
+
opacity: number;
|
|
2873
|
+
/** `fill-pattern`: drawn instead of `color`. */
|
|
2874
|
+
pattern?: FillPattern;
|
|
2875
|
+
translate: [number, number];
|
|
2876
|
+
/**
|
|
2877
|
+
* fill-outline-color. When omitted the fill `color` is used (MapLibre's
|
|
2878
|
+
* default: the antialias outline is drawn in the fill color).
|
|
2879
|
+
*/
|
|
2880
|
+
outlineColor?: Color;
|
|
2881
|
+
/**
|
|
2882
|
+
* fill-antialias. When truthy, a ~1px edge outline in `outlineColor` is drawn
|
|
2883
|
+
* over all fills of the layer (a separate pass) so a lower feature's border
|
|
2884
|
+
* composites on top of later overlapping fills — matching MapLibre for
|
|
2885
|
+
* choropleths and stacked polygons.
|
|
2886
|
+
*/
|
|
2887
|
+
antialias?: boolean;
|
|
2888
|
+
}
|
|
2889
|
+
interface LineStyle {
|
|
2890
|
+
blur: number;
|
|
2891
|
+
cap: 'butt' | 'round' | 'square';
|
|
2892
|
+
color: Color;
|
|
2893
|
+
dasharray?: number[];
|
|
2894
|
+
join: 'bevel' | 'miter' | 'round';
|
|
2895
|
+
miterLimit: number;
|
|
2896
|
+
offset: number;
|
|
2897
|
+
opacity: number;
|
|
2898
|
+
translate: [number, number];
|
|
2899
|
+
width: number;
|
|
2900
|
+
/** `line-pattern`: drawn instead of `color` and `dasharray`. */
|
|
2901
|
+
pattern?: LinePattern;
|
|
2902
|
+
}
|
|
2903
|
+
/**
|
|
2904
|
+
* A sprite image repeated along a line (`line-pattern`), spanning its width, as in MapLibre
|
|
2905
|
+
* (see `line_pattern.ts`).
|
|
2906
|
+
*/
|
|
2907
|
+
interface LinePattern {
|
|
2908
|
+
/** The image's name in the sprite. */
|
|
2909
|
+
name: string;
|
|
2910
|
+
sprite: SpriteEntry;
|
|
2911
|
+
/** How far one copy of the image reaches along the line, in pixels. */
|
|
2912
|
+
period: number;
|
|
2913
|
+
}
|
|
2914
|
+
interface CircleStyle {
|
|
2915
|
+
color: Color;
|
|
2916
|
+
/** Opacity of the fill only; the stroke has its own, as in MapLibre. */
|
|
2917
|
+
opacity: number;
|
|
2918
|
+
radius: number;
|
|
2919
|
+
translate: [number, number];
|
|
2920
|
+
strokeWidth: number;
|
|
2921
|
+
strokeColor: Color;
|
|
2922
|
+
strokeOpacity: number;
|
|
2923
|
+
/** `circle-blur`: the share of the outer radius over which the circle fades out. */
|
|
2924
|
+
blur?: number;
|
|
2925
|
+
}
|
|
2926
|
+
interface RasterStyle {
|
|
2927
|
+
opacity: number;
|
|
2928
|
+
hueRotate: number;
|
|
2929
|
+
brightnessMin: number;
|
|
2930
|
+
brightnessMax: number;
|
|
2931
|
+
saturation: number;
|
|
2932
|
+
contrast: number;
|
|
2933
|
+
resampling: 'linear' | 'nearest';
|
|
2934
|
+
}
|
|
2935
|
+
/** One character of a label along a line: its center, and its angle in degrees. */
|
|
2936
|
+
interface GlyphPlacement {
|
|
2937
|
+
text: string;
|
|
2938
|
+
x: number;
|
|
2939
|
+
y: number;
|
|
2940
|
+
angle: number;
|
|
2941
|
+
}
|
|
2942
|
+
interface SymbolStyle {
|
|
2943
|
+
/**
|
|
2944
|
+
* For a label along a line: where each of its characters goes. The label is drawn glyph
|
|
2945
|
+
* by glyph there, centered on each position, instead of at the feature's point.
|
|
2946
|
+
*/
|
|
2947
|
+
path?: GlyphPlacement[];
|
|
2948
|
+
/**
|
|
2949
|
+
* For a label drawn as the style's glyphs: each glyph's outline, where it goes and how
|
|
2950
|
+
* large. Drawn instead of the text.
|
|
2951
|
+
*/
|
|
2952
|
+
glyphs?: PlacedGlyph[];
|
|
2953
|
+
/** With `glyphs`: also the text, invisible, so the label stays selectable and searchable. */
|
|
2954
|
+
textOverlay?: boolean;
|
|
2955
|
+
/**
|
|
2956
|
+
* For a label of several lines: each line, and the point its alignment (`justify`)
|
|
2957
|
+
* refers to, vertically at the middle of the line. The anchor and offset are applied
|
|
2958
|
+
* already; `text` is all lines.
|
|
2959
|
+
*/
|
|
2960
|
+
lines?: {
|
|
2961
|
+
text: string;
|
|
2962
|
+
x: number;
|
|
2963
|
+
y: number;
|
|
2964
|
+
width?: number;
|
|
2965
|
+
}[];
|
|
2966
|
+
/** How the `lines` align at their points (`text-justify`). */
|
|
2967
|
+
justify?: 'left' | 'center' | 'right';
|
|
2968
|
+
/** `text-letter-spacing`, in ems. */
|
|
2969
|
+
letterSpacing?: number;
|
|
2970
|
+
text: string;
|
|
2971
|
+
size: number;
|
|
2972
|
+
font: string[];
|
|
2973
|
+
anchor: string;
|
|
2974
|
+
offset: [number, number];
|
|
2975
|
+
rotate: number;
|
|
2976
|
+
color: Color;
|
|
2977
|
+
opacity: number;
|
|
2978
|
+
haloColor: Color;
|
|
2979
|
+
haloWidth: number;
|
|
2980
|
+
}
|
|
2981
|
+
interface IconStyle {
|
|
2982
|
+
image: string;
|
|
2983
|
+
size: number;
|
|
2984
|
+
anchor: string;
|
|
2985
|
+
offset: [number, number];
|
|
2986
|
+
rotate: number;
|
|
2987
|
+
opacity: number;
|
|
2988
|
+
sdf: boolean;
|
|
2989
|
+
color: Color;
|
|
2990
|
+
haloColor: Color;
|
|
2991
|
+
haloWidth: number;
|
|
2992
|
+
/**
|
|
2993
|
+
* Fitted to its label (`icon-text-fit`): the box the icon spans, `[left, top, right,
|
|
2994
|
+
* bottom]` from its point, before `icon-size`; `anchor` and `offset` then do not apply.
|
|
2995
|
+
*/
|
|
2996
|
+
fit?: [number, number, number, number];
|
|
2997
|
+
}
|
|
2998
|
+
interface RasterTile {
|
|
2999
|
+
x: number;
|
|
3000
|
+
y: number;
|
|
3001
|
+
width: number;
|
|
3002
|
+
height: number;
|
|
3003
|
+
dataUri: string;
|
|
3004
|
+
/**
|
|
3005
|
+
* On the globe a tile cannot be drawn as a rectangle. Instead it is split into a mesh of
|
|
3006
|
+
* triangles, each drawn with its own affine transform.
|
|
3007
|
+
*/
|
|
3008
|
+
triangles?: RasterTriangle[];
|
|
3009
|
+
/**
|
|
3010
|
+
* An image on its own (an `image` source), with no neighbouring tiles to close seams
|
|
3011
|
+
* with: its triangles are drawn without the underlay that reaches beyond its border.
|
|
3012
|
+
*/
|
|
3013
|
+
standalone?: boolean;
|
|
3014
|
+
}
|
|
3015
|
+
/** An image of the style's sprite: where it is on its sprite sheet, and how it stretches. */
|
|
3016
|
+
interface SpriteEntry {
|
|
3017
|
+
width: number;
|
|
3018
|
+
height: number;
|
|
3019
|
+
x: number;
|
|
3020
|
+
y: number;
|
|
3021
|
+
pixelRatio: number;
|
|
3022
|
+
sdf: boolean;
|
|
3023
|
+
sheetDataUri: string;
|
|
3024
|
+
sheetWidth: number;
|
|
3025
|
+
sheetHeight: number;
|
|
3026
|
+
/** The columns of the image that stretch with `icon-text-fit`, as `[from, to]` pixels. */
|
|
3027
|
+
stretchX?: [number, number][];
|
|
3028
|
+
/** The rows of the image that stretch with `icon-text-fit`, as `[from, to]` pixels. */
|
|
3029
|
+
stretchY?: [number, number][];
|
|
3030
|
+
/** The part of the image `icon-text-fit` fits to the label: `[left, top, right, bottom]` pixels. */
|
|
3031
|
+
content?: [number, number, number, number];
|
|
3032
|
+
/** Whether a fitted image keeps the content's aspect ratio, horizontally. */
|
|
3033
|
+
textFitWidth?: TextFit;
|
|
3034
|
+
/** Whether a fitted image keeps the content's aspect ratio, vertically. */
|
|
3035
|
+
textFitHeight?: TextFit;
|
|
3036
|
+
}
|
|
3037
|
+
type TextFit = 'stretchOrShrink' | 'stretchOnly' | 'proportional';
|
|
3038
|
+
type SpriteAtlas = Map<string, SpriteEntry>;
|
|
3039
|
+
|
|
3040
|
+
/**
|
|
3041
|
+
* The part of a `Response` the renderer uses. A real `Response` has all of it; the type
|
|
3042
|
+
* is spelled out so that using this package needs neither the DOM nor Node's type
|
|
3043
|
+
* definitions.
|
|
3044
|
+
*/
|
|
3045
|
+
interface FetchResponse {
|
|
3046
|
+
readonly ok: boolean;
|
|
3047
|
+
readonly status: number;
|
|
3048
|
+
readonly headers: {
|
|
3049
|
+
get(name: string): string | null;
|
|
3050
|
+
};
|
|
3051
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
3052
|
+
json(): Promise<unknown>;
|
|
3053
|
+
}
|
|
3054
|
+
/**
|
|
3055
|
+
* Loads a URL, like `fetch`: the renderer loads tiles, sprites, TileJSON documents and GeoJSON data through it. It is called
|
|
3056
|
+
* with the URL only, and should resolve to a `Response`.
|
|
3057
|
+
*/
|
|
3058
|
+
type FetchFunction = (url: string) => Promise<FetchResponse>;
|
|
2562
3059
|
|
|
2563
|
-
/** Options for {@link
|
|
2564
|
-
interface
|
|
3060
|
+
/** Options for {@link SVGMapRenderer}: what stays the same for every view of the map. */
|
|
3061
|
+
interface SVGMapRendererOptions {
|
|
2565
3062
|
/**
|
|
2566
3063
|
* The MapLibre style to render.
|
|
2567
3064
|
*
|
|
2568
|
-
*
|
|
2569
|
-
*
|
|
2570
|
-
*
|
|
2571
|
-
*
|
|
2572
|
-
*
|
|
3065
|
+
* A source may list its tile URLs (`tiles: [...]`) or point at a TileJSON document
|
|
3066
|
+
* (`url: '.../tiles.json'`), which is fetched once, like the sprite, with
|
|
3067
|
+
* {@link SVGMapRendererOptions.fetch}. As in MapLibre GL JS, `tiles`, `minzoom`,
|
|
3068
|
+
* `maxzoom` and the like come from the document unless the style sets them, and
|
|
3069
|
+
* relative tile URLs are resolved against the document's URL. A GeoJSON source's `data`
|
|
3070
|
+
* may be a URL too. A source whose TileJSON or GeoJSON cannot be loaded is left out, and
|
|
3071
|
+
* the next render tries again.
|
|
2573
3072
|
*/
|
|
2574
3073
|
style: StyleSpecification;
|
|
3074
|
+
/**
|
|
3075
|
+
* Whether and how to draw the style's symbol layers, its labels and icons:
|
|
3076
|
+
*
|
|
3077
|
+
* - `'none'`: neither labels nor icons.
|
|
3078
|
+
* - `'text'`: labels as `<text>` naming the style's fonts (`text-font`), which whatever
|
|
3079
|
+
* displays the SVG resolves, so they show in the intended typeface only where that font
|
|
3080
|
+
* is installed. In PNG output, with the fonts given by `fonts`.
|
|
3081
|
+
* - `'glyphs'`: labels as the style's own glyphs (`glyphs`), the letter shapes MapLibre
|
|
3082
|
+
* draws, traced into outlines: exact in every viewer and editor, but not text. Each
|
|
3083
|
+
* glyph is defined once and reused.
|
|
3084
|
+
* - `'glyphs-text'`: as `'glyphs'`, with the text laid invisibly over the outlines, so labels
|
|
3085
|
+
* stay selectable and searchable. (In PNG output, the same as `'glyphs'`.)
|
|
3086
|
+
*
|
|
3087
|
+
* Labels are placed as in MapLibre: at points, inside each polygon at the point farthest
|
|
3088
|
+
* from its edges, and along lines; labels and icons that would overlap one placed before
|
|
3089
|
+
* are left out, from the top layer down. With glyphs, they are laid out with MapLibre's
|
|
3090
|
+
* own metrics; as text, with the widths of Noto Sans. A style without `glyphs`, or glyphs
|
|
3091
|
+
* that cannot be loaded, fall back to `'text'`, reported through `onWarning`.
|
|
3092
|
+
* @defaultValue `'none'`, or as given by {@link SVGMapRendererOptions.renderLabels}
|
|
3093
|
+
*/
|
|
3094
|
+
labels?: LabelMode;
|
|
3095
|
+
/**
|
|
3096
|
+
* Draw the style's labels and icons.
|
|
3097
|
+
* @deprecated Use {@link SVGMapRendererOptions.labels}: `true` is `'glyphs-text'`, `false`
|
|
3098
|
+
* is `'none'`.
|
|
3099
|
+
* @defaultValue `false`
|
|
3100
|
+
*/
|
|
3101
|
+
renderLabels?: boolean;
|
|
3102
|
+
/**
|
|
3103
|
+
* How much memory the fetched tiles may take, in bytes. Tiles are kept so that
|
|
3104
|
+
* rendering an overlapping view does not fetch them again; beyond this size, the least
|
|
3105
|
+
* recently used ones are dropped. `0` keeps none.
|
|
3106
|
+
*
|
|
3107
|
+
* Tiles are kept for the lifetime of the instance, regardless of the HTTP caching
|
|
3108
|
+
* headers they were served with; see {@link SVGMapRenderer.clearCache}.
|
|
3109
|
+
* @defaultValue `134217728` (128 MB)
|
|
3110
|
+
*/
|
|
3111
|
+
tileCacheSize?: number;
|
|
3112
|
+
/**
|
|
3113
|
+
* Loads tiles, sprites, TileJSON documents and GeoJSON data, like `fetch`, which is the default. Pass your own to send
|
|
3114
|
+
* headers, go through a proxy, or keep tiles in a cache on disk.
|
|
3115
|
+
*
|
|
3116
|
+
* It must return a real `Response`, and its status matters: a 404 or 204 means the
|
|
3117
|
+
* server has no such tile, which is remembered (see {@link SVGMapRendererOptions.tileCacheSize}); any other
|
|
3118
|
+
* error status, or a rejected promise, counts as failed, and the next render tries
|
|
3119
|
+
* again.
|
|
3120
|
+
* @defaultValue the global `fetch`
|
|
3121
|
+
*/
|
|
3122
|
+
fetch?: FetchFunction;
|
|
3123
|
+
/**
|
|
3124
|
+
* Called with a message for each part of the style the renderer does not draw: a layer
|
|
3125
|
+
* type, a layer property, a source, or a TileJSON document that could not be loaded. Each
|
|
3126
|
+
* message is reported once per instance. Pass `() => {}` to silence them.
|
|
3127
|
+
*
|
|
3128
|
+
* Properties that make no difference to a flat, north-up map (e.g. `*-pitch-alignment`)
|
|
3129
|
+
* are not reported, nor are symbol layers unless {@link SVGMapRendererOptions.labels}
|
|
3130
|
+
* is set.
|
|
3131
|
+
* @defaultValue `console.warn`
|
|
3132
|
+
*/
|
|
3133
|
+
onWarning?: (message: string) => void;
|
|
3134
|
+
/**
|
|
3135
|
+
* Values for the style's global state, read by `global-state` expressions, e.g. to
|
|
3136
|
+
* switch the language or a theme of a style. They override the defaults in the style's
|
|
3137
|
+
* `state`, like `map.setGlobalStateProperty(name, value)` in MapLibre GL JS.
|
|
3138
|
+
* @defaultValue the defaults of the style's `state`
|
|
3139
|
+
*/
|
|
3140
|
+
globalState?: GlobalState;
|
|
3141
|
+
}
|
|
3142
|
+
/** The view to render: size, centre and zoom. */
|
|
3143
|
+
interface ViewOptions {
|
|
2575
3144
|
/**
|
|
2576
3145
|
* Width of the image in pixels.
|
|
2577
3146
|
* @defaultValue `1024`
|
|
@@ -2584,34 +3153,127 @@ interface RenderToSVGOptions {
|
|
|
2584
3153
|
height?: number;
|
|
2585
3154
|
/**
|
|
2586
3155
|
* Longitude of the map centre, in degrees.
|
|
2587
|
-
* @defaultValue `0`
|
|
3156
|
+
* @defaultValue the longitude of the style's `center`, else `0`
|
|
2588
3157
|
*/
|
|
2589
3158
|
lon?: number;
|
|
2590
3159
|
/**
|
|
2591
3160
|
* Latitude of the map centre, in degrees.
|
|
2592
|
-
* @defaultValue `0`
|
|
3161
|
+
* @defaultValue the latitude of the style's `center`, else `0`
|
|
2593
3162
|
*/
|
|
2594
3163
|
lat?: number;
|
|
2595
3164
|
/**
|
|
2596
3165
|
* Zoom level, as in MapLibre: each step doubles the scale. Fractional values are
|
|
2597
3166
|
* allowed.
|
|
2598
|
-
* @defaultValue `2`
|
|
3167
|
+
* @defaultValue the style's `zoom`, else `2`
|
|
2599
3168
|
*/
|
|
2600
3169
|
zoom?: number;
|
|
2601
3170
|
/**
|
|
2602
|
-
*
|
|
3171
|
+
* The compass direction that is up, in degrees, as in MapLibre: `90` puts east at the
|
|
3172
|
+
* top. The map turns around the image's center; labels stay upright.
|
|
3173
|
+
* @defaultValue the style's `bearing`, else `0`
|
|
3174
|
+
*/
|
|
3175
|
+
bearing?: number;
|
|
3176
|
+
/**
|
|
3177
|
+
* Space around the map's center, in pixels, as MapLibre's `padding`: the center (`lon`,
|
|
3178
|
+
* `lat`) sits in the middle of the area inside it, e.g. to keep it clear of a panel laid
|
|
3179
|
+
* over the image. A number applies to all sides.
|
|
3180
|
+
* @defaultValue `0`
|
|
3181
|
+
*/
|
|
3182
|
+
padding?: number | Padding;
|
|
3183
|
+
}
|
|
3184
|
+
/**
|
|
3185
|
+
* Renders many views of one MapLibre style as SVG.
|
|
3186
|
+
*
|
|
3187
|
+
* Does the work that depends only on the style once, when constructed or on the first
|
|
3188
|
+
* render, instead of on every call as {@link renderToSVG} does: the style is parsed once,
|
|
3189
|
+
* and the sprite (the icons, needed with `labels`) and the glyphs are fetched once. Tiles are kept
|
|
3190
|
+
* too (up to {@link SVGMapRendererOptions.tileCacheSize}), so overlapping views share
|
|
3191
|
+
* them. Use it to render a batch of views, e.g. thumbnails or a series of map sections.
|
|
3192
|
+
*
|
|
3193
|
+
* The style is read when the instance is created and is expected not to change
|
|
3194
|
+
* afterwards; to render a changed style, create a new instance. Renders may run
|
|
3195
|
+
* concurrently.
|
|
3196
|
+
*
|
|
3197
|
+
* @example Render several views of one style
|
|
3198
|
+
* ```ts
|
|
3199
|
+
* import { SVGMapRenderer } from '@versatiles/svg-renderer';
|
|
3200
|
+
*
|
|
3201
|
+
* const map = new SVGMapRenderer({ style });
|
|
3202
|
+
*
|
|
3203
|
+
* const berlin = await map.renderSVG({ lon: 13.4, lat: 52.52, zoom: 12 });
|
|
3204
|
+
* const potsdam = await map.renderSVG({ lon: 13.06, lat: 52.4, zoom: 12 });
|
|
3205
|
+
* ```
|
|
3206
|
+
*/
|
|
3207
|
+
declare class SVGMapRenderer {
|
|
3208
|
+
#private;
|
|
3209
|
+
/**
|
|
3210
|
+
* @param options - The style, whether to draw labels, the tile cache size, how to load
|
|
3211
|
+
* tiles and sprites, and where to report unsupported parts of the style.
|
|
3212
|
+
* @throws If `tileCacheSize` is negative or not a number.
|
|
3213
|
+
*/
|
|
3214
|
+
constructor(options: SVGMapRendererOptions);
|
|
3215
|
+
/**
|
|
3216
|
+
* Renders one view of the map as SVG. The result is a single self-contained SVG
|
|
3217
|
+
* document, as described on {@link renderToSVG}.
|
|
3218
|
+
*
|
|
3219
|
+
* @param view - Size, centre and zoom. All optional.
|
|
3220
|
+
* @returns The SVG document, as a string beginning with `<svg`.
|
|
3221
|
+
* @throws If `width` or `height` is not positive.
|
|
3222
|
+
*/
|
|
3223
|
+
renderSVG(view?: ViewOptions): Promise<string>;
|
|
3224
|
+
/**
|
|
3225
|
+
* Forgets the fetched tiles, sprite, TileJSON documents and GeoJSON data, so the next render fetches them again, e.g.
|
|
3226
|
+
* after they were updated on the server, or to free their memory.
|
|
3227
|
+
*/
|
|
3228
|
+
clearCache(): void;
|
|
3229
|
+
/** Draws `view` onto `renderer`, which must already have the view's size. */
|
|
3230
|
+
protected draw<R extends Renderer>(renderer: R, view: ViewOptions): Promise<R>;
|
|
3231
|
+
/**
|
|
3232
|
+
* Where a coordinate lands in the image of `view`: its position in the units of
|
|
3233
|
+
* `width` and `height`, the same in the SVG and on the canvas of `renderCanvas`. Use
|
|
3234
|
+
* it to place your own drawing on the map.
|
|
2603
3235
|
*
|
|
2604
|
-
*
|
|
2605
|
-
*
|
|
2606
|
-
*
|
|
2607
|
-
*
|
|
3236
|
+
* On the globe, a coordinate on its far side is hidden; then this returns `undefined`.
|
|
3237
|
+
* A position outside the image is returned as is, so it can lie beyond `width` and
|
|
3238
|
+
* `height`, or be negative. The map ends at about ±85.05° latitude, as in MapLibre: a
|
|
3239
|
+
* latitude beyond that, up to the poles, gives the position of the map's edge.
|
|
2608
3240
|
*
|
|
2609
|
-
*
|
|
2610
|
-
*
|
|
2611
|
-
*
|
|
2612
|
-
*
|
|
3241
|
+
* @example Mark a place on a rendered canvas
|
|
3242
|
+
* ```ts
|
|
3243
|
+
* const view = { lon: 13.4, lat: 52.52, zoom: 12 };
|
|
3244
|
+
* const canvas = await map.renderCanvas(view);
|
|
3245
|
+
* const [x, y] = map.project(view, [13.3777, 52.5163])!; // Brandenburg Gate
|
|
3246
|
+
* const ctx = canvas.getContext('2d');
|
|
3247
|
+
* ctx.beginPath();
|
|
3248
|
+
* ctx.arc(x, y, 6, 0, 2 * Math.PI);
|
|
3249
|
+
* ctx.fill();
|
|
3250
|
+
* ```
|
|
3251
|
+
*
|
|
3252
|
+
* @param view - The view the image was rendered with.
|
|
3253
|
+
* @param lonLat - Longitude and latitude, in degrees.
|
|
3254
|
+
* @returns `[x, y]`, or `undefined` for a point hidden on the globe, and for a
|
|
3255
|
+
* longitude or latitude that is not a finite number.
|
|
3256
|
+
* @throws If `width` or `height` is not positive.
|
|
2613
3257
|
*/
|
|
2614
|
-
|
|
3258
|
+
project(view: ViewOptions, lonLat: [number, number]): [number, number] | undefined;
|
|
3259
|
+
/**
|
|
3260
|
+
* The opposite of {@link SVGMapRenderer.project}: the coordinate shown at a position in
|
|
3261
|
+
* the image of `view`, e.g. where a user clicked on it.
|
|
3262
|
+
*
|
|
3263
|
+
* Where the image shows no map — next to the globe, or beyond the poles of the mercator
|
|
3264
|
+
* map (about ±85°) — this returns `undefined`. The longitude is between -180 and 180.
|
|
3265
|
+
*
|
|
3266
|
+
* @param view - The view the image was rendered with.
|
|
3267
|
+
* @param xy - A position in the units of `width` and `height`.
|
|
3268
|
+
* @returns `[lon, lat]` in degrees, or `undefined` where there is no map, and for a
|
|
3269
|
+
* position that is not a finite number.
|
|
3270
|
+
* @throws If `width` or `height` is not positive.
|
|
3271
|
+
*/
|
|
3272
|
+
unproject(view: ViewOptions, xy: [number, number]): [number, number] | undefined;
|
|
3273
|
+
}
|
|
3274
|
+
|
|
3275
|
+
/** Options for {@link renderToSVG}: the style and the view, in one object. */
|
|
3276
|
+
interface RenderToSVGOptions extends Omit<SVGMapRendererOptions, 'tileCacheSize'>, ViewOptions {
|
|
2615
3277
|
}
|
|
2616
3278
|
/**
|
|
2617
3279
|
* Renders a MapLibre style to an SVG image.
|
|
@@ -2625,43 +3287,23 @@ interface RenderToSVGOptions {
|
|
|
2625
3287
|
* `@versatiles/svg-renderer`, `@versatiles/png-renderer` and
|
|
2626
3288
|
* `@versatiles/maplibre-svg-export`; the examples import it from the first.
|
|
2627
3289
|
*
|
|
2628
|
-
*
|
|
2629
|
-
*
|
|
2630
|
-
*
|
|
2631
|
-
* import { inlineSources, osm } from '@versatiles/style';
|
|
2632
|
-
* import { writeFile } from 'node:fs/promises';
|
|
2633
|
-
*
|
|
2634
|
-
* // inlineSources() resolves the style's TileJSON sources into tile URLs,
|
|
2635
|
-
* // which the renderer needs. Without it the map comes out empty.
|
|
2636
|
-
* const style = await inlineSources(osm({ theme: 'colorful' }));
|
|
3290
|
+
* Each call starts from scratch: it parses the style and fetches the tiles and the
|
|
3291
|
+
* sprite again. To render many views of one style, use {@link SVGMapRenderer}, which
|
|
3292
|
+
* keeps them between renders.
|
|
2637
3293
|
*
|
|
2638
|
-
*
|
|
2639
|
-
* style,
|
|
2640
|
-
* width: 800,
|
|
2641
|
-
* height: 600,
|
|
2642
|
-
* lon: 13.4, // Berlin
|
|
2643
|
-
* lat: 52.52,
|
|
2644
|
-
* zoom: 12,
|
|
2645
|
-
* });
|
|
2646
|
-
*
|
|
2647
|
-
* await writeFile('berlin.svg', svg);
|
|
2648
|
-
* ```
|
|
2649
|
-
*
|
|
2650
|
-
* @example Render a hosted style in the browser
|
|
3294
|
+
* @example Render a map
|
|
2651
3295
|
* ```ts
|
|
2652
3296
|
* import { renderToSVG } from '@versatiles/svg-renderer';
|
|
2653
3297
|
*
|
|
2654
|
-
*
|
|
2655
|
-
* const style = await fetch(
|
|
2656
|
-
* 'https://tiles.versatiles.org/assets/styles/colorful/style.json',
|
|
2657
|
-
* ).then((response) => response.json());
|
|
3298
|
+
* const url = 'https://tiles.versatiles.org/assets/styles/colorful/style.json';
|
|
3299
|
+
* const style = await (await fetch(url)).json();
|
|
2658
3300
|
*
|
|
2659
|
-
*
|
|
3301
|
+
* const svg = await renderToSVG({ style, lon: 13.4, lat: 52.52, zoom: 12 });
|
|
2660
3302
|
* ```
|
|
2661
3303
|
*
|
|
2662
3304
|
* @example Include labels and icons
|
|
2663
3305
|
* ```ts
|
|
2664
|
-
* const svg = await renderToSVG({ style, lon: 13.4, lat: 52.52, zoom: 14,
|
|
3306
|
+
* const svg = await renderToSVG({ style, lon: 13.4, lat: 52.52, zoom: 14, labels: 'glyphs-text' });
|
|
2665
3307
|
* ```
|
|
2666
3308
|
*
|
|
2667
3309
|
* @param options - What to render and how large. Only `style` is required.
|
|
@@ -2693,7 +3335,7 @@ interface RenderToPNGOptions extends RenderToSVGOptions {
|
|
|
2693
3335
|
* installed on the machine, which is usually not the one the style asked for.
|
|
2694
3336
|
*
|
|
2695
3337
|
* Fonts are registered process-wide, so a name registered by one call stays available
|
|
2696
|
-
* to every later call. Only matters when {@link RenderToSVGOptions.
|
|
3338
|
+
* to every later call. Only matters when {@link RenderToSVGOptions.labels} is `'text'`.
|
|
2697
3339
|
*/
|
|
2698
3340
|
fonts?: Record<string, string>;
|
|
2699
3341
|
}
|
|
@@ -2704,6 +3346,10 @@ interface RenderToPNGOptions extends RenderToSVGOptions {
|
|
|
2704
3346
|
* directly instead of producing SVG — no browser or SVG rasterizer needed. Satellite and
|
|
2705
3347
|
* other raster tiles in WebP work too, which many SVG rasterizers cannot decode.
|
|
2706
3348
|
*
|
|
3349
|
+
* Each call starts from scratch: it parses the style and fetches the tiles and the
|
|
3350
|
+
* sprite again. To render many views of one style, use {@link PNGMapRenderer}, which
|
|
3351
|
+
* keeps them between renders.
|
|
3352
|
+
*
|
|
2707
3353
|
* **Node.js only.** It draws with the native canvas backend `@napi-rs/canvas`, a dependency
|
|
2708
3354
|
* of this package that npm installs together with it, including the prebuilt binary for
|
|
2709
3355
|
* the platform. If that binary is missing (e.g. installed with `--omit=optional`, or
|
|
@@ -2713,40 +3359,24 @@ interface RenderToPNGOptions extends RenderToSVGOptions {
|
|
|
2713
3359
|
* @example Render a map to a file
|
|
2714
3360
|
* ```ts
|
|
2715
3361
|
* import { renderToPNG } from '@versatiles/png-renderer';
|
|
2716
|
-
* import { inlineSources, osm } from '@versatiles/style';
|
|
2717
3362
|
* import { writeFile } from 'node:fs/promises';
|
|
2718
3363
|
*
|
|
2719
|
-
*
|
|
2720
|
-
* const style = await
|
|
2721
|
-
*
|
|
2722
|
-
* const png = await renderToPNG({
|
|
2723
|
-
* style,
|
|
2724
|
-
* width: 800,
|
|
2725
|
-
* height: 600,
|
|
2726
|
-
* lon: 13.4, // Berlin
|
|
2727
|
-
* lat: 52.52,
|
|
2728
|
-
* zoom: 12,
|
|
2729
|
-
* scale: 2, // 1600 × 1200 pixels, for high-resolution screens
|
|
2730
|
-
* });
|
|
3364
|
+
* const url = 'https://tiles.versatiles.org/assets/styles/colorful/style.json';
|
|
3365
|
+
* const style = await (await fetch(url)).json();
|
|
2731
3366
|
*
|
|
3367
|
+
* const png = await renderToPNG({ style, lon: 13.4, lat: 52.52, zoom: 12 });
|
|
2732
3368
|
* await writeFile('berlin.png', png);
|
|
2733
3369
|
* ```
|
|
2734
3370
|
*
|
|
2735
3371
|
* @example Draw labels in the style's own fonts
|
|
2736
3372
|
* ```ts
|
|
2737
|
-
* // The VersaTiles styles use Noto Sans. One source is `npm install @fontsource/noto-sans`
|
|
2738
|
-
* // (its "latin" files cover Western European scripts; it ships others alongside).
|
|
2739
|
-
* const files = 'node_modules/@fontsource/noto-sans/files';
|
|
2740
3373
|
* const png = await renderToPNG({
|
|
2741
3374
|
* style,
|
|
2742
3375
|
* lon: 13.4,
|
|
2743
3376
|
* lat: 52.52,
|
|
2744
3377
|
* zoom: 14,
|
|
2745
|
-
*
|
|
2746
|
-
* fonts: {
|
|
2747
|
-
* noto_sans_regular: `${files}/noto-sans-latin-400-normal.woff2`,
|
|
2748
|
-
* noto_sans_bold: `${files}/noto-sans-latin-700-normal.woff2`,
|
|
2749
|
-
* },
|
|
3378
|
+
* labels: 'text',
|
|
3379
|
+
* fonts: { noto_sans_regular: 'fonts/NotoSans-Regular.ttf', noto_sans_bold: 'fonts/NotoSans-Bold.ttf' },
|
|
2750
3380
|
* });
|
|
2751
3381
|
* ```
|
|
2752
3382
|
*
|
|
@@ -2759,6 +3389,100 @@ interface RenderToPNGOptions extends RenderToSVGOptions {
|
|
|
2759
3389
|
* positive, or if a font in `fonts` cannot be loaded.
|
|
2760
3390
|
*/
|
|
2761
3391
|
declare function renderToPNG(options: RenderToPNGOptions): Promise<Uint8Array>;
|
|
3392
|
+
/**
|
|
3393
|
+
* Renders a MapLibre style onto a canvas, to draw on top of it or to encode it in another
|
|
3394
|
+
* format than PNG. Takes the options of {@link renderToPNG}; the canvas is described on
|
|
3395
|
+
* {@link PNGMapRenderer.renderCanvas}.
|
|
3396
|
+
*
|
|
3397
|
+
* @example Save a map as JPEG
|
|
3398
|
+
* ```ts
|
|
3399
|
+
* const canvas = await renderToCanvas({ style, lon: 13.4, lat: 52.52, zoom: 12 });
|
|
3400
|
+
* await writeFile('berlin.jpg', await canvas.encode('jpeg', 85));
|
|
3401
|
+
* ```
|
|
3402
|
+
*
|
|
3403
|
+
* @returns A `Canvas` of `@napi-rs/canvas`.
|
|
3404
|
+
* @throws As {@link renderToPNG}.
|
|
3405
|
+
*/
|
|
3406
|
+
declare function renderToCanvas(options: RenderToPNGOptions): Promise<Canvas>;
|
|
3407
|
+
/** Options for {@link PNGMapRenderer}: those of {@link SVGMapRenderer}, plus fonts. */
|
|
3408
|
+
interface PNGMapRendererOptions extends SVGMapRendererOptions {
|
|
3409
|
+
/**
|
|
3410
|
+
* Font files to draw labels with, as `{ "<text-font name>": "<path to a font file>" }`.
|
|
3411
|
+
* See {@link RenderToPNGOptions.fonts}.
|
|
3412
|
+
*/
|
|
3413
|
+
fonts?: Record<string, string>;
|
|
3414
|
+
}
|
|
3415
|
+
/** The view to render as PNG: {@link ViewOptions}, plus the pixel density. */
|
|
3416
|
+
interface PNGViewOptions extends ViewOptions {
|
|
3417
|
+
/**
|
|
3418
|
+
* Pixel density, like a device pixel ratio. The image is `width * scale` by
|
|
3419
|
+
* `height * scale` pixels, while the map is laid out as if it were `width` by `height`.
|
|
3420
|
+
* See {@link RenderToPNGOptions.scale}.
|
|
3421
|
+
* @defaultValue `1`
|
|
3422
|
+
*/
|
|
3423
|
+
scale?: number;
|
|
3424
|
+
}
|
|
3425
|
+
/**
|
|
3426
|
+
* Renders many views of one MapLibre style, as PNG or SVG.
|
|
3427
|
+
*
|
|
3428
|
+
* An {@link SVGMapRenderer} that can also render PNG, sharing everything it keeps between
|
|
3429
|
+
* the two formats: the parsed style, the sprite and the tiles. For PNG it also keeps the
|
|
3430
|
+
* decoded tile and sprite images. Like {@link renderToPNG}, PNG rendering works in Node.js
|
|
3431
|
+
* only.
|
|
3432
|
+
*
|
|
3433
|
+
* @example Render several views of one style
|
|
3434
|
+
* ```ts
|
|
3435
|
+
* import { PNGMapRenderer } from '@versatiles/png-renderer';
|
|
3436
|
+
*
|
|
3437
|
+
* const map = new PNGMapRenderer({ style });
|
|
3438
|
+
*
|
|
3439
|
+
* const berlin = await map.renderPNG({ lon: 13.4, lat: 52.52, zoom: 12 });
|
|
3440
|
+
* const potsdam = await map.renderPNG({ lon: 13.06, lat: 52.4, zoom: 12 });
|
|
3441
|
+
* const svg = await map.renderSVG({ lon: 13.4, lat: 52.52, zoom: 12 });
|
|
3442
|
+
* ```
|
|
3443
|
+
*/
|
|
3444
|
+
declare class PNGMapRenderer extends SVGMapRenderer {
|
|
3445
|
+
#private;
|
|
3446
|
+
/** @param options - The style, whether to draw labels, the tile cache size, and fonts. */
|
|
3447
|
+
constructor(options: PNGMapRendererOptions);
|
|
3448
|
+
/**
|
|
3449
|
+
* Renders one view of the map as PNG.
|
|
3450
|
+
*
|
|
3451
|
+
* @param view - Size, centre, zoom and pixel density. All optional.
|
|
3452
|
+
* @returns The encoded PNG file, as described on {@link renderToPNG}.
|
|
3453
|
+
* @throws If the `@napi-rs/canvas` binary cannot be loaded, if `width`, `height` or
|
|
3454
|
+
* `scale` is not positive, or if a font in `fonts` cannot be loaded.
|
|
3455
|
+
*/
|
|
3456
|
+
renderPNG(view?: PNGViewOptions): Promise<Uint8Array>;
|
|
3457
|
+
/**
|
|
3458
|
+
* Renders one view of the map onto a canvas, to draw on top of it or to encode it in
|
|
3459
|
+
* another format.
|
|
3460
|
+
*
|
|
3461
|
+
* The canvas is `width × scale` by `height × scale` pixels. Its 2D context is in its
|
|
3462
|
+
* default state, except that it is scaled by `scale`: draw in the same units as
|
|
3463
|
+
* `width` and `height`. Encode it with `canvas.encode('webp' | 'jpeg' | 'avif' | 'png')`
|
|
3464
|
+
* or `canvas.toBuffer(…)`.
|
|
3465
|
+
*
|
|
3466
|
+
* The canvas records what is drawn and only paints the pixels when they are needed,
|
|
3467
|
+
* usually when it is encoded, so drawing more on it costs little. Reading pixels
|
|
3468
|
+
* (`getImageData`) paints everything recorded so far, every time it is called.
|
|
3469
|
+
*
|
|
3470
|
+
* @example Save a map as WebP
|
|
3471
|
+
* ```ts
|
|
3472
|
+
* const canvas = await map.renderCanvas({ lon: 13.4, lat: 52.52, zoom: 12 });
|
|
3473
|
+
* await writeFile('berlin.webp', await canvas.encode('webp'));
|
|
3474
|
+
* ```
|
|
3475
|
+
*
|
|
3476
|
+
* To draw on the map, see the example on {@link SVGMapRenderer.project}.
|
|
3477
|
+
*
|
|
3478
|
+
* @param view - Size, centre, zoom and pixel density. All optional.
|
|
3479
|
+
* @returns A `Canvas` of `@napi-rs/canvas`.
|
|
3480
|
+
* @throws As {@link PNGMapRenderer.renderPNG}.
|
|
3481
|
+
*/
|
|
3482
|
+
renderCanvas(view?: PNGViewOptions): Promise<Canvas>;
|
|
3483
|
+
/** Forgets the fetched tiles and sprite, and the decoded images. */
|
|
3484
|
+
clearCache(): void;
|
|
3485
|
+
}
|
|
2762
3486
|
|
|
2763
|
-
export { renderToPNG, renderToSVG };
|
|
2764
|
-
export type { RenderToPNGOptions, RenderToSVGOptions };
|
|
3487
|
+
export { PNGMapRenderer, SVGMapRenderer, renderToCanvas, renderToPNG, renderToSVG };
|
|
3488
|
+
export type { FetchFunction, FetchResponse, GlobalState, PNGMapRendererOptions, PNGViewOptions, RenderToPNGOptions, RenderToSVGOptions, SVGMapRendererOptions, ViewOptions };
|