diff --git a/__snapshots__/chromium_layers-gpx-layer--gpx-layer-default.png b/__snapshots__/chromium_layers-gpx-layer--gpx-layer-default.png index e820170..6ee0697 100644 Binary files a/__snapshots__/chromium_layers-gpx-layer--gpx-layer-default.png and b/__snapshots__/chromium_layers-gpx-layer--gpx-layer-default.png differ diff --git a/__snapshots__/chromium_layers-gpx-layer--gpx-layer-line-style.png b/__snapshots__/chromium_layers-gpx-layer--gpx-layer-line-style.png index 470f41f..44fd23a 100644 Binary files a/__snapshots__/chromium_layers-gpx-layer--gpx-layer-line-style.png and b/__snapshots__/chromium_layers-gpx-layer--gpx-layer-line-style.png differ diff --git a/__snapshots__/chromium_layers-gpx-layer--gpx-wms.png b/__snapshots__/chromium_layers-gpx-layer--gpx-wms.png index ba292b0..a715686 100644 Binary files a/__snapshots__/chromium_layers-gpx-layer--gpx-wms.png and b/__snapshots__/chromium_layers-gpx-layer--gpx-wms.png differ diff --git a/__snapshots__/webkit_layers-gpx-layer--gpx-layer-default.png b/__snapshots__/webkit_layers-gpx-layer--gpx-layer-default.png index 1499a5d..811c139 100644 Binary files a/__snapshots__/webkit_layers-gpx-layer--gpx-layer-default.png and b/__snapshots__/webkit_layers-gpx-layer--gpx-layer-default.png differ diff --git a/__snapshots__/webkit_layers-gpx-layer--gpx-layer-line-style.png b/__snapshots__/webkit_layers-gpx-layer--gpx-layer-line-style.png index c0a467f..0bab6be 100644 Binary files a/__snapshots__/webkit_layers-gpx-layer--gpx-layer-line-style.png and b/__snapshots__/webkit_layers-gpx-layer--gpx-layer-line-style.png differ diff --git a/__snapshots__/webkit_layers-gpx-layer--gpx-wms.png b/__snapshots__/webkit_layers-gpx-layer--gpx-wms.png index 86de020..8164bf4 100644 Binary files a/__snapshots__/webkit_layers-gpx-layer--gpx-wms.png and b/__snapshots__/webkit_layers-gpx-layer--gpx-wms.png differ diff --git a/src/index.ts b/src/index.ts index 481f615..1f9f4a4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ export { ActivityMap, ActivityMapProps, } from "./components/activity-map"; -export { GpxLayer } from "./layers/gpx-layer"; +export { GpxLayer, GpxLayerProps } from "./layers/gpx-layer/gpx-layer"; export { GpxStreetMap } from "./components/gpx-street-map"; export { StreetLayer } from "./layers/street-layer"; export { FocusGpxStreetMap } from "./components/focus-gpx-street-map"; diff --git a/src/layers/gpx-layer.stories.tsx b/src/layers/gpx-layer.stories.tsx deleted file mode 100644 index f0ae42c..0000000 --- a/src/layers/gpx-layer.stories.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import { DeckGL } from "@deck.gl/react"; -import { StreetLayer } from "./street-layer"; -import { useMemo, useState } from "react"; -import * as React from "react"; -import { GpxLayer, GpxLayerProps } from "./gpx-layer"; -import { TerrainLayer } from "@deck.gl/geo-layers"; -import { LayersList, CompositeLayer } from "@deck.gl/core"; -import { Map } from "react-map-gl/maplibre"; -import type { StoryObj } from "@storybook/react"; -import { - JR_ACTIVITY_FILE, - JR_INITIAL_VIEW_STATE, - JR_PITCHED_VIEW_STATE, -} from "../constant.stories"; - -export default { - title: "Layers / GPX Layer", - tags: ["autodocs"], - parameters: { - docs: { - story: { - height: "600px", - }, - }, - }, -}; - -const defaultLayerProps = { - id: "gpx-layer", - data: JR_ACTIVITY_FILE, -}; - -export function GPXLayerDefault() { - const layer = new GpxLayer({ ...defaultLayerProps }); - - return ( - - ); -} - -export function GPXLayerLineStyle() { - const layer = new GpxLayer({ - ...defaultLayerProps, - lineWidthMinPixels: 5, - getLineColor: [0, 0, 200], - }) as CompositeLayer; - - return ( - - ); -} - -export function GpxWms() { - const gpxLayer = new GpxLayer({ - ...defaultLayerProps, - }) as CompositeLayer; - - const layers = [gpxLayer, new StreetLayer()]; - - return ( - - ); -} - -export const GpxSatteliteTerrain: StoryObj = { - render: () => { - const layerProps: GpxLayerProps = { - ...defaultLayerProps, - getLineColor: [255, 255, 0], - }; - - const gpxLayer = new GpxLayer({ ...layerProps }); - - const [key] = useState(import.meta.env.VITE_MAPTILER_API_KEY); - - const TERRAIN_IMAGE = `https://api.maptiler.com/tiles/terrain-rgb-v2/{z}/{x}/{y}.webp?key=${key}`; - const SURFACE_IMAGE = `https://api.maptiler.com/tiles/satellite-v2/{z}/{x}/{y}.jpg?key=${key}`; - - const ELEVATION_DECODER = { - rScaler: 6553.6, - gScaler: 25.6, - bScaler: 0.1, - offset: -10000, - }; - - const terrainLayer = useMemo( - () => - new TerrainLayer({ - id: "terrain", - minZoom: 0, - maxZoom: 12, - elevationDecoder: ELEVATION_DECODER, - elevationData: TERRAIN_IMAGE, - texture: SURFACE_IMAGE, - wireframe: false, - color: [255, 255, 255], - }), - [ELEVATION_DECODER, TERRAIN_IMAGE, SURFACE_IMAGE], - ); - - const layers = [gpxLayer, terrainLayer]; - - return ( - - ); - }, - tags: ["no-visual-test"], -}; - -export function GpxMapTerrain() { - const gpxLayer = new GpxLayer({ ...defaultLayerProps }) as CompositeLayer; - - const [API_KEY] = useState(import.meta.env.VITE_MAPTILER_API_KEY); - const layers = [gpxLayer]; - const mapStyle = `https://api.maptiler.com/maps/streets-v2/style.json?key=${API_KEY}`; - - return ( - - - - ); -} -GpxMapTerrain.tags = ["no-visual-test"]; diff --git a/src/layers/gpx-layer.ts b/src/layers/gpx-layer.ts deleted file mode 100644 index 41773ea..0000000 --- a/src/layers/gpx-layer.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { - GeoJsonLayer, - PathLayer, - type GeoJsonLayerProps, -} from "@deck.gl/layers"; -import { Color } from "@deck.gl/core"; -import { GPXLoader, TCXLoader } from "@loaders.gl/kml"; -import * as _ from "lodash"; - -export type GpxLayerProps = GeoJsonLayerProps; - -export class GpxLayer extends GeoJsonLayer { - constructor(props: GpxLayerProps) { - super({ ...props }); - } - - renderLayers() { - const defaultLayers = super.renderLayers(); - const lineLayers = defaultLayers[1]; - if (!_.isArray(lineLayers) || lineLayers.length < 2) { - return defaultLayers; - } - const pathLayer = lineLayers[1]; - if (!pathLayer || pathLayer.constructor.name !== "PathLayer") { - return defaultLayers; - } - const outlineLayer = (pathLayer as PathLayer).clone({ - id: "outline", - widthMinPixels: this.props.lineWidthMinPixels + 1, - getColor: [0, 0, 0], - }); - return [outlineLayer, ...defaultLayers]; - } -} - -const defaultProps = { - ...GeoJsonLayer.defaultProps, - lineWidthMinPixels: 3, - getLineColor: [255, 255, 0] as Color, - loaders: [GPXLoader, TCXLoader], -}; - -GpxLayer.defaultProps = defaultProps; -GpxLayer.layerName = "GpxLayer"; diff --git a/src/layers/gpx-layer/gpx-layer.stories.tsx b/src/layers/gpx-layer/gpx-layer.stories.tsx new file mode 100644 index 0000000..1391808 --- /dev/null +++ b/src/layers/gpx-layer/gpx-layer.stories.tsx @@ -0,0 +1,133 @@ +import { DeckGL } from "@deck.gl/react"; +import { StreetLayer } from "../street-layer"; +import { useState } from "react"; +import * as React from "react"; +import { GpxLayer, GpxLayerProps } from "./gpx-layer"; +import { CompositeLayer } from "@deck.gl/core"; +import { Map } from "react-map-gl/maplibre"; +import type { StoryObj } from "@storybook/react"; +import { + JR_ACTIVITY_FILE, + JR_INITIAL_VIEW_STATE, + JR_PITCHED_VIEW_STATE, +} from "../../constant.stories"; +import { HillLayer } from "../hill-layer"; +import { getRgba } from "../util.stories"; + +export default { + title: "Layers / GPX Layer", + tags: ["autodocs"], + parameters: { + docs: { + story: { + height: "600px", + }, + }, + }, +}; + +const defaultLayerProps = { + id: "gpx-layer", + data: JR_ACTIVITY_FILE, +}; + +export const GPXLayerDefault: StoryObj = { + render: () => { + const layer = new GpxLayer({ ...defaultLayerProps }); + + return ( + + ); + }, +}; + +export const GPXLayerLineStyle: StoryObj<{ color: string } & GpxLayerProps> = { + args: { + color: "blue", + lineWidthMinPixels: 5, + }, + render: ({ color, lineWidthMinPixels }) => { + const getLineColor = getRgba(color); + + const layer = new GpxLayer({ + ...defaultLayerProps, + lineWidthMinPixels, + getLineColor, + }); + + return ( + + ); + }, +}; + +export const GpxWms: StoryObj = { + render: () => { + const gpxLayer = new GpxLayer({ + ...defaultLayerProps, + }); + + const layers = [gpxLayer, new StreetLayer()]; + + return ( + + ); + }, +}; + +export const GpxSatteliteTerrain: StoryObj = { + render: () => { + const layerProps: GpxLayerProps = { + ...defaultLayerProps, + getLineColor: [255, 255, 0], + }; + + const gpxLayer = new GpxLayer({ ...layerProps }); + + const layers = [gpxLayer, new HillLayer()]; + + return ( + + ); + }, + tags: ["no-visual-test"], +}; + +export function GpxMapTerrain() { + const gpxLayer = new GpxLayer({ ...defaultLayerProps }) as CompositeLayer; + + const [API_KEY] = useState(import.meta.env.VITE_MAPTILER_API_KEY); + const layers = [gpxLayer]; + const mapStyle = `https://api.maptiler.com/maps/streets-v2/style.json?key=${API_KEY}`; + + return ( + + + + ); +} +GpxMapTerrain.tags = ["no-visual-test"]; diff --git a/src/layers/gpx-layer/gpx-layer.ts b/src/layers/gpx-layer/gpx-layer.ts new file mode 100644 index 0000000..2e7c3eb --- /dev/null +++ b/src/layers/gpx-layer/gpx-layer.ts @@ -0,0 +1,24 @@ +import { GeoJsonLayer, type GeoJsonLayerProps } from "@deck.gl/layers"; +import { Color } from "@deck.gl/core"; +import { GPXLoader, TCXLoader } from "@loaders.gl/kml"; +import { ExtrudedPathLayer } from "../extruded-path-layer/extruded-path-layer"; + +export type GpxLayerProps = GeoJsonLayerProps; + +export class GpxLayer extends GeoJsonLayer {} + +const defaultProps = { + ...GeoJsonLayer.defaultProps, + lineWidthMinPixels: 3, + getLineColor: [255, 255, 0] as Color, + loaders: [GPXLoader, TCXLoader], + _subLayerProps: { + linestrings: { + type: ExtrudedPathLayer, + getSideColor: [120, 120, 120, 255], + }, + }, +}; + +GpxLayer.defaultProps = defaultProps; +GpxLayer.layerName = "GpxLayer";