├── .npmignore ├── doc ├── static │ ├── .nojekyll │ └── img │ │ ├── favicon.png │ │ ├── hero │ │ ├── mjs.png │ │ ├── dropoff.png │ │ └── semantic.png │ │ ├── oss_logo.png │ │ ├── theory │ │ ├── graph-diagram.png │ │ ├── polygon-clipped.png │ │ ├── polygon-on-grid.png │ │ ├── polygon-rendered.jpg │ │ ├── graph-single-tile.png │ │ ├── polygon-undistorted.jpg │ │ ├── graph-multiple-tiles.png │ │ ├── polygon-behind-camera.png │ │ ├── polygon-on-real-image.png │ │ ├── polygon-triangulated.png │ │ ├── polygon-combined-sphere.png │ │ ├── graph-multiple-tiles-edges.png │ │ ├── graph-multiple-tiles-nodes.png │ │ ├── polygon-clipped-on-sphere.png │ │ ├── polygon-clipped-projected.png │ │ ├── polygon-in-front-of-image.png │ │ ├── polygon-on-undistorted-image.png │ │ └── polygon-equirectangular-panorama.jpg │ │ ├── extension │ │ ├── custom-render-design.png │ │ └── data-provider-design.png │ │ ├── examples │ │ ├── scale.svg │ │ ├── translate.svg │ │ ├── code.svg │ │ └── rotate.svg │ │ ├── logo_black.svg │ │ └── logo_green.svg ├── src │ ├── css │ │ ├── mapbox.css │ │ └── log.css │ ├── js │ │ ├── components │ │ │ ├── viewer.module.css │ │ │ ├── code.module.css │ │ │ ├── Code.js │ │ │ └── ViewerComponent.js │ │ ├── utils │ │ │ ├── error.js │ │ │ └── image.js │ │ └── options │ │ │ ├── FunctionController.js │ │ │ ├── Controller.js │ │ │ └── OptionController.js │ └── pages │ │ ├── examples │ │ ├── support.js │ │ ├── component-tag.js │ │ ├── extend-editor.js │ │ ├── viewer-events.js │ │ ├── viewer-filters.js │ │ ├── viewer-methods.js │ │ ├── viewer-options.js │ │ ├── viewer-to-map.js │ │ ├── component-popup.js │ │ ├── extend-map-sync.js │ │ ├── viewer-from-map.js │ │ ├── component-marker.js │ │ ├── component-pointer.js │ │ ├── component-spatial.js │ │ ├── extend-animation.js │ │ ├── component-keyboard.js │ │ ├── component-popup-tag.js │ │ ├── extend-fly-controls.js │ │ ├── viewer-coordinates.js │ │ ├── component-marker-map.js │ │ ├── component-tag-create.js │ │ ├── component-tag-interact.js │ │ ├── extend-three-renderer.js │ │ ├── extend-webgl-renderer.js │ │ ├── component-marker-million.js │ │ ├── extend-graphics-developer.js │ │ ├── viewer-initialization.js │ │ └── extend-procedural-data-provider.js │ │ └── styles.module.css ├── .eslintignore ├── .prettierignore ├── .prettierrc ├── sidebars │ ├── examples.sidebars.js │ └── api.sidebars.js ├── babel.config.js ├── mapillary-js.sh ├── .stylelintrc.js ├── .gitignore ├── typedoc.json ├── docs │ ├── theory │ │ └── theory.md │ └── main │ │ └── guide.md ├── plugins │ └── plugin-overwrite-slug │ │ └── index.js └── docusaurus.config.js ├── src ├── geometry │ ├── Constants.ts │ ├── interfaces │ │ ├── ICameraFactory.ts │ │ └── ICamera.ts │ └── Camera.ts ├── util │ ├── Func.ts │ ├── SubscriptionHolder.ts │ ├── DOM.ts │ └── interfaces │ │ └── IEventEmitter.ts ├── render │ ├── RenderPass.ts │ ├── interfaces │ │ ├── ViewportSize.ts │ │ ├── VirtualNodeHash.ts │ │ ├── IGLRenderHash.ts │ │ ├── GLRenderFunction.ts │ │ └── GLFrameRenderer.ts │ └── RenderMode.ts ├── shader │ ├── chunk │ │ ├── uniforms_vertex.glsl.ts │ │ ├── gl_frag_color_fragment.glsl.ts │ │ ├── varyings_fragment.glsl.ts │ │ ├── varyings_vertex.glsl.ts │ │ ├── bearing_fragment.glsl.ts │ │ ├── extrinsic_vertex.glsl.ts │ │ ├── uniforms_fragment.glsl.ts │ │ ├── gl_position_vertex.glsl.ts │ │ ├── common.glsl.ts │ │ ├── precision_fragment.glsl.ts │ │ ├── coordinates.glsl.ts │ │ └── map_color_fragment.glsl.ts │ ├── Shader.ts │ └── shaders │ │ └── texture.glsl.ts ├── component │ ├── cover │ │ └── CoverState.ts │ ├── tag │ │ ├── TagOperation.ts │ │ ├── tag │ │ │ ├── events │ │ │ │ ├── TagEventType.ts │ │ │ │ └── TagStateEvent.ts │ │ │ └── TagDomain.ts │ │ ├── interfaces │ │ │ ├── OutlineCreateTagOptions.ts │ │ │ ├── TagInteraction.ts │ │ │ ├── ExtremePointCreateTagOptions.ts │ │ │ └── SpotTagOptions.ts │ │ ├── error │ │ │ └── GeometryTagError.ts │ │ ├── handlers │ │ │ ├── CreatePointsHandler.ts │ │ │ ├── CreatePolygonHandler.ts │ │ │ └── CreatePointHandler.ts │ │ ├── TagMode.ts │ │ └── TagDOMRenderer.ts │ ├── interfaces │ │ ├── Shader.ts │ │ ├── ComponentConfiguration.ts │ │ ├── CoverConfiguration.ts │ │ ├── ZoomConfiguration.ts │ │ ├── BearingConfiguration.ts │ │ ├── IComponent.ts │ │ ├── MarkerConfiguration.ts │ │ ├── NavigationFallbackConfiguration.ts │ │ ├── TagConfiguration.ts │ │ ├── PointerConfiguration.ts │ │ └── KeyboardConfiguration.ts │ ├── sequence │ │ └── SequenceMode.ts │ ├── fallback │ │ └── FallbackComponentName.ts │ ├── popup │ │ ├── popup │ │ │ └── PopupAlignment.ts │ │ └── interfaces │ │ │ └── PopupOffset.ts │ ├── pointer │ │ └── HandlerTypes.ts │ ├── image │ │ └── interfaces │ │ │ └── ProjectorShaderMaterial.ts │ ├── slider │ │ ├── interfaces │ │ │ └── SliderBBoxProjectorShaderMaterial.ts │ │ ├── shaders │ │ │ ├── fisheye_curtain.vertex.glsl.ts │ │ │ ├── fisheye.vertex.glsl.ts │ │ │ ├── spherical_curtain.vertex.glsl.ts │ │ │ ├── perspective_curtain.vertex.glsl.ts │ │ │ ├── spherical.vertex.glsl.ts │ │ │ ├── perspective.vertex.glsl.ts │ │ │ ├── perspective_distorted.vertex.glsl.ts │ │ │ ├── perspective_distorted_curtain.vertex.glsl.ts │ │ │ ├── spherical.fragment.glsl.ts │ │ │ ├── perspective_distorted.fragment.glsl.ts │ │ │ ├── perspective_distorted_curtain.fragment.glsl.ts │ │ │ ├── spherical_curtain.fragment.glsl.ts │ │ │ ├── perspective.fragment.glsl.ts │ │ │ ├── perspective_curtain.fragment.glsl.ts │ │ │ └── fisheye.fragment.glsl.ts │ │ └── SliderInterfaces.ts │ ├── events │ │ ├── ComponentEventType.ts │ │ ├── ComponentPlayEvent.ts │ │ ├── ComponentGeometryEvent.ts │ │ ├── ComponentTagModeEvent.ts │ │ ├── ComponentEvent.ts │ │ ├── ComponentHoverEvent.ts │ │ ├── ComponentMarkerEvent.ts │ │ └── ComponentStateEvent.ts │ ├── ComponentName.ts │ ├── spatial │ │ ├── enums │ │ │ ├── PointVisualizationMode.ts │ │ │ ├── OriginalPositionMode.ts │ │ │ └── CameraVisualizationMode.ts │ │ ├── Modes.ts │ │ ├── SpatialCommon.ts │ │ └── scene │ │ │ ├── SpatialOctreeMath.ts │ │ │ └── SpatialAssets.ts │ ├── marker │ │ └── interfaces │ │ │ └── CircleMarkerOptions.ts │ └── util │ │ └── ComponentSize.ts ├── viewer │ ├── interfaces │ │ ├── MouseClaim.ts │ │ ├── MousePixelDeferral.ts │ │ ├── Unprojection.ts │ │ ├── ISpriteAtlas.ts │ │ └── PointOfView.ts │ ├── enums │ │ ├── RenderPass.ts │ │ ├── Alignment.ts │ │ └── CameraControls.ts │ ├── events │ │ ├── ViewerReferenceEvent.ts │ │ ├── ViewerEvent.ts │ │ ├── ViewerImageEvent.ts │ │ ├── ViewerNavigationEdgeEvent.ts │ │ ├── ViewerResetEvent.ts │ │ ├── ViewerBearingEvent.ts │ │ ├── ViewerEventType.ts │ │ ├── ViewerDataLoadingEvent.ts │ │ ├── ViewerNavigableEvent.ts │ │ ├── ViewerStateEvent.ts │ │ ├── ViewerDragEndEvent.ts │ │ └── ViewerLoadEvent.ts │ ├── options │ │ ├── UrlOptions.ts │ │ └── FallbackOptions.ts │ ├── Modes.ts │ ├── KeyboardService.ts │ └── ConfigurationService.ts ├── geo │ ├── interfaces │ │ └── CameraType.ts │ └── GeoRBush.ts ├── state │ ├── interfaces │ │ ├── EulerRotation.ts │ │ ├── AnimationFrame.ts │ │ ├── IStateBase.ts │ │ └── IAnimationState.ts │ ├── State.ts │ ├── TransitionMode.ts │ └── state │ │ └── CustomState.ts ├── api │ ├── events │ │ ├── ProviderEventType.ts │ │ ├── ProviderCellEvent.ts │ │ ├── ProviderClusterEvent.ts │ │ └── ProviderEvent.ts │ ├── provider │ │ ├── GraphDataProviderOptions.ts │ │ ├── GraphEnts.ts │ │ └── GraphContracts.ts │ ├── contracts │ │ ├── SequenceContract.ts │ │ ├── ImagesContract.ts │ │ ├── ImageTilesContract.ts │ │ ├── EntContract.ts │ │ ├── SpatialImagesContract.ts │ │ ├── ImageTilesRequestContract.ts │ │ ├── CoreImagesContract.ts │ │ └── MeshContract.ts │ ├── ents │ │ ├── IDEnt.ts │ │ ├── ImageEnt.ts │ │ ├── URLEnt.ts │ │ ├── CreatorEnt.ts │ │ ├── SequenceEnt.ts │ │ ├── ImageTileEnt.ts │ │ ├── CoreImageEnt.ts │ │ └── CameraEnt.ts │ ├── interfaces │ │ ├── LngLat.ts │ │ └── LngLatAlt.ts │ └── CellMath.ts ├── graph │ ├── edge │ │ └── interfaces │ │ │ ├── StepDirection.ts │ │ │ ├── TurnDirection.ts │ │ │ ├── SphericalDirection.ts │ │ │ ├── NavigationEdge.ts │ │ │ └── NavigationEdgeData.ts │ ├── interfaces │ │ ├── NavigationEdgeStatus.ts │ │ └── GraphConfiguration.ts │ └── GraphMode.ts ├── error │ ├── GraphMapillaryError.ts │ ├── MapillaryError.ts │ ├── ArgumentMapillaryError.ts │ └── CancelMapillaryError.ts └── tile │ └── interfaces │ ├── TileBoundingBox.ts │ ├── TileTypes.ts │ └── TileRegionOfInterest.ts ├── config ├── rollup.serve.config.js ├── tsconfig.test.json ├── postcss.config.cjs ├── rollup.js └── init.js ├── .gitignore ├── styles ├── svg │ ├── pointer-wheat.svg │ ├── pointer-white.svg │ ├── stepper-stop.svg │ ├── stepper-play.svg │ ├── stepper-left.svg │ ├── stepper-right.svg │ ├── turn.svg │ └── turn-around.svg └── mapillary.css ├── .editorconfig ├── test ├── helper │ ├── TestMath.ts │ ├── MockCreatorBase.ts │ ├── ProviderHelper.ts │ ├── GeoHelper.ts │ ├── RequestHelper.ts │ ├── LoadingServiceMockCreator.ts │ ├── SpriteServiceMockCreator.ts │ ├── ImageMockCreator.ts │ ├── KeyboardServiceMockCreator.ts │ ├── DOMRendererMockCreator.ts │ ├── TestImage.ts │ ├── PanServiceMockCreator.ts │ ├── PlayServiceMockCreator.ts │ ├── TestComponent.ts │ ├── GLRendererMockCreator.ts │ ├── ConfigurationServiceMockCreator.ts │ ├── WebGLRenderer.ts │ ├── MockCreator.ts │ ├── TransformHelper.ts │ ├── RenderServiceMockCreator.ts │ └── GraphServiceMockCreator.ts ├── tile │ └── TileTypes.test.ts ├── state │ └── StateService.test.ts ├── viewer │ ├── LoadingService.test.ts │ └── Modes.test.ts ├── graph │ └── Sequence.test.ts └── component │ └── spatial │ └── SpatialComponent.test.ts ├── tsconfig.json ├── jest.config.js ├── Dockerfile ├── types └── s2-geometry │ └── index.d.ts ├── .github ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE.md ├── LICENSE ├── rollup.config.js └── examples └── doc ├── extend-procedural-data-provider.html ├── support.html ├── viewer-options.html ├── extend-animation.html ├── extend-fly-controls.html ├── extend-webgl-renderer.html ├── viewer-initialization.html ├── extend-three-renderer.html ├── extend-graphics-developer.html └── viewer-events.html /.npmignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/static/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/geometry/Constants.ts: -------------------------------------------------------------------------------- 1 | export const EPSILON = 1e-8; 2 | -------------------------------------------------------------------------------- /doc/src/css/mapbox.css: -------------------------------------------------------------------------------- 1 | @import '~mapbox-gl/dist/mapbox-gl.css'; 2 | -------------------------------------------------------------------------------- /src/util/Func.ts: -------------------------------------------------------------------------------- 1 | export type Func = (item: T) => TResult; 2 | -------------------------------------------------------------------------------- /config/rollup.serve.config.js: -------------------------------------------------------------------------------- 1 | import { esm } from './rollup.js'; 2 | 3 | export default esm; 4 | -------------------------------------------------------------------------------- /src/render/RenderPass.ts: -------------------------------------------------------------------------------- 1 | export enum RenderPass { 2 | Background, 3 | Opaque, 4 | } 5 | -------------------------------------------------------------------------------- /doc/static/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/favicon.png -------------------------------------------------------------------------------- /doc/static/img/hero/mjs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/hero/mjs.png -------------------------------------------------------------------------------- /doc/static/img/oss_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/oss_logo.png -------------------------------------------------------------------------------- /src/shader/chunk/uniforms_vertex.glsl.ts: -------------------------------------------------------------------------------- 1 | export default /* glsl */` 2 | uniform mat4 extrinsicMatrix; 3 | `; 4 | -------------------------------------------------------------------------------- /src/component/cover/CoverState.ts: -------------------------------------------------------------------------------- 1 | export enum CoverState { 2 | Hidden, 3 | Loading, 4 | Visible, 5 | } 6 | -------------------------------------------------------------------------------- /src/component/tag/TagOperation.ts: -------------------------------------------------------------------------------- 1 | export enum TagOperation { 2 | None, 3 | Centroid, 4 | Vertex, 5 | } 6 | -------------------------------------------------------------------------------- /src/shader/chunk/gl_frag_color_fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export default /* glsl */` 2 | gl_FragColor = mapColor; 3 | `; 4 | -------------------------------------------------------------------------------- /src/shader/chunk/varyings_fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export default /* glsl */` 2 | varying vec4 positionExtrinsic; 3 | `; 4 | -------------------------------------------------------------------------------- /src/shader/chunk/varyings_vertex.glsl.ts: -------------------------------------------------------------------------------- 1 | export default /* glsl */` 2 | varying vec4 positionExtrinsic; 3 | `; 4 | -------------------------------------------------------------------------------- /doc/static/img/hero/dropoff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/hero/dropoff.png -------------------------------------------------------------------------------- /doc/static/img/hero/semantic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/hero/semantic.png -------------------------------------------------------------------------------- /src/component/interfaces/Shader.ts: -------------------------------------------------------------------------------- 1 | export interface Shader { 2 | fragment: string; 3 | vertex: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/viewer/interfaces/MouseClaim.ts: -------------------------------------------------------------------------------- 1 | export interface MouseClaim { 2 | name: string; 3 | zindex: number; 4 | } 5 | -------------------------------------------------------------------------------- /src/component/sequence/SequenceMode.ts: -------------------------------------------------------------------------------- 1 | export enum SequenceMode { 2 | Default, 3 | Playback, 4 | Timeline, 5 | } 6 | -------------------------------------------------------------------------------- /src/geo/interfaces/CameraType.ts: -------------------------------------------------------------------------------- 1 | export type CameraType = 2 | "spherical" | 3 | "fisheye" | 4 | "perspective"; 5 | -------------------------------------------------------------------------------- /src/render/interfaces/ViewportSize.ts: -------------------------------------------------------------------------------- 1 | export interface ViewportSize { 2 | height: number; 3 | width: number; 4 | } 5 | -------------------------------------------------------------------------------- /src/state/interfaces/EulerRotation.ts: -------------------------------------------------------------------------------- 1 | export interface EulerRotation { 2 | phi: number; 3 | theta: number; 4 | } 5 | -------------------------------------------------------------------------------- /src/component/interfaces/ComponentConfiguration.ts: -------------------------------------------------------------------------------- 1 | export interface ComponentConfiguration { 2 | [key: string]: any; 3 | } 4 | -------------------------------------------------------------------------------- /doc/static/img/theory/graph-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/graph-diagram.png -------------------------------------------------------------------------------- /src/shader/chunk/bearing_fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export default /* glsl */` 2 | vec3 bearing = normalize(positionExtrinsic.xyz); 3 | `; 4 | -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-clipped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-clipped.png -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-on-grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-on-grid.png -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-rendered.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-rendered.jpg -------------------------------------------------------------------------------- /src/viewer/interfaces/MousePixelDeferral.ts: -------------------------------------------------------------------------------- 1 | export interface MousePixelDeferral { 2 | name: string; 3 | deferPixels: number; 4 | } 5 | -------------------------------------------------------------------------------- /doc/static/img/theory/graph-single-tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/graph-single-tile.png -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-undistorted.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-undistorted.jpg -------------------------------------------------------------------------------- /src/api/events/ProviderEventType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @event 3 | */ 4 | export type ProviderEventType = 5 | | "datacreate" 6 | | "datadelete"; 7 | -------------------------------------------------------------------------------- /src/component/fallback/FallbackComponentName.ts: -------------------------------------------------------------------------------- 1 | export type FallbackComponentName = 2 | | "imagefallback" 3 | | "navigationfallback" 4 | -------------------------------------------------------------------------------- /src/shader/chunk/extrinsic_vertex.glsl.ts: -------------------------------------------------------------------------------- 1 | export default /* glsl */` 2 | positionExtrinsic = extrinsicMatrix * vec4(position, 1.0); 3 | `; 4 | -------------------------------------------------------------------------------- /doc/static/img/theory/graph-multiple-tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/graph-multiple-tiles.png -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-behind-camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-behind-camera.png -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-on-real-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-on-real-image.png -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-triangulated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-triangulated.png -------------------------------------------------------------------------------- /doc/static/img/extension/custom-render-design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/extension/custom-render-design.png -------------------------------------------------------------------------------- /doc/static/img/extension/data-provider-design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/extension/data-provider-design.png -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-combined-sphere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-combined-sphere.png -------------------------------------------------------------------------------- /src/api/provider/GraphDataProviderOptions.ts: -------------------------------------------------------------------------------- 1 | export interface GraphDataProviderOptions { 2 | endpoint?: string; 3 | accessToken?: string; 4 | } 5 | -------------------------------------------------------------------------------- /src/shader/chunk/uniforms_fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export default /* glsl */` 2 | uniform sampler2D map; 3 | uniform float opacity; 4 | uniform vec2 scale; 5 | `; 6 | -------------------------------------------------------------------------------- /doc/.eslintignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules 3 | 4 | # Generated files 5 | .access-token 6 | .docusaurus 7 | api 8 | build 9 | src/mapillary-js 10 | -------------------------------------------------------------------------------- /doc/static/img/theory/graph-multiple-tiles-edges.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/graph-multiple-tiles-edges.png -------------------------------------------------------------------------------- /doc/static/img/theory/graph-multiple-tiles-nodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/graph-multiple-tiles-nodes.png -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-clipped-on-sphere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-clipped-on-sphere.png -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-clipped-projected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-clipped-projected.png -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-in-front-of-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-in-front-of-image.png -------------------------------------------------------------------------------- /src/component/tag/tag/events/TagEventType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @event 3 | */ 4 | export type TagEventType = 5 | | "click" 6 | | "geometry" 7 | | "tag"; 8 | -------------------------------------------------------------------------------- /src/shader/chunk/gl_position_vertex.glsl.ts: -------------------------------------------------------------------------------- 1 | export default /* glsl */` 2 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 3 | `; 4 | -------------------------------------------------------------------------------- /doc/.prettierignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules 3 | 4 | # Generated files 5 | .access-token 6 | .docusaurus 7 | api 8 | build 9 | src/mapillary-js 10 | -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-on-undistorted-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-on-undistorted-image.png -------------------------------------------------------------------------------- /src/state/State.ts: -------------------------------------------------------------------------------- 1 | export enum State { 2 | Custom, 3 | Earth, 4 | GravityTraversing, 5 | Traversing, 6 | Waiting, 7 | WaitingInteractively, 8 | } 9 | -------------------------------------------------------------------------------- /doc/static/img/theory/polygon-equirectangular-panorama.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mapillary/mapillary-js/HEAD/doc/static/img/theory/polygon-equirectangular-panorama.jpg -------------------------------------------------------------------------------- /src/render/interfaces/VirtualNodeHash.ts: -------------------------------------------------------------------------------- 1 | import * as vd from "virtual-dom"; 2 | 3 | export interface VirtualNodeHash { 4 | name: string; 5 | vNode: vd.VNode; 6 | } 7 | -------------------------------------------------------------------------------- /src/shader/chunk/common.glsl.ts: -------------------------------------------------------------------------------- 1 | export default /* glsl */` 2 | #define PI 3.141592653589793 3 | #define PI2 6.283185307179586 4 | #define POSITIVE_INFINITY 3.402823466e+38 5 | `; 6 | -------------------------------------------------------------------------------- /src/component/popup/popup/PopupAlignment.ts: -------------------------------------------------------------------------------- 1 | export type PopupAlignment = "center" | "top" | "bottom" | "left" | "right" | "top-left" | "top-right" | "bottom-left" | "bottom-right"; 2 | -------------------------------------------------------------------------------- /src/geometry/interfaces/ICameraFactory.ts: -------------------------------------------------------------------------------- 1 | import { ICamera } from "./ICamera"; 2 | 3 | export interface ICameraFactory { 4 | makeCamera(type: string, parameters: number[]): ICamera; 5 | } 6 | -------------------------------------------------------------------------------- /src/shader/chunk/precision_fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export default /* glsl */` 2 | #ifdef GL_FRAGMENT_PRECISION_HIGH 3 | precision highp float; 4 | #else 5 | precision mediump float; 6 | #endif 7 | `; 8 | -------------------------------------------------------------------------------- /src/render/interfaces/IGLRenderHash.ts: -------------------------------------------------------------------------------- 1 | import { GLFrameRenderer } from "./GLFrameRenderer"; 2 | 3 | export interface GLRenderHash { 4 | name: string; 5 | renderer: GLFrameRenderer; 6 | } 7 | -------------------------------------------------------------------------------- /src/api/contracts/SequenceContract.ts: -------------------------------------------------------------------------------- 1 | import { SequenceEnt } from "../ents/SequenceEnt"; 2 | 3 | /** 4 | * Contract describing sequence results. 5 | */ 6 | export type SequenceContract = SequenceEnt; 7 | -------------------------------------------------------------------------------- /src/state/interfaces/AnimationFrame.ts: -------------------------------------------------------------------------------- 1 | import { IAnimationState } from "./IAnimationState"; 2 | 3 | export interface AnimationFrame { 4 | id: number; 5 | fps: number; 6 | state: IAnimationState; 7 | } 8 | -------------------------------------------------------------------------------- /src/viewer/interfaces/Unprojection.ts: -------------------------------------------------------------------------------- 1 | import { LngLat } from "../../api/interfaces/LngLat"; 2 | 3 | export interface Unprojection { 4 | basicPoint: number[]; 5 | lngLat: LngLat; 6 | pixelPoint: number[]; 7 | } 8 | -------------------------------------------------------------------------------- /src/api/ents/IDEnt.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Ent representing an entity with a unique ID. 3 | * 4 | * @interface IDEnt 5 | */ 6 | export interface IDEnt { 7 | /** 8 | * Unique ID. 9 | */ 10 | id: string; 11 | } 12 | -------------------------------------------------------------------------------- /src/shader/chunk/coordinates.glsl.ts: -------------------------------------------------------------------------------- 1 | export default /* glsl */` 2 | vec2 sfmToUv(const in vec2 sfm, const in vec2 scale) { 3 | float u = scale.x * sfm.x + 0.5; 4 | float v = - scale.y * sfm.y + 0.5; 5 | return vec2(u, v); 6 | } 7 | `; 8 | -------------------------------------------------------------------------------- /src/api/contracts/ImagesContract.ts: -------------------------------------------------------------------------------- 1 | import { ImageEnt } from "../ents/ImageEnt"; 2 | import { EntContract } from "./EntContract"; 3 | 4 | /** 5 | * Contract describing image results. 6 | */ 7 | export type ImagesContract = EntContract[]; 8 | -------------------------------------------------------------------------------- /src/graph/edge/interfaces/StepDirection.ts: -------------------------------------------------------------------------------- 1 | import { NavigationDirection } from "../NavigationDirection"; 2 | 3 | export interface StepDirection { 4 | direction: NavigationDirection; 5 | motionChange: number; 6 | useFallback: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /src/graph/edge/interfaces/TurnDirection.ts: -------------------------------------------------------------------------------- 1 | import { NavigationDirection } from "../NavigationDirection"; 2 | 3 | export interface TurnDirection { 4 | direction: NavigationDirection; 5 | directionChange: number; 6 | motionChange?: number; 7 | } 8 | -------------------------------------------------------------------------------- /src/api/ents/ImageEnt.ts: -------------------------------------------------------------------------------- 1 | import { SpatialImageEnt } from "./SpatialImageEnt"; 2 | import { CoreImageEnt } from "./CoreImageEnt"; 3 | 4 | /** 5 | * Ent representing image properties. 6 | */ 7 | export interface ImageEnt extends CoreImageEnt, SpatialImageEnt { } 8 | -------------------------------------------------------------------------------- /src/api/ents/URLEnt.ts: -------------------------------------------------------------------------------- 1 | import { IDEnt } from "./IDEnt"; 2 | 3 | /** 4 | * Ent representing URL properties. 5 | */ 6 | export interface URLEnt extends IDEnt { 7 | /** 8 | * URL for fetching ent data. 9 | */ 10 | url: string; 11 | } 12 | -------------------------------------------------------------------------------- /src/render/interfaces/GLRenderFunction.ts: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | 3 | export interface GLRenderFunction extends Function { 4 | ( 5 | perspectiveCamera: THREE.PerspectiveCamera, 6 | renderer: THREE.WebGLRenderer, 7 | ): void; 8 | } 9 | -------------------------------------------------------------------------------- /src/api/contracts/ImageTilesContract.ts: -------------------------------------------------------------------------------- 1 | import { ImageTileEnt } from "../ents/ImageTileEnt"; 2 | import { EntContract } from "./EntContract"; 3 | 4 | /** 5 | * Contract describing image tile results. 6 | */ 7 | export type ImageTilesContract = EntContract; 8 | -------------------------------------------------------------------------------- /src/component/pointer/HandlerTypes.ts: -------------------------------------------------------------------------------- 1 | /** @ignore */ 2 | export type MouseTouchPair = [MouseEvent, MouseEvent] | [Touch, Touch]; 3 | 4 | /** @ignore */ 5 | export type ClientTouch = { 6 | clientX: number; 7 | clientY: number; 8 | shiftKey: boolean; 9 | }; 10 | -------------------------------------------------------------------------------- /doc/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSpacing": false, 4 | "jsxBracketSameLine": true, 5 | "printWidth": 80, 6 | "proseWrap": "never", 7 | "singleQuote": true, 8 | "tabWidth": 2, 9 | "trailingComma": "all", 10 | "useTabs": false 11 | } 12 | -------------------------------------------------------------------------------- /src/api/contracts/EntContract.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Contract describing ent results. 3 | */ 4 | export interface EntContract { 5 | /** 6 | * Ent node. 7 | */ 8 | node: T; 9 | 10 | /** 11 | * Ent node id. 12 | */ 13 | node_id: string; 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE 2 | .idea 3 | .vagrant 4 | .vscode 5 | vagrant.* 6 | Vagrantfile 7 | 8 | # Dependencies 9 | /node_modules 10 | 11 | # Misc 12 | *.DS_STORE 13 | *.tgz 14 | *.watchman* 15 | 16 | yarn-error.log* 17 | yarn-debug.log* 18 | 19 | # Artifacts 20 | /build 21 | /dist 22 | -------------------------------------------------------------------------------- /src/api/ents/CreatorEnt.ts: -------------------------------------------------------------------------------- 1 | import { IDEnt } from "./IDEnt"; 2 | 3 | /** 4 | * Ent representing image creator properties. 5 | */ 6 | export interface CreatorEnt extends IDEnt { 7 | /** 8 | * The username of the creator. 9 | */ 10 | username: string; 11 | } 12 | -------------------------------------------------------------------------------- /src/api/contracts/SpatialImagesContract.ts: -------------------------------------------------------------------------------- 1 | import { SpatialImageEnt } from "../ents/SpatialImageEnt"; 2 | import { EntContract } from "./EntContract"; 3 | 4 | /** 5 | * Contract describing spatial image results. 6 | */ 7 | export type SpatialImagesContract = EntContract[]; 8 | -------------------------------------------------------------------------------- /src/viewer/enums/RenderPass.ts: -------------------------------------------------------------------------------- 1 | export enum RenderPass { 2 | /** 3 | * Occurs after the background render pass. 4 | */ 5 | Opaque, 6 | 7 | /** 8 | * Occurs last in the render sequence, after the opaque render pass. 9 | */ 10 | Transparent, 11 | } 12 | -------------------------------------------------------------------------------- /config/tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "declaration": false, 5 | "downlevelIteration": true, 6 | "module": "commonjs", 7 | "outDir": "../build/cjs/", 8 | "sourceMap": false, 9 | "target": "ES5" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /styles/svg/pointer-wheat.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /styles/svg/pointer-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/graph/edge/interfaces/SphericalDirection.ts: -------------------------------------------------------------------------------- 1 | import { NavigationDirection } from "../NavigationDirection"; 2 | 3 | export interface SphericalDirection { 4 | direction: NavigationDirection; 5 | prev: NavigationDirection; 6 | next: NavigationDirection; 7 | directionChange: number; 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | indent_style = space 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.{ts,html,css}] 13 | indent_size = 4 14 | 15 | [*.{js,json,yml}] 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /src/render/interfaces/GLFrameRenderer.ts: -------------------------------------------------------------------------------- 1 | import { GLRenderFunction } from "./GLRenderFunction"; 2 | import { RenderPass } from "../RenderPass"; 3 | 4 | export interface GLFrameRenderer { 5 | frameId: number; 6 | needsRender: boolean; 7 | render: GLRenderFunction; 8 | pass: RenderPass; 9 | } 10 | -------------------------------------------------------------------------------- /src/component/interfaces/CoverConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { CoverState } from "../cover/CoverState"; 2 | import { ComponentConfiguration } from "./ComponentConfiguration"; 3 | 4 | export interface CoverConfiguration extends ComponentConfiguration { 5 | id?: string; 6 | src?: string; 7 | state?: CoverState; 8 | } 9 | -------------------------------------------------------------------------------- /src/api/contracts/ImageTilesRequestContract.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Contract describing image tile requests. 3 | */ 4 | export interface ImageTilesRequestContract { 5 | /** 6 | * ID of the tile's image. 7 | */ 8 | imageId: string; 9 | 10 | /** 11 | * Tile level. 12 | */ 13 | z: number; 14 | } 15 | -------------------------------------------------------------------------------- /src/component/image/interfaces/ProjectorShaderMaterial.ts: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | 3 | export interface ProjectorShaderMaterial extends THREE.ShaderMaterial { 4 | uniforms: { 5 | [uniform: string]: THREE.IUniform; 6 | opacity: THREE.IUniform; 7 | map: THREE.IUniform; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /doc/sidebars/examples.sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | module.exports = { 11 | examples: ['examples'], 12 | }; 13 | -------------------------------------------------------------------------------- /src/component/slider/interfaces/SliderBBoxProjectorShaderMaterial.ts: -------------------------------------------------------------------------------- 1 | export interface SliderBBoxProjectorShaderMaterial extends THREE.ShaderMaterial { 2 | uniforms: { 3 | [uniform: string]: THREE.IUniform; 4 | opacity: THREE.IUniform; 5 | projectorTex: THREE.IUniform; 6 | bbox: THREE.IUniform; 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /src/component/events/ComponentEventType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @event 3 | */ 4 | export type ComponentEventType = 5 | | "geometrycreate" 6 | | "hover" 7 | | "markerdragend" 8 | | "markerdragstart" 9 | | "markerposition" 10 | | "playing" 11 | | "tagcreateend" 12 | | "tagcreatestart" 13 | | "tagmode" 14 | | "tags"; 15 | -------------------------------------------------------------------------------- /styles/svg/stepper-stop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | stop 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/viewer/interfaces/ISpriteAtlas.ts: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import * as vd from "virtual-dom"; 3 | 4 | import { Alignment } from "../enums/Alignment"; 5 | 6 | export interface ISpriteAtlas { 7 | loaded: boolean; 8 | getGLSprite(name: string): THREE.Object3D; 9 | getDOMSprite(name: string, float?: Alignment): vd.VNode; 10 | } 11 | -------------------------------------------------------------------------------- /doc/babel.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | module.exports = { 11 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 12 | }; 13 | -------------------------------------------------------------------------------- /src/component/ComponentName.ts: -------------------------------------------------------------------------------- 1 | export type ComponentName = 2 | | "attribution" 3 | | "bearing" 4 | | "cache" 5 | | "cover" 6 | | "direction" 7 | | "image" 8 | | "keyboard" 9 | | "marker" 10 | | "pointer" 11 | | "popup" 12 | | "sequence" 13 | | "slider" 14 | | "spatial" 15 | | "tag" 16 | | "zoom"; 17 | -------------------------------------------------------------------------------- /config/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('autoprefixer'), 4 | require('postcss-inline-svg')({ 5 | paths: ['./styles'], 6 | encode: svg => Buffer.from(svg).toString('base64'), 7 | transform: encoded => `"data:image/svg+xml;base64,${encoded}"` 8 | }), 9 | ], 10 | }; 11 | -------------------------------------------------------------------------------- /src/error/GraphMapillaryError.ts: -------------------------------------------------------------------------------- 1 | import { MapillaryError } from "./MapillaryError"; 2 | 3 | export class GraphMapillaryError extends MapillaryError { 4 | constructor(message: string) { 5 | super(message); 6 | 7 | Object.setPrototypeOf(this, GraphMapillaryError.prototype); 8 | 9 | this.name = "GraphMapillaryError"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/component/slider/shaders/fisheye_curtain.vertex.glsl.ts: -------------------------------------------------------------------------------- 1 | export const fisheyeCurtainVert = ` 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | uniform mat4 projectorMat; 6 | varying vec4 vRstq; 7 | void main() 8 | { 9 | vRstq = projectorMat * vec4(position, 1.0); 10 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 11 | } 12 | ` 13 | -------------------------------------------------------------------------------- /src/error/MapillaryError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @class MapillaryError 3 | * 4 | * @classdesc Generic Mapillary error. 5 | */ 6 | export class MapillaryError extends Error { 7 | constructor(message?: string) { 8 | super(message); 9 | 10 | Object.setPrototypeOf(this, MapillaryError.prototype); 11 | 12 | this.name = "MapillaryError"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /styles/svg/stepper-play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | play 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/api/ents/SequenceEnt.ts: -------------------------------------------------------------------------------- 1 | import { IDEnt } from "./IDEnt"; 2 | 3 | /** 4 | * Ent representing sequence properties. 5 | * 6 | * @interface SequenceEnt 7 | */ 8 | export interface SequenceEnt extends IDEnt { 9 | /** 10 | * The image IDs of the sequence sorted in 11 | * acsending order based on capture time. 12 | */ 13 | image_ids: string[]; 14 | } 15 | -------------------------------------------------------------------------------- /src/component/events/ComponentPlayEvent.ts: -------------------------------------------------------------------------------- 1 | import { ComponentEvent } from "./ComponentEvent"; 2 | 3 | /** 4 | * Interface for component play events. 5 | */ 6 | export interface ComponentPlayEvent extends ComponentEvent { 7 | /** 8 | * Value indiciating if the component is playing or not. 9 | */ 10 | playing: boolean; 11 | 12 | type: "playing"; 13 | } 14 | -------------------------------------------------------------------------------- /src/component/slider/shaders/fisheye.vertex.glsl.ts: -------------------------------------------------------------------------------- 1 | export const fisheyeVert = ` 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | 6 | uniform mat4 projectorMat; 7 | 8 | varying vec4 vRstq; 9 | 10 | void main() 11 | { 12 | vRstq = projectorMat * vec4(position, 1.0); 13 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 14 | } 15 | ` 16 | -------------------------------------------------------------------------------- /src/component/slider/shaders/spherical_curtain.vertex.glsl.ts: -------------------------------------------------------------------------------- 1 | export const sphericalCurtainVert = ` 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | uniform mat4 projectorMat; 6 | varying vec4 vRstq; 7 | void main() 8 | { 9 | vRstq = projectorMat * vec4(position, 1.0); 10 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 11 | } 12 | ` 13 | -------------------------------------------------------------------------------- /src/component/tag/interfaces/OutlineCreateTagOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface for the options that define the behavior and 3 | * appearance of the outline create tag. 4 | * 5 | * @interface 6 | */ 7 | export interface OutlineCreateTagOptions { 8 | /** 9 | * Text color as hexadecimal number. 10 | * @default 0xFFFFFF 11 | */ 12 | color?: number; 13 | } 14 | -------------------------------------------------------------------------------- /src/component/slider/shaders/perspective_curtain.vertex.glsl.ts: -------------------------------------------------------------------------------- 1 | export const perspectiveCurtainVert = ` 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | uniform mat4 projectorMat; 6 | varying vec4 vRstq; 7 | void main() 8 | { 9 | vRstq = projectorMat * vec4(position, 1.0); 10 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 11 | } 12 | ` 13 | -------------------------------------------------------------------------------- /src/component/slider/shaders/spherical.vertex.glsl.ts: -------------------------------------------------------------------------------- 1 | export const sphericalVert = ` 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | 6 | uniform mat4 projectorMat; 7 | 8 | varying vec4 vRstq; 9 | 10 | void main() 11 | { 12 | vRstq = projectorMat * vec4(position, 1.0); 13 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 14 | } 15 | ` 16 | -------------------------------------------------------------------------------- /src/component/slider/shaders/perspective.vertex.glsl.ts: -------------------------------------------------------------------------------- 1 | export const perspectiveVert = ` 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | 6 | uniform mat4 projectorMat; 7 | 8 | varying vec4 vRstq; 9 | 10 | void main() 11 | { 12 | vRstq = projectorMat * vec4(position, 1.0); 13 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 14 | } 15 | ` 16 | -------------------------------------------------------------------------------- /src/component/slider/shaders/perspective_distorted.vertex.glsl.ts: -------------------------------------------------------------------------------- 1 | export const perspectiveDistortedVert = ` 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | uniform mat4 projectorMat; 6 | varying vec4 vRstq; 7 | void main() 8 | { 9 | vRstq = projectorMat * vec4(position, 1.0); 10 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 11 | } 12 | ` 13 | -------------------------------------------------------------------------------- /src/api/contracts/CoreImagesContract.ts: -------------------------------------------------------------------------------- 1 | import { CoreImageEnt } from "../ents/CoreImageEnt"; 2 | 3 | /** 4 | * Contract describing core image results. 5 | */ 6 | export interface CoreImagesContract { 7 | /** 8 | * Geometry cell ID. 9 | */ 10 | cell_id: string; 11 | 12 | /** 13 | * Array of core image ents. 14 | */ 15 | images: CoreImageEnt[]; 16 | } 17 | -------------------------------------------------------------------------------- /doc/mapillary-js.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DOC="$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | # MapillaryJS 6 | # 7 | # Can not be in doc/node_modules because of 8 | # class inheritance problems related to CJS 9 | # module conversion in server build. 10 | MJS_NAME="mapillary-js" 11 | MJS_MODULE="$DOC/src/$MJS_NAME" 12 | MJS="$DOC/.." 13 | 14 | mkdir -p "$MJS_MODULE" 15 | cp -R "$MJS/dist" "$MJS_MODULE" 16 | -------------------------------------------------------------------------------- /doc/.stylelintrc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | module.exports = { 11 | plugins: ['stylelint-copyright'], 12 | rules: { 13 | 'docusaurus/copyright-header': true, 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /doc/sidebars/api.sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | module.exports = { 11 | api: [ 12 | { 13 | type: 'autogenerated', 14 | dirName: '.', 15 | }, 16 | ], 17 | }; 18 | -------------------------------------------------------------------------------- /src/api/interfaces/LngLat.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface that represents a longitude, latitude coordinate, 3 | * measured in degrees. Coordinates are defined in the WGS84 datum. 4 | */ 5 | export interface LngLat { 6 | /** 7 | * Latitude, measured in degrees. 8 | */ 9 | lat: number; 10 | 11 | /** 12 | * Longitude, measured in degrees. 13 | */ 14 | lng: number; 15 | } 16 | -------------------------------------------------------------------------------- /src/component/slider/shaders/perspective_distorted_curtain.vertex.glsl.ts: -------------------------------------------------------------------------------- 1 | export const perspectiveDistortedCurtainVert = ` 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | uniform mat4 projectorMat; 6 | varying vec4 vRstq; 7 | void main() 8 | { 9 | vRstq = projectorMat * vec4(position, 1.0); 10 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 11 | } 12 | ` 13 | -------------------------------------------------------------------------------- /src/component/interfaces/ZoomConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { ComponentConfiguration } from "./ComponentConfiguration"; 2 | import { ComponentSize } from "../util/ComponentSize"; 3 | 4 | export interface ZoomConfiguration extends ComponentConfiguration { 5 | /** 6 | * The size of the ui elements. 7 | * 8 | * @default ComponentSize.Automatic 9 | */ 10 | size?: ComponentSize; 11 | } 12 | -------------------------------------------------------------------------------- /src/viewer/events/ViewerReferenceEvent.ts: -------------------------------------------------------------------------------- 1 | import { LngLatAlt } from "../../external/api"; 2 | import { ViewerEvent } from "./ViewerEvent"; 3 | 4 | /** 5 | * Interface for viewer reference events. 6 | */ 7 | export interface ViewerReferenceEvent extends ViewerEvent { 8 | /** 9 | * The viewer's current reference. 10 | */ 11 | reference: LngLatAlt; 12 | 13 | type: "reference"; 14 | } 15 | -------------------------------------------------------------------------------- /test/helper/TestMath.ts: -------------------------------------------------------------------------------- 1 | export function isClockwise(polygon: number[][]): boolean { 2 | if (polygon.length < 3) { return false; }; 3 | let edgeSum = 0; 4 | for (let i = 0; i < polygon.length; ++i) { 5 | const [x1, y1] = polygon[i]; 6 | const [x2, y2] = polygon[(i + 1) % polygon.length]; 7 | edgeSum += (x2 - x1) * (y2 + y1); 8 | } 9 | return edgeSum > 0; 10 | } 11 | -------------------------------------------------------------------------------- /src/component/interfaces/BearingConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { ComponentConfiguration } from "./ComponentConfiguration"; 2 | import { ComponentSize } from "../util/ComponentSize"; 3 | 4 | export interface BearingConfiguration extends ComponentConfiguration { 5 | /** 6 | * The size of the ui elements. 7 | * 8 | * @default ComponentSize.Automatic 9 | */ 10 | size?: ComponentSize; 11 | } 12 | -------------------------------------------------------------------------------- /src/shader/chunk/map_color_fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export default /* glsl */` 2 | vec2 uv = sfmToUv(sfm, scale); 3 | float u = uv.x; 4 | float v = uv.y; 5 | 6 | vec4 mapColor; 7 | if (u >= 0. && u <= 1. && v >= 0. && v <= 1.) { 8 | mapColor = texture2D(map, vec2(u, v)); 9 | mapColor.a = opacity; 10 | } else { 11 | mapColor = vec4(0.0, 0.0, 0.0, 0.0); 12 | } 13 | `; 14 | -------------------------------------------------------------------------------- /src/component/spatial/enums/PointVisualizationMode.ts: -------------------------------------------------------------------------------- 1 | export enum PointVisualizationMode { 2 | /** 3 | * Points are hidden. 4 | */ 5 | Hidden, 6 | 7 | /** 8 | * Visualize points with original colors. 9 | */ 10 | Original, 11 | 12 | /** 13 | * Paint all points belonging to a specific 14 | * cluster with the same random color. 15 | */ 16 | Cluster, 17 | } 18 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .access-token 9 | .cache-loader 10 | .docusaurus 11 | /api 12 | /src/mapillary-js 13 | 14 | # Misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | # ESLint 26 | .eslintcache 27 | -------------------------------------------------------------------------------- /doc/src/js/components/viewer.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | @import '../../mapillary-js/dist/mapillary.css'; 11 | 12 | .mapillaryViewer { 13 | height: calc(100vh - 60px); 14 | width: 100%; 15 | } 16 | -------------------------------------------------------------------------------- /src/error/ArgumentMapillaryError.ts: -------------------------------------------------------------------------------- 1 | import { MapillaryError } from "./MapillaryError"; 2 | 3 | export class ArgumentMapillaryError extends MapillaryError { 4 | constructor(message?: string) { 5 | super(message != null ? message : "The argument is not valid."); 6 | 7 | Object.setPrototypeOf(this, ArgumentMapillaryError.prototype); 8 | 9 | this.name = "ArgumentMapillaryError"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/component/events/ComponentGeometryEvent.ts: -------------------------------------------------------------------------------- 1 | import { Geometry } from "../tag/geometry/Geometry"; 2 | import { ComponentEvent } from "./ComponentEvent"; 3 | 4 | /** 5 | * Interface for component geometry events. 6 | */ 7 | export interface ComponentGeometryEvent extends ComponentEvent { 8 | /** 9 | * Geometry related to the event. 10 | */ 11 | geometry: Geometry; 12 | 13 | type: "geometrycreate"; 14 | } 15 | -------------------------------------------------------------------------------- /src/component/events/ComponentTagModeEvent.ts: -------------------------------------------------------------------------------- 1 | import { TagMode } from "../tag/TagMode"; 2 | import { ComponentEvent } from "./ComponentEvent"; 3 | 4 | /** 5 | * Interface for component tag mode events. 6 | */ 7 | export interface ComponentTagModeEvent extends ComponentEvent { 8 | /** 9 | * Value indicating the current tag mode of the component. 10 | */ 11 | mode: TagMode; 12 | 13 | type: "tagmode"; 14 | } 15 | -------------------------------------------------------------------------------- /src/component/spatial/Modes.ts: -------------------------------------------------------------------------------- 1 | import { State } from "../../state/State"; 2 | import { CameraVisualizationMode } from "./enums/CameraVisualizationMode"; 3 | 4 | export function isModeVisible(mode: CameraVisualizationMode): boolean { 5 | return mode !== CameraVisualizationMode.Hidden; 6 | } 7 | 8 | export function isOverviewState(state: State): boolean { 9 | return state === State.Custom || state === State.Earth; 10 | } 11 | -------------------------------------------------------------------------------- /test/helper/MockCreatorBase.ts: -------------------------------------------------------------------------------- 1 | import { MockCreator } from "./MockCreator"; 2 | 3 | export abstract class MockCreatorBase { 4 | private _mockCreator: MockCreator = new MockCreator(); 5 | 6 | public abstract create(): T; 7 | 8 | protected _mockProperty(instance: T, propertyName: string, propertyValue: U): void { 9 | this._mockCreator.mockProperty(instance, propertyName, propertyValue); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /doc/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": [ 3 | "../src/external/api.ts", 4 | "../src/external/component.ts", 5 | "../src/external/viewer.ts" 6 | ], 7 | "excludeExternals": true, 8 | "excludePrivate": true, 9 | "excludeProtected": true, 10 | "hideGenerator": true, 11 | "includeVersion": true, 12 | "name": "MapillaryJS", 13 | "out": "../api", 14 | "readme": "none", 15 | "tsconfig": "../tsconfig.json" 16 | } 17 | -------------------------------------------------------------------------------- /src/api/events/ProviderCellEvent.ts: -------------------------------------------------------------------------------- 1 | import { ProviderEvent } from "./ProviderEvent"; 2 | 3 | /** 4 | * 5 | * Interface for data provider cell events. 6 | */ 7 | export interface ProviderCellEvent extends ProviderEvent { 8 | /** 9 | * Cell ids for cells where data have been created. 10 | */ 11 | cellIds: string[]; 12 | 13 | /** 14 | * Provider event type. 15 | */ 16 | type: "datacreate"; 17 | } 18 | -------------------------------------------------------------------------------- /src/viewer/events/ViewerEvent.ts: -------------------------------------------------------------------------------- 1 | import { IViewer } from "../interfaces/IViewer"; 2 | import { ViewerEventType } from "./ViewerEventType"; 3 | 4 | /** 5 | * Interface for general viewer events. 6 | */ 7 | export interface ViewerEvent { 8 | /** 9 | * The viewer object that fired the event. 10 | */ 11 | target: IViewer; 12 | 13 | /** 14 | * The event type. 15 | */ 16 | type: ViewerEventType; 17 | } 18 | -------------------------------------------------------------------------------- /styles/svg/stepper-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | chevronleft 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /styles/svg/stepper-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | chevronright 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/helper/ProviderHelper.ts: -------------------------------------------------------------------------------- 1 | import { DataProviderBase } from "../../src/api/DataProviderBase"; 2 | import { GeometryProviderBase } from "../../src/api/GeometryProviderBase"; 3 | 4 | export class GeometryProvider extends GeometryProviderBase { } 5 | 6 | export class DataProvider extends DataProviderBase { 7 | constructor(geometry?: GeometryProviderBase) { 8 | super(geometry ?? new GeometryProvider()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/component/tag/error/GeometryTagError.ts: -------------------------------------------------------------------------------- 1 | import { MapillaryError } from "../../../error/MapillaryError"; 2 | 3 | export class GeometryTagError extends MapillaryError { 4 | constructor(message?: string) { 5 | super(message != null ? message : "The provided geometry value is incorrect"); 6 | 7 | Object.setPrototypeOf(this, GeometryTagError.prototype); 8 | 9 | this.name = "GeometryTagError"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/api/events/ProviderClusterEvent.ts: -------------------------------------------------------------------------------- 1 | import { ProviderEvent } from "./ProviderEvent"; 2 | 3 | /** 4 | * 5 | * Interface for data provider cluster events. 6 | */ 7 | export interface ProviderClusterEvent extends ProviderEvent { 8 | /** 9 | * Cluster ids for clusters that have been deleted. 10 | */ 11 | clusterIds: string[]; 12 | 13 | /** 14 | * Provider event type. 15 | */ 16 | type: "datadelete"; 17 | } 18 | -------------------------------------------------------------------------------- /src/component/tag/interfaces/TagInteraction.ts: -------------------------------------------------------------------------------- 1 | import { Tag } from "../tag/Tag"; 2 | import { TagOperation } from "../TagOperation"; 3 | 4 | export type InteractionCursor = "crosshair" | "move" | "nesw-resize" | "nwse-resize"; 5 | 6 | export interface TagInteraction { 7 | cursor?: InteractionCursor; 8 | offsetX: number; 9 | offsetY: number; 10 | operation: TagOperation; 11 | tag: Tag; 12 | vertexIndex?: number; 13 | } 14 | -------------------------------------------------------------------------------- /test/tile/TileTypes.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | TILE_MIN_REQUEST_LEVEL, 3 | TILE_SIZE, 4 | } from "../../src/tile/interfaces/TileTypes"; 5 | 6 | describe("MIN_REQUEST_LEVEL", () => { 7 | it("should return 11", () => { 8 | expect(TILE_MIN_REQUEST_LEVEL).toBe(11); 9 | }); 10 | }); 11 | 12 | describe("TILE_SIZE", () => { 13 | it("should return 1024", () => { 14 | expect(TILE_SIZE).toBe(1024); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/component/spatial/enums/OriginalPositionMode.ts: -------------------------------------------------------------------------------- 1 | export enum OriginalPositionMode { 2 | /** 3 | * Original positions are hidden. 4 | */ 5 | Hidden, 6 | 7 | /** 8 | * Visualize original positions with altitude change. 9 | */ 10 | Altitude, 11 | 12 | /** 13 | * Visualize original positions without altitude change, 14 | * i.e. as flat lines from the camera origin. 15 | */ 16 | Flat, 17 | } 18 | -------------------------------------------------------------------------------- /src/shader/Shader.ts: -------------------------------------------------------------------------------- 1 | import { 2 | fragment as textureFragment, 3 | vertex as textureVertex, 4 | } from "./shaders/texture.glsl"; 5 | 6 | export interface GLShader { 7 | fragment: string; 8 | vertex: string; 9 | } 10 | 11 | // tslint:disable-next-line:variable-name 12 | export const Shader: { [name: string]: GLShader; } = { 13 | texture: { 14 | fragment: textureFragment, 15 | vertex: textureVertex, 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /styles/svg/turn.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/api/interfaces/LngLatAlt.ts: -------------------------------------------------------------------------------- 1 | import { LngLat } from "./LngLat"; 2 | 3 | /** 4 | * Interface that represents longitude-latitude-altitude 5 | * coordinates. Longitude and latitude are measured in degrees 6 | * and altitude in meters. Coordinates are defined in the WGS84 datum. 7 | * 8 | * @interface 9 | */ 10 | export interface LngLatAlt extends LngLat { 11 | /** 12 | * Altitude, measured in meters. 13 | */ 14 | alt: number; 15 | } 16 | -------------------------------------------------------------------------------- /src/api/ents/ImageTileEnt.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Ent representing image tile properties. 3 | */ 4 | export interface ImageTileEnt { 5 | /** 6 | * URL for fetching image tile pixel data. 7 | */ 8 | url: string, 9 | 10 | /** 11 | * X tile coordinate. 12 | */ 13 | x: number, 14 | 15 | /** 16 | * Y tile coordinate. 17 | */ 18 | y: number, 19 | 20 | /** 21 | * Tile level. 22 | */ 23 | z: number, 24 | } 25 | -------------------------------------------------------------------------------- /src/component/events/ComponentEvent.ts: -------------------------------------------------------------------------------- 1 | import { IComponent } from "../interfaces/IComponent"; 2 | import { ComponentEventType } from "./ComponentEventType"; 3 | 4 | /** 5 | * Interface for general component events. 6 | */ 7 | export interface ComponentEvent { 8 | /** 9 | * The component object that fired the event. 10 | */ 11 | target: IComponent; 12 | 13 | /** 14 | * The event type. 15 | */ 16 | type: ComponentEventType; 17 | } 18 | -------------------------------------------------------------------------------- /src/api/events/ProviderEvent.ts: -------------------------------------------------------------------------------- 1 | import { IDataProvider } from "../interfaces/IDataProvider"; 2 | import { ProviderEventType } from "./ProviderEventType"; 3 | 4 | /** 5 | * Interface for general provider events. 6 | */ 7 | export interface ProviderEvent { 8 | /** 9 | * Data provider target that emitted the event. 10 | */ 11 | target: IDataProvider; 12 | 13 | /** 14 | * Provider event type. 15 | */ 16 | type: ProviderEventType; 17 | } 18 | -------------------------------------------------------------------------------- /src/component/events/ComponentHoverEvent.ts: -------------------------------------------------------------------------------- 1 | import { ComponentEvent } from "./ComponentEvent"; 2 | 3 | /** 4 | * Interface for component hover events. 5 | */ 6 | export interface ComponentHoverEvent extends ComponentEvent { 7 | /** 8 | * The image id corresponding to the element or object that 9 | * is being hovered. When the mouse leaves the element or 10 | * object the id will be null. 11 | */ 12 | id: string; 13 | 14 | type: "hover"; 15 | } 16 | -------------------------------------------------------------------------------- /src/viewer/events/ViewerImageEvent.ts: -------------------------------------------------------------------------------- 1 | import { ViewerEvent } from "./ViewerEvent"; 2 | import { Image } from "../../graph/Image"; 3 | 4 | /** 5 | * Interface for viewer image events. 6 | */ 7 | export interface ViewerImageEvent extends ViewerEvent { 8 | /** 9 | * The viewer's current image. 10 | * 11 | * @description If the viewer is reset, the emitted 12 | * image will be null. 13 | */ 14 | image: Image | null; 15 | 16 | type: "image"; 17 | } 18 | -------------------------------------------------------------------------------- /test/helper/GeoHelper.ts: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import { Spatial } from "../../src/geo/Spatial"; 3 | 4 | export class GeoHelper { 5 | private spatial: Spatial = new Spatial(); 6 | 7 | public getTranslation(r: number[], C: number[]): number[] { 8 | let R: THREE.Matrix4 = this.spatial.rotationMatrix(r); 9 | let t: number[] = new THREE.Vector3().fromArray(C).applyMatrix4(R).multiplyScalar(-1).toArray(); 10 | 11 | return t; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/util/SubscriptionHolder.ts: -------------------------------------------------------------------------------- 1 | import { Subscription } from "rxjs"; 2 | 3 | export class SubscriptionHolder { 4 | private _subscriptions: Subscription[] = []; 5 | 6 | public push(subscription: Subscription): void { 7 | this._subscriptions.push(subscription); 8 | } 9 | 10 | public unsubscribe(): void { 11 | for (const sub of this._subscriptions) { 12 | sub.unsubscribe(); 13 | } 14 | 15 | this._subscriptions = []; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/api/contracts/MeshContract.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Contract describing triangulated meshes. 3 | */ 4 | export interface MeshContract { 5 | /** 6 | * Flattened array of faces for the mesh. Each face consist 7 | * three vertex indices. 8 | */ 9 | faces: number[]; 10 | 11 | /** 12 | * Flattened array of vertices for the mesh. Each vertex 13 | * consists of X, Y and Z coordinates in the camera 14 | * reference frame. 15 | */ 16 | vertices: number[]; 17 | } 18 | -------------------------------------------------------------------------------- /src/component/events/ComponentMarkerEvent.ts: -------------------------------------------------------------------------------- 1 | import { Marker } from "../marker/marker/Marker"; 2 | import { ComponentEvent } from "./ComponentEvent"; 3 | 4 | /** 5 | * Interface for component marker events. 6 | */ 7 | export interface ComponentMarkerEvent extends ComponentEvent { 8 | /** 9 | * The marker that was affected by the event. 10 | */ 11 | marker: Marker; 12 | 13 | type: 14 | | "markerdragend" 15 | | "markerdragstart" 16 | | "markerposition"; 17 | } 18 | -------------------------------------------------------------------------------- /styles/svg/turn-around.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/tile/interfaces/TileBoundingBox.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface that describes a bounding box. 3 | * 4 | * @interface TileBoundingBox 5 | */ 6 | export interface TileBoundingBox { 7 | /** 8 | * The minimum x value. 9 | */ 10 | minX: number; 11 | 12 | /** 13 | * The minimum y value. 14 | */ 15 | minY: number; 16 | 17 | /** 18 | * The maximum x value. 19 | */ 20 | maxX: number; 21 | 22 | /** 23 | * The maximum y value. 24 | */ 25 | maxY: number; 26 | } 27 | -------------------------------------------------------------------------------- /src/viewer/events/ViewerNavigationEdgeEvent.ts: -------------------------------------------------------------------------------- 1 | import { NavigationEdgeStatus } 2 | from "../../graph/interfaces/NavigationEdgeStatus"; 3 | import { ViewerEvent } from "./ViewerEvent"; 4 | 5 | /** 6 | * Interface for navigation edge viewer events. 7 | */ 8 | export interface ViewerNavigationEdgeEvent extends ViewerEvent { 9 | /** 10 | * The viewer's current navigation edge status. 11 | */ 12 | status: NavigationEdgeStatus; 13 | 14 | type: 15 | | "sequenceedges" 16 | | "spatialedges"; 17 | } 18 | -------------------------------------------------------------------------------- /src/viewer/events/ViewerResetEvent.ts: -------------------------------------------------------------------------------- 1 | import { ViewerEvent } from "./ViewerEvent"; 2 | 3 | /** 4 | * Interface for viewer reset events. 5 | * 6 | * @description Fired immediately after all resources 7 | * have been cleared. 8 | * 9 | * @example 10 | * ```js 11 | * // Set up an event listener on the viewer. 12 | * viewer.on('reset', function(e) { 13 | * console.log('A reset event has occured'); 14 | * }); 15 | * ``` 16 | */ 17 | export interface ViewerResetEvent extends ViewerEvent { 18 | type: "reset"; 19 | } 20 | -------------------------------------------------------------------------------- /test/helper/RequestHelper.ts: -------------------------------------------------------------------------------- 1 | export class XMLHTTPRequestMock { 2 | public response: {}; 3 | public responseType: string; 4 | public status: number; 5 | public timeout: number; 6 | 7 | public onload: (e: Event) => any; 8 | public onerror: (e: Event) => any; 9 | public ontimeout: (e: Event) => any; 10 | public onabort: (e: Event) => any; 11 | 12 | public abort(): void { this.onabort(new Event("abort")); } 13 | public open(...args: any[]): void { return; } 14 | public send(...args: any[]): void { return; } 15 | }; 16 | -------------------------------------------------------------------------------- /test/state/StateService.test.ts: -------------------------------------------------------------------------------- 1 | import { bootstrap } from "../Bootstrap"; 2 | bootstrap(); 3 | 4 | import { StateService } from "../../src/state/StateService"; 5 | import { State } from "../../src/state/State"; 6 | import { S2GeometryProvider } from "../../src/api/S2GeometryProvider"; 7 | 8 | describe("StateService.ctor", () => { 9 | it("should be contructed", () => { 10 | let stateService: StateService = new StateService(State.Traversing, new S2GeometryProvider()); 11 | 12 | expect(stateService).toBeDefined(); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/viewer/LoadingService.test.ts: -------------------------------------------------------------------------------- 1 | import { LoadingService } from "../../src/viewer/LoadingService"; 2 | 3 | describe("LoadingService", () => { 4 | let loadingService: LoadingService; 5 | 6 | beforeEach(() => { 7 | loadingService = new LoadingService(); 8 | }); 9 | 10 | it("should be initialized to not loading", (done: Function) => { 11 | loadingService.loading$ 12 | .subscribe((loading: boolean) => { 13 | expect(loading).toBe(false); 14 | done(); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /doc/docs/theory/theory.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: theory 3 | title: Theory 4 | --- 5 | 6 | This section is a deep dive in some of the theoretical concepts used in MapillaryJS. Reading and understanding this section is not needed when using MapillaryJS in your applications. 7 | 8 | :::info You will learn 9 | 10 | - [What coordinate systems are used and how can you convert between them](/docs/theory/coordinates) 11 | - [How the navigation graph is built](/docs/theory/navigation-graph) 12 | - [How to triangulate polygons on the sphere](/docs/theory/polygon-triangulation) 13 | 14 | ::: 15 | -------------------------------------------------------------------------------- /src/viewer/events/ViewerBearingEvent.ts: -------------------------------------------------------------------------------- 1 | import { ViewerEvent } from "./ViewerEvent"; 2 | 3 | /** 4 | * Interface for bearing viewer events. 5 | */ 6 | export interface ViewerBearingEvent extends ViewerEvent { 7 | /** 8 | * Bearing is measured in degrees 9 | * clockwise with respect to north. 10 | * 11 | * @description Bearing is related to the computed 12 | * compass angle ({@link Image.computedCompassAngle}) 13 | * from SfM, not the original EXIF compass angle. 14 | */ 15 | bearing: number; 16 | 17 | type: "bearing"; 18 | } 19 | -------------------------------------------------------------------------------- /src/geometry/Camera.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CameraParameters, 3 | CameraUniforms, 4 | ICamera, 5 | } from "./interfaces/ICamera"; 6 | 7 | export abstract class Camera implements ICamera { 8 | public readonly parameters: CameraParameters = {}; 9 | public readonly uniforms: CameraUniforms = {}; 10 | 11 | constructor( 12 | public readonly type: string, 13 | public readonly projectToSfmFunction: string) { } 14 | 15 | public abstract bearingFromSfm(_point: number[]): number[]; 16 | public abstract projectToSfm(_point: number[]): number[]; 17 | } 18 | -------------------------------------------------------------------------------- /src/state/interfaces/IStateBase.ts: -------------------------------------------------------------------------------- 1 | import { Camera } from "../../geo/Camera"; 2 | import { LngLatAlt } from "../../api/interfaces/LngLatAlt"; 3 | import { TransitionMode } from "../TransitionMode"; 4 | import { Image } from "../../graph/Image"; 5 | import { IGeometryProvider } from "../../mapillary"; 6 | 7 | export interface IStateBase { 8 | alpha: number; 9 | camera: Camera; 10 | currentIndex: number; 11 | geometry: IGeometryProvider, 12 | reference: LngLatAlt; 13 | trajectory: Image[]; 14 | transitionMode: TransitionMode; 15 | zoom: number; 16 | } 17 | -------------------------------------------------------------------------------- /doc/src/js/utils/error.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import {CancelMapillaryError} from '../../mapillary-js/dist/mapillary.module'; 11 | 12 | export function mapillaryErrorHandler(error) { 13 | if (error instanceof CancelMapillaryError) { 14 | console.warn(`Navigation request cancelled: ${error.message}`); 15 | } else { 16 | console.error(error); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/viewer/options/UrlOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface for the URL options that can be provided to the viewer. 3 | * 4 | * @interface 5 | */ 6 | export interface UrlOptions { 7 | /** 8 | * Explore host. 9 | * 10 | * @description Host used for links to the full 11 | * mapillary website. 12 | * 13 | * @default {"www.mapillary.com"} 14 | */ 15 | exploreHost?: string; 16 | 17 | /** 18 | * Scheme. 19 | * 20 | * @description Used for all hosts. 21 | * 22 | * @default {"https"} 23 | */ 24 | scheme?: string; 25 | } 26 | -------------------------------------------------------------------------------- /doc/src/js/components/code.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | .codeButton { 11 | position: fixed; 12 | top: 76px; 13 | left: 16px; 14 | padding: 13px 12px 9px 12px; 15 | border-radius: 50%; 16 | margin-bottom: 0px; 17 | background-color: #fff; 18 | opacity: 0.9; 19 | box-shadow: 0px 0px 3px rgb(0 0 0 / 40%); 20 | } 21 | 22 | .codeArrows { 23 | width: 24px; 24 | } 25 | -------------------------------------------------------------------------------- /src/error/CancelMapillaryError.ts: -------------------------------------------------------------------------------- 1 | import { MapillaryError } from "./MapillaryError"; 2 | 3 | /** 4 | * @class CancelMapillaryError 5 | * 6 | * @classdesc Error thrown when a move to request has been 7 | * cancelled before completing because of a subsequent request. 8 | */ 9 | export class CancelMapillaryError extends MapillaryError { 10 | constructor(message?: string) { 11 | super(message != null ? message : "The request was cancelled."); 12 | 13 | Object.setPrototypeOf(this, CancelMapillaryError.prototype); 14 | 15 | this.name = "CancelMapillaryError"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/viewer/interfaces/PointOfView.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface PointOfView 3 | * 4 | * Interface that represents the point of view of the viewer. 5 | */ 6 | export interface PointOfView { 7 | /** 8 | * Value indicating the current bearing of the viewer 9 | * measured in degrees clockwise with respect to north. 10 | * Ranges from 0° to 360°. 11 | */ 12 | bearing: number; 13 | 14 | /** 15 | * The camera tilt in degrees, relative to a horizontal plane. 16 | * Ranges from 90° (directly upwards) to -90° (directly downwards). 17 | */ 18 | tilt: number; 19 | } 20 | -------------------------------------------------------------------------------- /test/helper/LoadingServiceMockCreator.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from "rxjs"; 2 | import { LoadingService } from "../../src/viewer/LoadingService"; 3 | 4 | import { MockCreator } from "./MockCreator"; 5 | import { MockCreatorBase } from "./MockCreatorBase"; 6 | 7 | export class LoadingServiceMockCreator extends MockCreatorBase { 8 | public create(): LoadingService { 9 | const mock: LoadingService = new MockCreator().create(LoadingService, "LoadingService"); 10 | 11 | this._mockProperty(mock, "loading$", new Subject()); 12 | 13 | return mock; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/component/tag/interfaces/ExtremePointCreateTagOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface for the options that define the behavior and 3 | * appearance of the extreme point create tag. 4 | * 5 | * @interface 6 | */ 7 | export interface ExtremePointCreateTagOptions { 8 | /** 9 | * Text color as hexadecimal number. 10 | * @default 0xFFFFFF 11 | */ 12 | color?: number; 13 | 14 | /** 15 | * Show an indicator at the centroid of the extreme 16 | * point tag rectrangle that creates the geometry when 17 | * clicked. 18 | * @default true 19 | */ 20 | indicateCompleter?: boolean; 21 | } 22 | -------------------------------------------------------------------------------- /src/geo/GeoRBush.ts: -------------------------------------------------------------------------------- 1 | import { BBox } from "rbush"; 2 | import RBush from "rbush"; 3 | 4 | import { LngLat } from "../api/interfaces/LngLat"; 5 | 6 | export class GeoRBush extends RBush { 7 | public compareMinX(a: T, b: T): number { 8 | return a.lng - b.lng; 9 | } 10 | 11 | public compareMinY(a: T, b: T): number { 12 | return a.lat - b.lat; 13 | } 14 | 15 | public toBBox(item: T): BBox { 16 | return { 17 | minX: item.lng, 18 | minY: item.lat, 19 | maxX: item.lng, 20 | maxY: item.lat, 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/viewer/Modes.ts: -------------------------------------------------------------------------------- 1 | import { State } from "../state/State"; 2 | import { CameraControls } from "./enums/CameraControls"; 3 | 4 | export function cameraControlsToState(cameraControls: CameraControls): State { 5 | switch (cameraControls) { 6 | case CameraControls.Custom: 7 | return State.Custom; 8 | case CameraControls.Earth: 9 | return State.Earth; 10 | case CameraControls.Gravity: 11 | return State.GravityTraversing; 12 | case CameraControls.Street: 13 | return State.Traversing; 14 | default: 15 | return null; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/graph/edge/interfaces/NavigationEdge.ts: -------------------------------------------------------------------------------- 1 | import { NavigationEdgeData } from "./NavigationEdgeData"; 2 | 3 | /** 4 | * Interface that describes the properties for a 5 | * navigation edge from a source image to a 6 | * target image. 7 | * 8 | * @interface NavigationEdge 9 | */ 10 | export interface NavigationEdge { 11 | /** 12 | * The id of the source image. 13 | */ 14 | source: string; 15 | 16 | /** 17 | * The id of the target image. 18 | */ 19 | target: string; 20 | 21 | /** 22 | * Additional data describing properties of the edge. 23 | */ 24 | data: NavigationEdgeData; 25 | } 26 | -------------------------------------------------------------------------------- /src/component/marker/interfaces/CircleMarkerOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @interface CircleMarkerOptions 3 | * 4 | * Interface that represents the options for configuring a `CircleMarker`. 5 | */ 6 | export interface CircleMarkerOptions { 7 | /** 8 | * The color of the marker. 9 | * 10 | * @default "#fff" 11 | */ 12 | color?: number | string; 13 | 14 | /** 15 | * The opacity of the marker. 16 | * 17 | * @default 0.4 18 | */ 19 | opacity?: number; 20 | 21 | /** 22 | * The radius of the circle in meters. 23 | * 24 | * @default 1 25 | */ 26 | radius?: number; 27 | } 28 | -------------------------------------------------------------------------------- /src/graph/edge/interfaces/NavigationEdgeData.ts: -------------------------------------------------------------------------------- 1 | import { NavigationDirection } from "../NavigationDirection"; 2 | 3 | /** 4 | * Interface that describes additional properties of an edge. 5 | * 6 | * @interface NavigationEdgeData 7 | */ 8 | export interface NavigationEdgeData { 9 | /** 10 | * The edge direction. 11 | */ 12 | direction: NavigationDirection; 13 | 14 | /** 15 | * The counter clockwise horizontal rotation angle from 16 | * the X-axis in a spherical coordiante system of the 17 | * motion from the source image to the destination node. 18 | */ 19 | worldMotionAzimuth: number; 20 | } 21 | -------------------------------------------------------------------------------- /src/component/tag/tag/events/TagStateEvent.ts: -------------------------------------------------------------------------------- 1 | import { Tag } from "../Tag"; 2 | import { TagEventType } from "./TagEventType"; 3 | 4 | /** 5 | * Interface for tag state events. 6 | * 7 | * @example 8 | * ```js 9 | * var tag = new OutlineTag({ // tag options }); 10 | * // Set an event listener 11 | * tag.on('tag', function() { 12 | * console.log("A tag event has occurred."); 13 | * }); 14 | * ``` 15 | */ 16 | export interface TagStateEvent { 17 | /** 18 | * The component object that fired the event. 19 | */ 20 | target: Tag; 21 | 22 | /** 23 | * The event type. 24 | */ 25 | type: TagEventType; 26 | } 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "declaration": true, 5 | "lib": ["es6", "dom"], 6 | "module": "es6", 7 | "moduleResolution": "node", 8 | "noImplicitAny": true, 9 | "outDir": "build/esm/", 10 | "sourceMap": true, 11 | "target": "es6", 12 | "typeRoots": ["node_modules/@types", "types"], 13 | "types": [ 14 | "earcut", 15 | "jest", 16 | "node", 17 | "pbf", 18 | "polylabel", 19 | "rbush", 20 | "s2-geometry", 21 | "three", 22 | "virtual-dom" 23 | ] 24 | }, 25 | "include": ["src/**/*", "test/**/*"] 26 | } 27 | -------------------------------------------------------------------------------- /src/tile/interfaces/TileTypes.ts: -------------------------------------------------------------------------------- 1 | export const TILE_MIN_REQUEST_LEVEL = 11; 2 | export const TILE_SIZE = 1024; 3 | 4 | export interface TileImageSize { 5 | h: number; 6 | w: number; 7 | } 8 | 9 | export interface TileCoords2D { 10 | x: number; 11 | y: number; 12 | } 13 | 14 | export interface TileCoords3D extends TileCoords2D { 15 | z: number; 16 | } 17 | 18 | export interface TilePixelCoords2D extends 19 | TileImageSize, 20 | TileCoords2D { } 21 | 22 | export interface TileLevelColumnRows { 23 | columns: number; 24 | rows: number; 25 | } 26 | 27 | export interface TileLevel { 28 | z: number; 29 | max: number; 30 | } 31 | -------------------------------------------------------------------------------- /src/tile/interfaces/TileRegionOfInterest.ts: -------------------------------------------------------------------------------- 1 | import { TileBoundingBox } from "./TileBoundingBox"; 2 | 3 | /** 4 | * Interface that describes a region of interest. 5 | * 6 | * @interface TileRegionOfInterest 7 | */ 8 | export interface TileRegionOfInterest { 9 | /** 10 | * The bounding box for the region of interest in basic coordinates. 11 | */ 12 | bbox: TileBoundingBox; 13 | 14 | /** 15 | * Width of the footprint of a canvas pixel in basic coordinates. 16 | */ 17 | pixelWidth: number; 18 | 19 | /** 20 | * Height of the footprint of a canvas pixel in basic coordinates. 21 | */ 22 | pixelHeight: number; 23 | } 24 | -------------------------------------------------------------------------------- /src/viewer/events/ViewerEventType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @event 3 | */ 4 | export type ViewerEventType = 5 | | "bearing" 6 | | "click" 7 | | "contextmenu" 8 | | "dataprovider" 9 | | "dblclick" 10 | | "drag" 11 | | "dragend" 12 | | "dragstart" 13 | | "fov" 14 | | "dataloading" 15 | | "load" 16 | | "mousedown" 17 | | "mousemove" 18 | | "mouseout" 19 | | "mouseover" 20 | | "mouseup" 21 | | "moveend" 22 | | "movestart" 23 | | "navigable" 24 | | "image" 25 | | "position" 26 | | "pov" 27 | | "reference" 28 | | "remove" 29 | | "reset" 30 | | "sequenceedges" 31 | | "spatialedges"; 32 | -------------------------------------------------------------------------------- /src/viewer/events/ViewerDataLoadingEvent.ts: -------------------------------------------------------------------------------- 1 | import { ViewerEvent } from "./ViewerEvent"; 2 | 3 | /** 4 | * Interface for viewer data loading events. 5 | * 6 | * @description Fired when any viewer data (image, mesh, metadata, etc) 7 | * begins loading or changing asyncronously as a result of viewer 8 | * navigation. 9 | * 10 | * Also fired when the data has finished loading and the viewer 11 | * is able to perform the navigation. 12 | */ 13 | export interface ViewerDataLoadingEvent extends ViewerEvent { 14 | /** 15 | * Indicates if the viewer navigation is awaiting data load. 16 | */ 17 | loading: boolean; 18 | 19 | type: "dataloading"; 20 | } 21 | -------------------------------------------------------------------------------- /src/viewer/events/ViewerNavigableEvent.ts: -------------------------------------------------------------------------------- 1 | import { ViewerEvent } from "./ViewerEvent"; 2 | 3 | /** 4 | * Interface for navigable viewer events. 5 | */ 6 | export interface ViewerNavigableEvent extends ViewerEvent { 7 | /** 8 | * The navigable state indicates if the viewer supports 9 | * moving, i.e. calling the `moveTo` and `moveDir` 10 | * methods. The viewer will not be in a navigable state if the cover 11 | * is activated and the viewer has been supplied a id. When the cover 12 | * is deactivated or activated without being supplied a id it will 13 | * be navigable. 14 | */ 15 | navigable: boolean; 16 | 17 | type: "navigable"; 18 | } 19 | -------------------------------------------------------------------------------- /src/viewer/events/ViewerStateEvent.ts: -------------------------------------------------------------------------------- 1 | import { ViewerEvent } from "./ViewerEvent"; 2 | 3 | /** 4 | * Interface for viewer state events. 5 | * 6 | * @example 7 | * ```js 8 | * // The `fov` event is an example of a `ViewerStateEvent`. 9 | * // Set up an event listener on the viewer. 10 | * viewer.on('fov', function(e) { 11 | * console.log('A fov event has occured'); 12 | * }); 13 | * ``` 14 | */ 15 | export interface ViewerStateEvent extends ViewerEvent { 16 | /** 17 | * The event type. 18 | */ 19 | type: 20 | | "dataprovider" 21 | | "fov" 22 | | "moveend" 23 | | "movestart" 24 | | "position" 25 | | "pov" 26 | | "remove"; 27 | } 28 | -------------------------------------------------------------------------------- /src/component/slider/shaders/spherical.fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export const sphericalFrag = ` 2 | #ifdef GL_FRAGMENT_PRECISION_HIGH 3 | precision highp float; 4 | #else 5 | precision mediump float; 6 | #endif 7 | 8 | #define tau 6.28318530718 9 | 10 | uniform sampler2D projectorTex; 11 | uniform float opacity; 12 | 13 | varying vec4 vRstq; 14 | 15 | void main() 16 | { 17 | vec3 b = normalize(vRstq.xyz); 18 | float lat = -asin(b.y); 19 | float lng = atan(b.x, b.z); 20 | float x = lng / tau + 0.5; 21 | float y = lat / tau * 2.0 + 0.5; 22 | vec4 baseColor = texture2D(projectorTex, vec2(x, y)); 23 | baseColor.a = opacity; 24 | gl_FragColor = baseColor; 25 | } 26 | ` 27 | -------------------------------------------------------------------------------- /src/viewer/events/ViewerDragEndEvent.ts: -------------------------------------------------------------------------------- 1 | import { LngLat } from "../../api/interfaces/LngLat"; 2 | import { ViewerEvent } from "./ViewerEvent"; 3 | 4 | /** 5 | * Interface for drag end viewer events. 6 | * 7 | * @example 8 | * ```js 9 | * // Set up an event listener on the viewer. 10 | * viewer.on('dragened', function(e) { 11 | * console.log(e.originalEvent); 12 | * }); 13 | * ``` 14 | */ 15 | export interface ViewerDragEndEvent extends ViewerEvent { 16 | /** 17 | * The original event that triggered the viewer event. 18 | */ 19 | originalEvent: MouseEvent | FocusEvent; 20 | 21 | /** 22 | * The event type. 23 | */ 24 | type: "dragend"; 25 | } 26 | -------------------------------------------------------------------------------- /test/helper/SpriteServiceMockCreator.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from "rxjs"; 2 | import { ISpriteAtlas } from "../../src/viewer/interfaces/ISpriteAtlas"; 3 | import { SpriteService } from "../../src/viewer/SpriteService"; 4 | 5 | import { MockCreator } from "./MockCreator"; 6 | import { MockCreatorBase } from "./MockCreatorBase"; 7 | 8 | export class SpriteServiceMockCreator extends MockCreatorBase { 9 | public create(): SpriteService { 10 | const mock: SpriteService = new MockCreator().create(SpriteService, "SpriteService"); 11 | 12 | this._mockProperty(mock, "spriteAtlas$", new Subject()); 13 | 14 | return mock; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/component/spatial/enums/CameraVisualizationMode.ts: -------------------------------------------------------------------------------- 1 | export enum CameraVisualizationMode { 2 | /** 3 | * Cameras are hidden. 4 | */ 5 | Hidden, 6 | 7 | /** 8 | * Cameras are shown, all with the same color. 9 | */ 10 | Homogeneous, 11 | 12 | /** 13 | * Cameras are shown with colors based on the 14 | * their clusters. 15 | */ 16 | Cluster, 17 | 18 | /** 19 | * Cameras are shown with colors based on the 20 | * their connected components. 21 | */ 22 | ConnectedComponent, 23 | 24 | /** 25 | * Cameras are shown, with colors based on the 26 | * their sequence. 27 | */ 28 | Sequence, 29 | } 30 | -------------------------------------------------------------------------------- /test/helper/ImageMockCreator.ts: -------------------------------------------------------------------------------- 1 | import { Image as MImage } from "../../src/graph/Image"; 2 | 3 | import { MockCreator } from "./MockCreator"; 4 | import { MockCreatorBase } from "./MockCreatorBase"; 5 | 6 | export class ImageMockCreator extends MockCreatorBase { 7 | public create(configuration?: { [key: string]: any }): MImage { 8 | const mock: MImage = new MockCreator().create(MImage, "Image"); 9 | 10 | this._mockProperty( 11 | mock, "image", 12 | configuration.image ?? new Image()); 13 | this._mockProperty( 14 | mock, "key", 15 | configuration.key ?? "key"); 16 | 17 | return mock; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/helper/KeyboardServiceMockCreator.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from "rxjs"; 2 | import { KeyboardService } from "../../src/viewer/KeyboardService"; 3 | 4 | import { MockCreator } from "./MockCreator"; 5 | import { MockCreatorBase } from "./MockCreatorBase"; 6 | 7 | export class KeyboardServiceMockCreator extends MockCreatorBase { 8 | public create(): KeyboardService { 9 | const mock: KeyboardService = new MockCreator().create(KeyboardService, "KeyboardService"); 10 | 11 | this._mockProperty(mock, "keyDown$", new Subject()); 12 | this._mockProperty(mock, "keyUp$", new Subject()); 13 | 14 | return mock; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/component/slider/SliderInterfaces.ts: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import { Image } from "../../graph/Image"; 3 | import { IAnimationState } from "../../state/interfaces/IAnimationState"; 4 | import { SliderGLRenderer } from "./SliderGLRenderer"; 5 | export interface SliderImages { 6 | background: Image; 7 | foreground: Image; 8 | } 9 | export interface SliderCombination { 10 | images: SliderImages; 11 | state: IAnimationState; 12 | } 13 | export interface GLRendererOperation { 14 | (glRenderer: SliderGLRenderer): SliderGLRenderer; 15 | } 16 | export type PositionLookat = [ 17 | THREE.Vector3, 18 | THREE.Vector3, 19 | number, 20 | number, 21 | number, 22 | ]; 23 | -------------------------------------------------------------------------------- /src/component/slider/shaders/perspective_distorted.fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export const perspectiveDistortedFrag = ` 2 | #ifdef GL_FRAGMENT_PRECISION_HIGH 3 | precision highp float; 4 | #else 5 | precision mediump float; 6 | #endif 7 | uniform sampler2D projectorTex; 8 | uniform float opacity; 9 | varying vec4 vRstq; 10 | void main() 11 | { 12 | float u = vRstq.x / vRstq.w; 13 | float v = vRstq.y / vRstq.w; 14 | vec4 baseColor; 15 | if (u >= 0. && u <= 1. && v >= 0. && v <= 1.) { 16 | baseColor = texture2D(projectorTex, vec2(u, v)); 17 | baseColor.a = opacity; 18 | } else { 19 | baseColor = vec4(0.0, 0.0, 0.0, 0.0); 20 | } 21 | gl_FragColor = baseColor; 22 | } 23 | ` 24 | -------------------------------------------------------------------------------- /config/rollup.js: -------------------------------------------------------------------------------- 1 | import commonjs from "@rollup/plugin-commonjs"; 2 | import resolve from "@rollup/plugin-node-resolve"; 3 | import sourcemaps from "rollup-plugin-sourcemaps"; 4 | 5 | const resolveOptions = { preferBuiltins: false }; 6 | 7 | export const plugins = [sourcemaps(), resolve(resolveOptions), commonjs()]; 8 | 9 | export const umdOutput = { 10 | format: "umd", 11 | name: "mapillary", 12 | sourcemap: true, 13 | }; 14 | 15 | export const srcInput = "build/esm/src/mapillary.js"; 16 | 17 | export const esm = { 18 | input: srcInput, 19 | output: [ 20 | { 21 | file: "dist/mapillary.module.js", 22 | format: "es", 23 | sourcemap: true, 24 | }, 25 | ], 26 | plugins, 27 | }; 28 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | collectCoverage: true, 3 | collectCoverageFrom: ["/src/**/*"], 4 | coveragePathIgnorePatterns: [ 5 | "/src/api/contracts/", 6 | "/src/api/ents/", 7 | "/src/export/", 8 | "/src/component/shaders/", 9 | "/src/mapillary.js", 10 | "/src/viewer/events/", 11 | "/src/viewer/options/", 12 | "interfaces", 13 | ], 14 | coverageProvider: "babel", 15 | moduleDirectories: ["node_modules"], 16 | moduleFileExtensions: ["js"], 17 | rootDir: "build/cjs", 18 | slowTestThreshold: 1, 19 | testEnvironment: "jsdom", 20 | testRunner: "jest-jasmine2", 21 | watchman: false, 22 | }; 23 | -------------------------------------------------------------------------------- /src/api/ents/CoreImageEnt.ts: -------------------------------------------------------------------------------- 1 | import { IDEnt } from "./IDEnt"; 2 | import { LngLat } from "../interfaces/LngLat"; 3 | 4 | /** 5 | * Ent representing core image properties. 6 | */ 7 | export interface CoreImageEnt extends IDEnt { 8 | /** 9 | * SfM computed longitude, latitude in WGS84 datum, measured in degrees. 10 | * 11 | * @description Optional - no 3D interaction available 12 | * if unset. 13 | */ 14 | computed_geometry?: LngLat; 15 | 16 | /** 17 | * Original EXIF longitude, latitude in WGS84 datum, measured in degrees. 18 | */ 19 | geometry: LngLat; 20 | 21 | /** 22 | * Sequence that the image is part of. 23 | */ 24 | sequence: IDEnt; 25 | } 26 | -------------------------------------------------------------------------------- /src/graph/interfaces/NavigationEdgeStatus.ts: -------------------------------------------------------------------------------- 1 | import { NavigationEdge } from "../edge/interfaces/NavigationEdge"; 2 | 3 | /** 4 | * Interface that indicates edge status. 5 | * 6 | * @interface NavigationEdgeStatus 7 | */ 8 | export interface NavigationEdgeStatus { 9 | /** 10 | * Value indicating whether the edges have been cached. 11 | */ 12 | cached: boolean; 13 | 14 | /** 15 | * The edges. 16 | * 17 | * @description If the cached property is false the edges 18 | * property will always be an empty array. If the cached 19 | * property is true, there will exist edges in the the 20 | * array if the image has edges. 21 | */ 22 | edges: NavigationEdge[]; 23 | } 24 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.10 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | 5 | RUN apt-get update && \ 6 | apt-get install -y \ 7 | git \ 8 | curl && \ 9 | apt-get clean && \ 10 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 11 | 12 | RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && \ 13 | apt-get install -y nodejs 14 | 15 | RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg \ 16 | | apt-key add && \ 17 | echo "deb https://dl.yarnpkg.com/debian/ stable main" \ 18 | | tee /etc/apt/sources.list.d/yarn.list && \ 19 | apt update && \ 20 | apt install yarn 21 | 22 | COPY . /source/original-source/mapillary-js 23 | 24 | WORKDIR /source/mapillary-js 25 | -------------------------------------------------------------------------------- /src/component/interfaces/IComponent.ts: -------------------------------------------------------------------------------- 1 | import { ComponentConfiguration } from "./ComponentConfiguration"; 2 | 3 | export interface IComponent { 4 | /** 5 | * Value indicating if the component is currently active. 6 | */ 7 | readonly activated: boolean; 8 | 9 | /** 10 | * Default configuration for the component. 11 | */ 12 | readonly defaultConfiguration: ComponentConfiguration; 13 | 14 | /** 15 | * The name of the component. Used when interacting with the 16 | * component through the Viewer's API. 17 | */ 18 | readonly name: string; 19 | 20 | /** 21 | * Configure the component. 22 | */ 23 | configure(configuration: ComponentConfiguration): void; 24 | } 25 | -------------------------------------------------------------------------------- /test/viewer/Modes.test.ts: -------------------------------------------------------------------------------- 1 | import { State } from "../../src/state/State"; 2 | import { cameraControlsToState } from "../../src/viewer/Modes"; 3 | import { CameraControls } from "../../src/viewer/enums/CameraControls"; 4 | 5 | describe("cameraControlsToState", () => { 6 | it("converts to valid states", () => { 7 | expect(cameraControlsToState(CameraControls.Custom)) 8 | .toBe(State.Custom); 9 | expect(cameraControlsToState(CameraControls.Earth)) 10 | .toBe(State.Earth); 11 | expect(cameraControlsToState(CameraControls.Street)) 12 | .toBe(State.Traversing); 13 | expect(cameraControlsToState(-1)) 14 | .toBe(null); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/shader/shaders/texture.glsl.ts: -------------------------------------------------------------------------------- 1 | export const vertex = /* glsl */` 2 | #include 3 | #include 4 | 5 | void main() 6 | { 7 | #include 8 | #include 9 | } 10 | `; 11 | 12 | export const fragment = /* glsl */` 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #expand 19 | #expand 20 | #expand 21 | 22 | void main() 23 | { 24 | #include 25 | #expand 26 | #include 27 | #include 28 | } 29 | `; 30 | -------------------------------------------------------------------------------- /src/viewer/KeyboardService.ts: -------------------------------------------------------------------------------- 1 | import { 2 | fromEvent as observableFromEvent, 3 | Observable, 4 | } from "rxjs"; 5 | 6 | export class KeyboardService { 7 | private _keyDown$: Observable; 8 | private _keyUp$: Observable; 9 | 10 | constructor(canvasContainer: HTMLElement) { 11 | this._keyDown$ = observableFromEvent(canvasContainer, "keydown"); 12 | this._keyUp$ = observableFromEvent(canvasContainer, "keyup"); 13 | } 14 | 15 | public get keyDown$(): Observable { 16 | return this._keyDown$; 17 | } 18 | 19 | public get keyUp$(): Observable { 20 | return this._keyUp$; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/state/TransitionMode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enumeration for transition mode 3 | * @enum {number} 4 | * @readonly 5 | * @description Modes for specifying how transitions 6 | * between images are performed. 7 | */ 8 | export enum TransitionMode { 9 | /** 10 | * Default transitions. 11 | * 12 | * @description The viewer dynamically determines 13 | * whether transitions should be performed with or 14 | * without motion and blending for each transition 15 | * based on the underlying data. 16 | */ 17 | Default, 18 | 19 | /** 20 | * Instantaneous transitions. 21 | * 22 | * @description All transitions are performed 23 | * without motion or blending. 24 | */ 25 | Instantaneous, 26 | } 27 | -------------------------------------------------------------------------------- /test/helper/DOMRendererMockCreator.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from "rxjs"; 2 | import { DOMRenderer } from "../../src/render/DOMRenderer"; 3 | import { VirtualNodeHash } from "../../src/render/interfaces/VirtualNodeHash"; 4 | 5 | import { MockCreator } from "./MockCreator"; 6 | import { MockCreatorBase } from "./MockCreatorBase"; 7 | 8 | export class DOMRendererMockCreator extends MockCreatorBase { 9 | public create(): DOMRenderer { 10 | const mock: DOMRenderer = new MockCreator().create(DOMRenderer, "DOMRenderer"); 11 | 12 | this._mockProperty(mock, "element$", new Subject()); 13 | this._mockProperty(mock, "render$", new Subject()); 14 | 15 | return mock; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/helper/TestImage.ts: -------------------------------------------------------------------------------- 1 | import { Image } from "../../src/graph/Image"; 2 | import { MeshContract } from "../../src/api/contracts/MeshContract"; 3 | import { CoreImageEnt } from "../../src/api/ents/CoreImageEnt"; 4 | 5 | 6 | export class TestImage extends Image { 7 | private _mesh: MeshContract; 8 | 9 | constructor(core: CoreImageEnt) { 10 | super(core); 11 | } 12 | 13 | public get assetsCached(): boolean { 14 | return true; 15 | } 16 | 17 | public get image(): HTMLImageElement { 18 | return null; 19 | } 20 | 21 | public get mesh(): MeshContract { 22 | return this._mesh; 23 | } 24 | 25 | public set mesh(value: MeshContract) { 26 | this._mesh = value; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/api/provider/GraphEnts.ts: -------------------------------------------------------------------------------- 1 | import { IDEnt } from "../ents/IDEnt"; 2 | import { SpatialImageEnt } from "../ents/SpatialImageEnt"; 3 | import { URLEnt } from "../ents/URLEnt"; 4 | 5 | export interface GraphGeometry { coordinates: [number, number]; } 6 | 7 | export interface GraphCoreImageEnt extends IDEnt { 8 | computed_geometry: GraphGeometry; 9 | geometry: GraphGeometry; 10 | sequence: string; 11 | } 12 | 13 | export interface GraphSpatialImageEnt extends SpatialImageEnt { 14 | merge_cc: number; 15 | organization: IDEnt; 16 | sfm_cluster: URLEnt; 17 | thumb_1024_url: string; 18 | thumb_2048_url: string; 19 | } 20 | 21 | export interface GraphImageEnt extends 22 | GraphCoreImageEnt, 23 | GraphSpatialImageEnt { } 24 | -------------------------------------------------------------------------------- /src/component/spatial/SpatialCommon.ts: -------------------------------------------------------------------------------- 1 | import { LngLatAlt } from "../../api/interfaces/LngLatAlt"; 2 | import { enuToGeodetic, geodeticToEnu } from "../../geo/GeoCoords"; 3 | 4 | export const SPATIAL_DEFAULT_COLOR = 0xFFFFFF; 5 | 6 | export function resetEnu(reference: LngLatAlt, prevEnu: number[], prevReference: LngLatAlt): number[] { 7 | const [prevX, prevY, prevZ] = prevEnu; 8 | const [lng, lat, alt] = enuToGeodetic( 9 | prevX, 10 | prevY, 11 | prevZ, 12 | prevReference.lng, 13 | prevReference.lat, 14 | prevReference.alt); 15 | 16 | return geodeticToEnu( 17 | lng, 18 | lat, 19 | alt, 20 | reference.lng, 21 | reference.lat, 22 | reference.alt); 23 | } 24 | -------------------------------------------------------------------------------- /test/helper/PanServiceMockCreator.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from "rxjs"; 2 | 3 | import { MockCreator } from "./MockCreator"; 4 | import { MockCreatorBase } from "./MockCreatorBase"; 5 | 6 | import { Transform } from "../../src/geo/Transform"; 7 | import { Image } from "../../src/graph/Image"; 8 | import { PanService } from "../../src/viewer/PanService"; 9 | 10 | export class PanServiceMockCreator extends MockCreatorBase { 11 | public create(): PanService { 12 | const mock: PanService = 13 | new MockCreator().create(PanService, "PanService"); 14 | 15 | this._mockProperty( 16 | mock, 17 | "panImages$", 18 | new Subject<[Image, Transform]>()); 19 | 20 | return mock; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /types/s2-geometry/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "s2-geometry" { 2 | export module S2 { 3 | interface ILatLng { 4 | lat: number; 5 | lng: number; 6 | } 7 | 8 | function latLngToNeighborKeys(lat: number, lng: number, level: number): string[]; 9 | 10 | function latLngToKey(lat: number, lng: number, level: number): string; 11 | function keyToId(key: string): string; 12 | 13 | function idToLatLng(id: string): ILatLng; 14 | function idToKey(id: string): string; 15 | function keyToLatLng(key: string): ILatLng; 16 | 17 | class S2Cell { 18 | static FromHilbertQuadKey(key: string): S2Cell; 19 | getCornerLatLngs(): ILatLng[]; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/component/util/ComponentSize.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enumeration for component size. 3 | * @enum {number} 4 | * @readonly 5 | * @description May be used by a component to allow for resizing 6 | * of the UI elements rendered by the component. 7 | */ 8 | export enum ComponentSize { 9 | /** 10 | * Automatic size. The size of the elements will automatically 11 | * change at a predefined threshold. 12 | */ 13 | Automatic, 14 | 15 | /** 16 | * Large size. The size of the elements will be fixed until another 17 | * component size is configured. 18 | */ 19 | Large, 20 | 21 | /** 22 | * Small size. The size of the elements will be fixed until another 23 | * component size is configured. 24 | */ 25 | Small, 26 | } 27 | -------------------------------------------------------------------------------- /src/component/slider/shaders/perspective_distorted_curtain.fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export const perspectiveDistortedCurtainFrag = ` 2 | #ifdef GL_FRAGMENT_PRECISION_HIGH 3 | precision highp float; 4 | #else 5 | precision mediump float; 6 | #endif 7 | uniform sampler2D projectorTex; 8 | uniform float opacity; 9 | uniform float curtain; 10 | varying vec4 vRstq; 11 | void main() 12 | { 13 | float u = vRstq.x / vRstq.w; 14 | float v = vRstq.y / vRstq.w; 15 | vec4 baseColor; 16 | if ((u < curtain || curtain >= 1.0) && u >= 0. && u <= 1. && v >= 0. && v <= 1.) { 17 | baseColor = texture2D(projectorTex, vec2(u, v)); 18 | baseColor.a = opacity; 19 | } else { 20 | baseColor = vec4(0.0, 0.0, 0.0, 0.0); 21 | } 22 | gl_FragColor = baseColor; 23 | } 24 | ` 25 | -------------------------------------------------------------------------------- /src/component/spatial/scene/SpatialOctreeMath.ts: -------------------------------------------------------------------------------- 1 | // Level 0: 1 x 1 x 1 meter cubes 2 | export const OCTREE_ROOT_LEVEL = 14; // 16384 meters 3 | export const OCTREE_LEAF_LEVEL = 6; // 64 meters 4 | 5 | export function isLeafLevel(level: number, leafLevel: number): boolean { 6 | return level === leafLevel; 7 | } 8 | 9 | export function levelToSize(level: number): number { 10 | return 2 ** level; 11 | } 12 | 13 | export interface OctreeBoundingBox { 14 | min: number[]; 15 | max: number[]; 16 | } 17 | 18 | export function levelToRootBoundingBox(level: number): OctreeBoundingBox { 19 | const size = levelToSize(level); 20 | const half = size / 2; 21 | const min = [-half, -half, -half]; 22 | const max = [half, half, half]; 23 | return { min, max }; 24 | } 25 | -------------------------------------------------------------------------------- /src/graph/interfaces/GraphConfiguration.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface for graph configuration. 3 | * 4 | * @interface GraphConfiguration 5 | */ 6 | export interface GraphConfiguration { 7 | /** 8 | * The maximum number of cached sequences left 9 | * after uncache. 10 | */ 11 | maxSequences: number; 12 | 13 | /** 14 | * The maximum number of unused cached images left 15 | * after uncache. 16 | */ 17 | maxUnusedImages: number; 18 | 19 | /** 20 | * The maximum number of unused pre-stored cached images left 21 | * after uncache. 22 | */ 23 | maxUnusedPreStoredImages: number; 24 | 25 | /** 26 | * The maximum number of unused cached tiles left 27 | * after uncache. 28 | */ 29 | maxUnusedTiles: number; 30 | } 31 | -------------------------------------------------------------------------------- /src/util/DOM.ts: -------------------------------------------------------------------------------- 1 | export class DOM { 2 | private _document: HTMLDocument; 3 | 4 | constructor(doc?: Node) { 5 | this._document = !!doc ? doc : document; 6 | } 7 | 8 | public get document(): HTMLDocument { 9 | return this._document; 10 | } 11 | 12 | public createElement( 13 | tagName: K, className?: string, container?: HTMLElement): HTMLElementTagNameMap[K] { 14 | const element: HTMLElementTagNameMap[K] = this._document.createElement(tagName); 15 | 16 | if (!!className) { 17 | element.className = className; 18 | } 19 | 20 | if (!!container) { 21 | container.appendChild(element); 22 | } 23 | 24 | return element; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /styles/mapillary.css: -------------------------------------------------------------------------------- 1 | .mapillary-viewer { 2 | background-color: #0F0F0F; 3 | position: relative; 4 | overflow: hidden; 5 | -webkit-tap-highlight-color: rgba(0,0,0,0); 6 | } 7 | 8 | .mapillary-interactive { 9 | cursor: grab; 10 | } 11 | 12 | .mapillary-interactive:active { 13 | cursor: grabbing; 14 | } 15 | 16 | .mapillary-viewer .mapillary-dom { 17 | bottom: 0; 18 | left: 0; 19 | overflow: hidden; 20 | pointer-events: none; 21 | position: absolute; 22 | right: 0; 23 | top: 0; 24 | user-select: none; 25 | } 26 | 27 | .mapillary-dom .mapillary-dom-renderer { 28 | pointer-events: auto; 29 | } 30 | 31 | .mapillary-viewer div { 32 | box-sizing: content-box; 33 | } 34 | 35 | .mapillary-viewer input:focus { 36 | background: none; 37 | } 38 | -------------------------------------------------------------------------------- /doc/src/pages/examples/support.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/support'; 15 | 16 | export default function Example() { 17 | const title = 'Support'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/component/spatial/scene/SpatialAssets.ts: -------------------------------------------------------------------------------- 1 | import { CameraVisualizationMode } from "../enums/CameraVisualizationMode"; 2 | 3 | export class SpatialAssets { 4 | private readonly _colors: Map; 5 | 6 | constructor() { 7 | this._colors = new Map(); 8 | const cvm = CameraVisualizationMode; 9 | this._colors.set(cvm[cvm.Homogeneous], "#FFFFFF"); 10 | } 11 | 12 | public getColor(id: string): number | string { 13 | const colors = this._colors; 14 | if (!colors.has(id)) { 15 | colors.set(id, this._randomColor()); 16 | } 17 | return colors.get(id); 18 | } 19 | 20 | private _randomColor(): number | string { 21 | return `hsl(${Math.floor(360 * Math.random())}, 100%, 60%)`; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/component/interfaces/MarkerConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { ComponentConfiguration } from "./ComponentConfiguration"; 2 | 3 | /** 4 | * Interface for configuration of marker component. 5 | * 6 | * @interface 7 | * @example 8 | * ```js 9 | * var viewer = new Viewer({ 10 | * ... 11 | * component: { 12 | * marker: { 13 | * visibleBBoxSize: 80, 14 | * }, 15 | * }, 16 | * ... 17 | * }); 18 | * ``` 19 | */ 20 | export interface MarkerConfiguration extends ComponentConfiguration { 21 | /** 22 | * The size of the bounding box for which markers will be visible. 23 | * 24 | * @description Provided values will be clamped to the [1, 200] 25 | * interval. 26 | * 27 | * @default 100 28 | */ 29 | visibleBBoxSize?: number; 30 | } 31 | -------------------------------------------------------------------------------- /doc/static/img/examples/scale.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/src/js/options/FunctionController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import {Controller} from './Controller'; 11 | 12 | export class FunctionController extends Controller { 13 | constructor(object, property) { 14 | super(object, property); 15 | 16 | this.container.classList.add('function'); 17 | 18 | this._onChange = this.object[this.property]; 19 | 20 | this.container.addEventListener('click', (event) => { 21 | event.preventDefault(); 22 | this.fire(); 23 | }); 24 | } 25 | 26 | fire() { 27 | if (this._onChange) { 28 | this._onChange(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /doc/src/pages/examples/component-tag.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/component-tag'; 15 | 16 | export default function Example() { 17 | const title = 'Component Tag'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/extend-editor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/extend-editor'; 15 | 16 | export default function Example() { 17 | const title = 'Extend Editor'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/viewer-events.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/viewer-events'; 15 | 16 | export default function Example() { 17 | const title = 'Viewer Events'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/viewer-filters.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/viewer-filters'; 15 | 16 | export default function Example() { 17 | const title = 'Viewer Filters'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/viewer-methods.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/viewer-methods'; 15 | 16 | export default function Example() { 17 | const title = 'Viewer Methods'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/viewer-options.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/viewer-options'; 15 | 16 | export default function Example() { 17 | const title = 'Viewer Options'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/viewer-to-map.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/viewer-to-map'; 15 | 16 | export default function Example() { 17 | const title = 'Viewer To Map'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /test/helper/PlayServiceMockCreator.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from "rxjs"; 2 | import { NavigationDirection } from "../../src/graph/edge/NavigationDirection"; 3 | import { PlayService } from "../../src/viewer/PlayService"; 4 | 5 | import { MockCreator } from "./MockCreator"; 6 | import { MockCreatorBase } from "./MockCreatorBase"; 7 | 8 | export class PlayServiceMockCreator extends MockCreatorBase { 9 | public create(): PlayService { 10 | const mock: PlayService = new MockCreator().create(PlayService, "PlayService"); 11 | 12 | this._mockProperty(mock, "direction$", new Subject()); 13 | this._mockProperty(mock, "playing$", new Subject()); 14 | this._mockProperty(mock, "speed$", new Subject()); 15 | 16 | return mock; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/helper/TestComponent.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "../../src/component/Component"; 2 | import { ComponentConfiguration } from "../../src/component/interfaces/ComponentConfiguration"; 3 | import { Container } from "../../src/viewer/Container"; 4 | import { Navigator } from "../../src/viewer/Navigator"; 5 | 6 | export interface TestConfiguration extends ComponentConfiguration { 7 | test: boolean; 8 | } 9 | 10 | export class TestComponent extends Component { 11 | constructor(name: string, container: Container, navigator: Navigator) { 12 | super(name, container, navigator); 13 | } 14 | protected _activate(): void { /* noop */ } 15 | protected _deactivate(): void { /* noop */ } 16 | protected _getDefaultConfiguration(): TestConfiguration { return { test: false }; } 17 | } 18 | -------------------------------------------------------------------------------- /doc/src/pages/examples/component-popup.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/component-popup'; 15 | 16 | export default function Example() { 17 | const title = 'Component Popup'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/extend-map-sync.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/extend-map-sync'; 15 | 16 | export default function Example() { 17 | const title = 'Extend Map Sync'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/viewer-from-map.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/viewer-from-map'; 15 | 16 | export default function Example() { 17 | const title = 'Viewer From Map'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/docs/main/guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: guide 3 | title: Guide 4 | --- 5 | 6 | Our guide to main concepts is the best place to start to learn how to develop applications using MapillaryJS step by step. Every next chapter in it builds on the knowledge introduced in the previous chapters. By the end of this section, you will be able to use the viewer and component APIs to control the MapillaryJS behavior according to your application's use case. 7 | 8 | :::info You will learn 9 | 10 | - [How to initialize the viewer with different behaviors and appearances](/docs/main/init) 11 | - [How to control the viewer's behavior and appearance after initialization](/docs/main/control) 12 | - [How to listen to and handle viewer events](/docs/main/event) 13 | - [How to work with component APIs and component events](/docs/main/component) 14 | 15 | ::: 16 | -------------------------------------------------------------------------------- /doc/src/pages/examples/component-marker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/component-marker'; 15 | 16 | export default function Example() { 17 | const title = 'Component Marker'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/component-pointer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/component-pointer'; 15 | 16 | export default function Example() { 17 | const title = 'Component Pointer'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/component-spatial.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/component-spatial'; 15 | 16 | export default function Example() { 17 | const title = 'Component Spatial'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/extend-animation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/extend-animation'; 15 | 16 | export default function Example() { 17 | const title = 'Extend Animation'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/state/interfaces/IAnimationState.ts: -------------------------------------------------------------------------------- 1 | import { State } from "../State"; 2 | import { Camera } from "../../geo/Camera"; 3 | import { Transform } from "../../geo/Transform"; 4 | import { LngLatAlt } from "../../api/interfaces/LngLatAlt"; 5 | import { Image } from "../../graph/Image"; 6 | 7 | export interface IAnimationState { 8 | alpha: number; 9 | camera: Camera; 10 | currentCamera: Camera; 11 | currentImage: Image; 12 | currentIndex: number; 13 | currentTransform: Transform; 14 | imagesAhead: number; 15 | lastImage: Image; 16 | motionless: boolean; 17 | previousCamera: Camera; 18 | previousImage: Image; 19 | previousTransform: Transform; 20 | reference: LngLatAlt; 21 | state: State; 22 | stateTransitionAlpha: number; 23 | trajectory: Image[]; 24 | zoom: number; 25 | } 26 | -------------------------------------------------------------------------------- /src/viewer/enums/Alignment.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enumeration for alignments 3 | * @enum {number} 4 | * @readonly 5 | */ 6 | export enum Alignment { 7 | /** 8 | * Align to bottom 9 | */ 10 | Bottom, 11 | 12 | /** 13 | * Align to bottom left 14 | */ 15 | BottomLeft, 16 | 17 | /** 18 | * Align to bottom right 19 | */ 20 | BottomRight, 21 | 22 | /** 23 | * Align to center 24 | */ 25 | Center, 26 | 27 | /** 28 | * Align to left 29 | */ 30 | Left, 31 | 32 | /** 33 | * Align to right 34 | */ 35 | Right, 36 | 37 | /** 38 | * Align to top 39 | */ 40 | Top, 41 | 42 | /** 43 | * Align to top left 44 | */ 45 | TopLeft, 46 | 47 | /** 48 | * Align to top right 49 | */ 50 | TopRight, 51 | } 52 | -------------------------------------------------------------------------------- /doc/src/pages/examples/component-keyboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/component-keyboard'; 15 | 16 | export default function Example() { 17 | const title = 'Component Keyboard'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/component-popup-tag.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/component-popup-tag'; 15 | 16 | export default function Example() { 17 | const title = 'Component Popup-Tag'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/extend-fly-controls.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/extend-fly-controls'; 15 | 16 | export default function Example() { 17 | const title = 'Extend Fly Controls'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/viewer-coordinates.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/viewer-coordinates'; 15 | 16 | export default function Example() { 17 | const title = 'Viewer Coordinates'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/component-marker-map.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/component-marker-map'; 15 | 16 | export default function Example() { 17 | const title = 'Component Marker Map'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/component-tag-create.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/component-tag-create'; 15 | 16 | export default function Example() { 17 | const title = 'Component Tag Create'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/static/img/examples/translate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/src/pages/examples/component-tag-interact.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/component-tag-interact'; 15 | 16 | export default function Example() { 17 | const title = 'Component Tag Interact'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/extend-three-renderer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/extend-three-renderer'; 15 | 16 | export default function Example() { 17 | const title = 'Extend Three Renderer'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/extend-webgl-renderer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/extend-webgl-renderer'; 15 | 16 | export default function Example() { 17 | const title = 'Extend WebGL Renderer'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/component-marker-million.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/component-marker-million'; 15 | 16 | export default function Example() { 17 | const title = 'Component Marker Million'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/extend-graphics-developer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/extend-graphics-developer'; 15 | 16 | export default function Example() { 17 | const title = 'Extend Graphics Developer'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /doc/src/pages/examples/viewer-initialization.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/viewer-initialization'; 15 | 16 | export default function Example() { 17 | const title = 'Viewer Initialization'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/viewer/events/ViewerLoadEvent.ts: -------------------------------------------------------------------------------- 1 | import { ViewerEvent } from "./ViewerEvent"; 2 | 3 | /** 4 | * Interface for viewer load events. 5 | * 6 | * @description Fired immediately after all necessary resources 7 | * have been downloaded and the first visually complete 8 | * rendering of the viewer has occurred. 9 | * 10 | * The visually complete rendering does not include custom 11 | * renderers. 12 | * 13 | * This event is only fired for viewer configurations where 14 | * the WebGL context is created, i.e. not when using the 15 | * fallback functionality only. 16 | * 17 | * @example 18 | * ```js 19 | * // Set up an event listener on the viewer. 20 | * viewer.on('load', function(e) { 21 | * console.log('A load event has occured'); 22 | * }); 23 | * ``` 24 | */ 25 | export interface ViewerLoadEvent extends ViewerEvent { 26 | type: "load"; 27 | } 28 | -------------------------------------------------------------------------------- /doc/src/pages/examples/extend-procedural-data-provider.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import Layout from '@theme/Layout'; 12 | import {Code} from '../../js/components/Code'; 13 | import {ViewerComponent} from '../../js/components/ViewerComponent'; 14 | import {dispose, init} from '../../js/examples/extend-procedural-data-provider'; 15 | 16 | export default function Example() { 17 | const title = 'Extend Procedural Data Provider'; 18 | return ( 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/component/tag/interfaces/SpotTagOptions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface for the options that define the behavior and 3 | * appearance of the spot tag. 4 | * 5 | * @interface 6 | */ 7 | export interface SpotTagOptions { 8 | /** 9 | * Color for the spot specified as a hexadecimal number. 10 | * @default 0xFFFFFF 11 | */ 12 | color?: number; 13 | 14 | /** 15 | * Indicate whether the tag geometry should be editable. 16 | * @default false 17 | */ 18 | editable?: boolean; 19 | 20 | /** 21 | * A string referencing the sprite data property to pull from. 22 | */ 23 | icon?: string; 24 | 25 | /** 26 | * Text shown as label if no icon is provided. 27 | */ 28 | text?: string; 29 | 30 | /** 31 | * Text color as hexadecimal number. 32 | * @default 0xFFFFFF 33 | */ 34 | textColor?: number; 35 | } 36 | -------------------------------------------------------------------------------- /test/helper/GLRendererMockCreator.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from "rxjs"; 2 | import { GLRenderer } from "../../src/render/GLRenderer"; 3 | import { GLRenderHash } from "../../src/render/interfaces/IGLRenderHash"; 4 | 5 | import { MockCreator } from "./MockCreator"; 6 | import { MockCreatorBase } from "./MockCreatorBase"; 7 | 8 | export class GLRendererMockCreator extends MockCreatorBase { 9 | public create(): GLRenderer { 10 | const mock = new MockCreator().create(GLRenderer, "GLRenderer"); 11 | 12 | this._mockProperty(mock, "webGLRenderer$", new Subject()); 13 | this._mockProperty(mock, "render$", new Subject()); 14 | this._mockProperty(mock, "opaqueRender$", new Subject()); 15 | this._mockProperty(mock, "transparentRender$", new Subject()); 16 | 17 | return mock; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/helper/ConfigurationServiceMockCreator.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from "rxjs"; 2 | 3 | import { MockCreator } from "./MockCreator"; 4 | import { MockCreatorBase } from "./MockCreatorBase"; 5 | 6 | import { ConfigurationService } from "../../src/viewer/ConfigurationService"; 7 | 8 | export class ConfigurationServiceMockCreator extends 9 | MockCreatorBase { 10 | public create(): ConfigurationService { 11 | const mock: ConfigurationService = 12 | new MockCreator() 13 | .create(ConfigurationService, "ConfigurationService"); 14 | 15 | this._mockProperty( 16 | mock, 17 | "exploreUrl$", 18 | new Subject()); 19 | this._mockProperty( 20 | mock, 21 | "imageTiling$", 22 | new Subject()); 23 | 24 | return mock; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 11 | 12 | ## Motivation 13 | 14 | (Write your motivation here.) 15 | 16 | ### Have you read the [Contributing Guidelines](https://github.com/mapillary/mapillary-js/blob//main/.github/CONTRIBUTING.md)? 17 | 18 | (Write your answer here.) 19 | 20 | ## Contribution 21 | 22 | (If this PR adds or changes functionality, describe it here.) 23 | 24 | ## Test Plan 25 | 26 | (Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.) 27 | -------------------------------------------------------------------------------- /src/component/interfaces/NavigationFallbackConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { ComponentConfiguration } from "./ComponentConfiguration"; 2 | 3 | /** 4 | * Interface for configuration of navigation component. 5 | * 6 | * @interface 7 | * @example 8 | * ```js 9 | * var viewer = new Viewer({ 10 | * ... 11 | * component: { 12 | * fallback: { 13 | * navigation: { 14 | * spatial: false, 15 | * }, 16 | * }, 17 | * }, 18 | * ... 19 | * }); 20 | * ``` 21 | */ 22 | export interface NavigationFallbackConfiguration 23 | extends ComponentConfiguration { 24 | /** 25 | * Enable or disable the sequence arrows. 26 | * 27 | * @default true 28 | */ 29 | sequence?: boolean; 30 | 31 | /** 32 | * Enable or disable the spatial arrows. 33 | * 34 | * @default true 35 | */ 36 | spatial?: boolean; 37 | } 38 | -------------------------------------------------------------------------------- /src/viewer/options/FallbackOptions.ts: -------------------------------------------------------------------------------- 1 | import { NavigationFallbackConfiguration } 2 | from "../../component/interfaces/NavigationFallbackConfiguration"; 3 | 4 | /** 5 | * Interface for the fallback component options that can be 6 | * provided to the viewer when the browser does not have 7 | * WebGL support. 8 | * 9 | * @interface 10 | */ 11 | export interface FallbackOptions { 12 | 13 | /** 14 | * Show static images without pan, zoom, or transitions. 15 | * 16 | * @description Fallback for `image` when WebGL is not supported. 17 | * 18 | * @default false 19 | */ 20 | image?: boolean; 21 | 22 | /** 23 | * Show static navigation arrows in the corners. 24 | * 25 | * @description Fallback for `direction` and `sequence` when WebGL is not supported. 26 | * 27 | * @default false 28 | */ 29 | navigation?: boolean | NavigationFallbackConfiguration; 30 | } 31 | -------------------------------------------------------------------------------- /src/component/tag/handlers/CreatePointsHandler.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from "rxjs"; 2 | import { Transform } from "../../../geo/Transform"; 3 | import { ExtremePointCreateTag } from "../tag/ExtremePointCreateTag"; 4 | import { CreateVertexHandler } from "./CreateVertexHandler"; 5 | 6 | export class CreatePointsHandler extends CreateVertexHandler { 7 | protected get _create$(): Subject { 8 | return this._tagCreator.createPoints$; 9 | } 10 | 11 | protected _addPoint(tag: ExtremePointCreateTag, basicPoint: number[]): void { 12 | tag.geometry.addPoint2d(basicPoint); 13 | } 14 | 15 | protected _getNameExtension(): string { 16 | return "create-points"; 17 | } 18 | 19 | protected _setVertex2d(tag: ExtremePointCreateTag, basicPoint: number[], transform: Transform): void { 20 | tag.geometry.setPoint2d((tag.geometry).points.length - 1, basicPoint, transform); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/graph/GraphMode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enumeration for graph modes. 3 | * @enum {number} 4 | * @readonly 5 | * @description Modes for the retrieval and caching performed 6 | * by the graph service on the graph. 7 | */ 8 | export enum GraphMode { 9 | /** 10 | * Caching is performed on sequences only and sequence edges are 11 | * calculated. Spatial tiles 12 | * are not retrieved and spatial edges are not calculated when 13 | * caching nodes. Complete sequences are being cached for requested 14 | * nodes within the graph. 15 | */ 16 | Sequence, 17 | 18 | /** 19 | * Caching is performed with emphasis on spatial data. Sequence edges 20 | * as well as spatial edges are cached. Sequence data 21 | * is still requested but complete sequences are not being cached 22 | * for requested nodes. 23 | * 24 | * This is the initial mode of the graph service. 25 | */ 26 | Spatial, 27 | } 28 | -------------------------------------------------------------------------------- /src/component/events/ComponentStateEvent.ts: -------------------------------------------------------------------------------- 1 | import { IComponent } from "../interfaces/IComponent"; 2 | import { Marker } from "../marker/marker/Marker"; 3 | import { Geometry } from "../tag/geometry/Geometry"; 4 | import { TagMode } from "../tag/TagMode"; 5 | import { ComponentEvent } from "./ComponentEvent"; 6 | import { ComponentEventType } from "./ComponentEventType"; 7 | 8 | /** 9 | * Interface for component state events. 10 | * 11 | * @example 12 | * ```js 13 | * // The `hover` event is an example of a `ComponentStateEvent`. 14 | * // Set up an event listener on the direction component. 15 | * var directionComponent = viewer.getComponent('direction'); 16 | * directionComponent.on('hover', function(e) { 17 | * console.log('A hover event has occured'); 18 | * }); 19 | * ``` 20 | */ 21 | export interface ComponentStateEvent extends ComponentEvent { 22 | type: 23 | | "tagcreateend" 24 | | "tagcreatestart" 25 | | "tags"; 26 | } 27 | -------------------------------------------------------------------------------- /src/component/tag/TagMode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enumeration for tag modes 3 | * @enum {number} 4 | * @readonly 5 | * @description Modes for the interaction in the tag component. 6 | */ 7 | export enum TagMode { 8 | /** 9 | * Disables creating tags. 10 | */ 11 | Default, 12 | 13 | /** 14 | * Create a point geometry through a click. 15 | */ 16 | CreatePoint, 17 | 18 | /** 19 | * Create a points geometry through clicks. 20 | */ 21 | CreatePoints, 22 | 23 | /** 24 | * Create a polygon geometry through clicks. 25 | */ 26 | CreatePolygon, 27 | 28 | /** 29 | * Create a rect geometry through clicks. 30 | */ 31 | CreateRect, 32 | 33 | /** 34 | * Create a rect geometry through drag. 35 | * 36 | * @description Claims the mouse which results in mouse handlers like 37 | * drag pan and scroll zoom becoming inactive. 38 | */ 39 | CreateRectDrag, 40 | } 41 | -------------------------------------------------------------------------------- /src/util/interfaces/IEventEmitter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface describing event emitter members. 3 | */ 4 | export interface IEventEmitter { 5 | /** 6 | * @ignore 7 | */ 8 | fire( 9 | type: string, 10 | event: T): void; 11 | 12 | /** 13 | * Unsubscribe from an event by its name. 14 | * @param {string} type - The name of the event 15 | * to unsubscribe from. 16 | * @param {(event: T) => void} handler - The 17 | * handler to remove. 18 | */ 19 | off( 20 | type: string, 21 | handler: (event: T) => void): void; 22 | 23 | /** 24 | * Subscribe to an event by its name. 25 | * @param {string} type - The name of the event 26 | * to subscribe to. 27 | * @param {(event: T) => void} handler - The 28 | * handler called when the event occurs. 29 | */ 30 | on( 31 | type: string, 32 | handler: (event: T) => void): void; 33 | } 34 | -------------------------------------------------------------------------------- /test/helper/WebGLRenderer.ts: -------------------------------------------------------------------------------- 1 | export class RendererMock implements THREE.Renderer { 2 | public domElement: HTMLCanvasElement = document.createElement("canvas"); 3 | 4 | public clear(): void { /* noop */; } 5 | public clearDepth(): void { /* noop */ } 6 | public getContext(): void { /* noop */ } 7 | public getRenderTarget(): THREE.WebGLRenderTarget { return; } 8 | public render( 9 | s: THREE.Scene, 10 | c: THREE.Camera, 11 | t?: THREE.WebGLRenderTarget) 12 | : void { /* noop */ } 13 | public resetState(): void { /* noop */ } 14 | public setClearColor( 15 | color: THREE.Color | string | number, 16 | alpha?: number): void { /* noop */ } 17 | public setPixelRatio(ratio: number): void { /* noop */ } 18 | public setRenderTarget(): void { /* noop */ } 19 | public setSize( 20 | w: number, 21 | h: number, 22 | updateStyle?: boolean): void { /* noop */ } 23 | } 24 | -------------------------------------------------------------------------------- /test/helper/MockCreator.ts: -------------------------------------------------------------------------------- 1 | export class MockCreator { 2 | public create(ctor: new (...args: any[]) => T, name: string): T { 3 | const spy: { [key: string]: any } = {}; 4 | 5 | for (const key in ctor.prototype) { 6 | if (!!Object.getOwnPropertyDescriptor(ctor.prototype, key) && 7 | !Object.getOwnPropertyDescriptor(ctor.prototype, key).get) { 8 | spy[key] = jasmine.createSpy(name + "." + key, ctor.prototype[key]); 9 | } 10 | } 11 | 12 | return spy; 13 | } 14 | 15 | public mockProperty(instance: T, propertyName: string, propertyValue: U): T { 16 | Object.defineProperty( 17 | instance, 18 | propertyName, 19 | { 20 | get: (): U => { return propertyValue; }, 21 | set: (value: U): void => { propertyValue = value; }, 22 | }); 23 | 24 | return instance; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/helper/TransformHelper.ts: -------------------------------------------------------------------------------- 1 | import { ImageHelper } from "./ImageHelper"; 2 | import { Transform } from "../../src/geo/Transform"; 3 | import { CameraType } from "../../src/geo/interfaces/CameraType"; 4 | import { ProjectionService } from "../../src/viewer/ProjectionService"; 5 | 6 | export class TransformHelper { 7 | private _imageHelper: ImageHelper = new ImageHelper(); 8 | 9 | public createTransform( 10 | cameraType: CameraType = "perspective"): Transform { 11 | 12 | const image = this._imageHelper 13 | .createImage(cameraType); 14 | const camera = new ProjectionService() 15 | .makeCamera(cameraType, image.cameraParameters); 16 | 17 | return new Transform( 18 | image.exifOrientation, 19 | image.width, 20 | image.height, 21 | image.scale, 22 | image.rotation, 23 | [0, 0, 0], 24 | null, 25 | camera); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /doc/src/js/options/Controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | export class Controller { 11 | constructor(object, property) { 12 | this.object = object; 13 | this.property = property; 14 | 15 | this.name = document.createElement('span'); 16 | this.name.textContent = property; 17 | 18 | this.container = document.createElement('div'); 19 | this.container.classList.add('controller'); 20 | this.container.appendChild(this.name); 21 | 22 | this._onChange = null; 23 | } 24 | 25 | getValue() { 26 | return this.object[this.property]; 27 | } 28 | 29 | onChange(handler) { 30 | this._onChange = handler; 31 | return this; 32 | } 33 | 34 | setName(name) { 35 | this.name.textContent = name; 36 | return this; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/render/RenderMode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enumeration for render mode 3 | * @enum {number} 4 | * @readonly 5 | * @description Modes for specifying how rendering is done 6 | * in the viewer. All modes preserves the original aspect 7 | * ratio of the images. 8 | */ 9 | export enum RenderMode { 10 | 11 | /** 12 | * Displays all content within the viewer. 13 | * 14 | * @description Black bars shown on both 15 | * sides of the content. Bars are shown 16 | * either below and above or to the left 17 | * and right of the content depending on 18 | * the aspect ratio relation between the 19 | * image and the viewer. 20 | */ 21 | Letterbox, 22 | 23 | /** 24 | * Fills the viewer by cropping content. 25 | * 26 | * @description Cropping is done either 27 | * in horizontal or vertical direction 28 | * depending on the aspect ratio relation 29 | * between the image and the viewer. 30 | */ 31 | Fill, 32 | } 33 | -------------------------------------------------------------------------------- /src/geometry/interfaces/ICamera.ts: -------------------------------------------------------------------------------- 1 | export type CameraParameters = { [key: string]: number; }; 2 | 3 | export type CameraUniforms = { [key: string]: boolean | number | number[]; }; 4 | 5 | /** 6 | * @interface 7 | * 8 | * @description Interface for cameras. This is a 9 | * specification for implementers to model: it is not 10 | * an exported method or class. 11 | * 12 | * Implmenting a custom camera allows the implementer to 13 | * render textures and camera frustums with proper undistortion. 14 | * 15 | * Custom cameras must have a unique type. 16 | */ 17 | export interface ICamera { 18 | readonly type: string; 19 | 20 | readonly parameters: CameraParameters; 21 | readonly uniforms: CameraUniforms; 22 | 23 | readonly projectToSfmFunction: string; 24 | 25 | bearingFromSfm(point: number[]): number[]; 26 | projectToSfm(bearing: number[]): number[]; 27 | } 28 | 29 | export interface CameraConstructor { 30 | new(parameters: number[]): ICamera; 31 | }; 32 | -------------------------------------------------------------------------------- /src/component/popup/interfaces/PopupOffset.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface for the popup offset with respect to its anchor point. 3 | * 4 | * @description An object of number arrays specifying an offset for 5 | * each float direction. Negative offsets indicate left and up. 6 | * 7 | * @interface 8 | * 9 | * @example 10 | * ```js 11 | * var offset = = { 12 | * bottom: [0, 10], 13 | * bottomLeft: [-10, 10], 14 | * bottomRight: [10, 10], 15 | * center: [0, 0], 16 | * left: [-10, 0], 17 | * right: [10, 0], 18 | * top: [0, -10], 19 | * topLeft: [-10, -10], 20 | * topRight: [10, -10], 21 | * } 22 | * 23 | * var popup = new Popup({ offset: offset }); 24 | * ``` 25 | */ 26 | export interface PopupOffset { 27 | bottom: number[]; 28 | bottomLeft: number[]; 29 | bottomRight: number[]; 30 | center: number[]; 31 | left: number[]; 32 | right: number[]; 33 | top: number[]; 34 | topLeft: number[]; 35 | topRight: number[]; 36 | } 37 | -------------------------------------------------------------------------------- /src/component/tag/handlers/CreatePolygonHandler.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from "rxjs"; 2 | import { Transform } from "../../../geo/Transform"; 3 | import { PolygonGeometry } from "../geometry/PolygonGeometry"; 4 | import { OutlineCreateTag } from "../tag/OutlineCreateTag"; 5 | import { CreateVertexHandler } from "./CreateVertexHandler"; 6 | 7 | export class CreatePolygonHandler extends CreateVertexHandler { 8 | protected get _create$(): Subject { 9 | return this._tagCreator.createPolygon$; 10 | } 11 | 12 | protected _addPoint(tag: OutlineCreateTag, basicPoint: number[]): void { 13 | tag.addPoint(basicPoint); 14 | } 15 | 16 | protected _getNameExtension(): string { 17 | return "create-polygon"; 18 | } 19 | 20 | protected _setVertex2d(tag: OutlineCreateTag, basicPoint: number[], transform: Transform): void { 21 | tag.geometry.setVertex2d((tag.geometry).polygon.length - 2, basicPoint, transform); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/component/tag/tag/TagDomain.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enumeration for tag domains. 3 | * @enum {number} 4 | * @readonly 5 | * @description Defines where lines between two vertices are treated 6 | * as straight. 7 | * 8 | * Only applicable for polygons. For rectangles lines between 9 | * vertices are always treated as straight in the distorted 2D 10 | * projection and bended in the undistorted 3D space. 11 | */ 12 | export enum TagDomain { 13 | /** 14 | * Treats lines between two vertices as straight in the 15 | * distorted 2D projection, i.e. on the image. If the image 16 | * is distorted this will result in bended lines when rendered 17 | * in the undistorted 3D space. 18 | */ 19 | TwoDimensional, 20 | 21 | /** 22 | * Treats lines as straight in the undistorted 3D space. If the 23 | * image is distorted this will result in bended lines when rendered 24 | * on the distorted 2D projection of the image. 25 | */ 26 | ThreeDimensional, 27 | } 28 | -------------------------------------------------------------------------------- /src/viewer/ConfigurationService.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Observable, 3 | of as observableOf, 4 | } from "rxjs"; 5 | 6 | import { ViewerOptions } from "../external/viewer"; 7 | 8 | export class ConfigurationService { 9 | private _imageTiling$: Observable; 10 | private _exploreUrl$: Observable; 11 | 12 | constructor(options: ViewerOptions) { 13 | const host = options?.url?.exploreHost ?? "www.mapillary.com"; 14 | const scheme = options?.url?.scheme ?? "https"; 15 | const exploreUrl = `${scheme}://${host}`; 16 | this._exploreUrl$ = observableOf(exploreUrl); 17 | 18 | const imageTiling = options?.imageTiling === false ? false : true; 19 | this._imageTiling$ = observableOf(imageTiling); 20 | } 21 | 22 | public get exploreUrl$(): Observable { 23 | return this._exploreUrl$; 24 | } 25 | 26 | public get imageTiling$(): Observable { 27 | return this._imageTiling$; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/helper/RenderServiceMockCreator.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from "rxjs"; 2 | import { RenderCamera } from "../../src/render/RenderCamera"; 3 | import { RenderService } from "../../src/render/RenderService"; 4 | 5 | import { MockCreator } from "./MockCreator"; 6 | import { MockCreatorBase } from "./MockCreatorBase"; 7 | 8 | export class RenderServiceMockCreator extends MockCreatorBase { 9 | public create(): RenderService { 10 | const mock: RenderService = new MockCreator().create(RenderService, "RenderService"); 11 | 12 | this._mockProperty(mock, "bearing$", new Subject()); 13 | this._mockProperty(mock, "projectionMatrix$", new Subject()); 14 | this._mockProperty(mock, "renderCamera$", new Subject()); 15 | this._mockProperty(mock, "renderCameraFrame$", new Subject()); 16 | this._mockProperty(mock, "size$", new Subject()); 17 | 18 | return mock; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /doc/src/pages/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | /** 11 | * CSS files with the .module.css suffix will be treated as CSS modules 12 | * and scoped locally. 13 | */ 14 | 15 | .heroBanner { 16 | padding: 4rem 0; 17 | text-align: center; 18 | position: relative; 19 | overflow: hidden; 20 | } 21 | 22 | .heroBannerLogo { 23 | max-width: 150px; 24 | max-height: 150px; 25 | } 26 | 27 | @media screen and (max-width: 966px) { 28 | .heroBanner { 29 | padding: 2rem; 30 | } 31 | } 32 | 33 | .buttons { 34 | display: flex; 35 | align-items: center; 36 | justify-content: center; 37 | } 38 | 39 | .features { 40 | display: flex; 41 | align-items: center; 42 | padding: 2rem 0; 43 | width: 100%; 44 | } 45 | 46 | .featureImage { 47 | height: 200px; 48 | max-width: 300px; 49 | } 50 | -------------------------------------------------------------------------------- /src/api/ents/CameraEnt.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Ent representing camera properties. 3 | */ 4 | export interface CameraEnt { 5 | /** 6 | * Camera type dependent camera parameters. 7 | * 8 | * For perspective and fisheye camera types, 9 | * the camera parameters array should be 10 | * constructed according to 11 | * 12 | * `[focal, k1, k2]` 13 | * 14 | * where focal is the camera focal length, 15 | * and k1, k2 are radial distortion parameters. 16 | * 17 | * For spherical camera type the camera 18 | * parameters should be an emtpy array. 19 | */ 20 | camera_parameters: number[]; 21 | 22 | /** 23 | * Projection type of the camera. 24 | * 25 | * @description Supported camera types are: 26 | * 27 | * ```js 28 | * 'spherical' 29 | * 'fisheye' 30 | * 'perspective' 31 | * ``` 32 | * 33 | * Other camera types will be treated as 34 | * perspective images. 35 | */ 36 | camera_type: string; 37 | } 38 | -------------------------------------------------------------------------------- /test/helper/GraphServiceMockCreator.ts: -------------------------------------------------------------------------------- 1 | import { Subject } from "rxjs"; 2 | 3 | import { MockCreator } from "./MockCreator"; 4 | import { MockCreatorBase } from "./MockCreatorBase"; 5 | 6 | import { FilterFunction } from "../../src/graph/FilterCreator"; 7 | import { GraphMode } from "../../src/graph/GraphMode"; 8 | import { GraphService } from "../../src/graph/GraphService"; 9 | 10 | export class GraphServiceMockCreator extends MockCreatorBase { 11 | public create(): GraphService { 12 | const mock: GraphService = new MockCreator().create(GraphService, "GraphService"); 13 | 14 | this._mockProperty(mock, "dataAdded$", new Subject()); 15 | this._mockProperty(mock, "dataDeleted$", new Subject()); 16 | this._mockProperty(mock, "dataReset$", new Subject()); 17 | this._mockProperty(mock, "graphMode$", new Subject()); 18 | this._mockProperty(mock, "filter$", new Subject()); 19 | 20 | return mock; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 16 | 17 | ### Basic information 18 | 19 | **MapillaryJS version**: `...` 20 | **System/Browser**: `...` 21 | 22 | ### Steps to Reproduce Behavior 23 | 24 | 1. 25 | 2. 26 | 3. 27 | 28 | ### Expected behavior 29 | 30 | ... 31 | 32 | ### Actual behavior 33 | 34 | ... 35 | 36 | ### Additional information 37 | 38 | ... 39 | 40 | 41 | -------------------------------------------------------------------------------- /doc/src/js/components/Code.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import useBaseUrl from '@docusaurus/useBaseUrl'; 12 | 13 | import styles from './code.module.css'; 14 | 15 | export function Code(props) { 16 | const {title, style} = props; 17 | const name = title.replace(/\s/g, '-'); 18 | return ( 19 | 26 | View source code on GitHub 31 | 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /src/state/state/CustomState.ts: -------------------------------------------------------------------------------- 1 | import { Matrix4, Vector3 } from "three"; 2 | import { StateBase } from "./StateBase"; 3 | import { IStateBase } from "../interfaces/IStateBase"; 4 | 5 | export class CustomState extends StateBase { 6 | constructor(state: IStateBase) { 7 | super(state); 8 | } 9 | 10 | public setViewMatrix(viewMatrix: number[]): void { 11 | const viewMatrixInverse = new Matrix4() 12 | .fromArray(viewMatrix) 13 | .invert(); 14 | 15 | const me = viewMatrixInverse.elements; 16 | const eye = new Vector3(me[12], me[13], me[14]); 17 | const forward = new Vector3(-me[8], -me[9], -me[10]); 18 | const up = new Vector3(me[4], me[5], me[6]); 19 | 20 | const camera = this._camera; 21 | camera.position.copy(eye); 22 | camera.lookat.copy(eye 23 | .clone() 24 | .add(forward)); 25 | camera.up.copy(up); 26 | 27 | const focal = 0.5 / Math.tan(Math.PI / 3); 28 | camera.focal = focal; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /config/init.js: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import { join } from "path"; 3 | 4 | export const pathname = (dirname) => { 5 | const url = join(import.meta.url, `../${dirname}`); 6 | return new URL(url).pathname; 7 | }; 8 | 9 | const mapillaryAccessToken = process.env.MAPILLARY_ACCESS_TOKEN; 10 | const mapboxAccessToken = process.env.MAPBOX_ACCESS_TOKEN; 11 | 12 | const esmContent = ` 13 | export const accessToken = '${mapillaryAccessToken}'; 14 | export const mapboxAccessToken = '${mapboxAccessToken}'; 15 | `; 16 | const umdContent = ` 17 | var accessToken = '${mapillaryAccessToken}'; 18 | var mapboxAccessToken = '${mapboxAccessToken}'; 19 | `; 20 | 21 | const files = [ 22 | { 23 | name: "token.js", 24 | content: esmContent, 25 | }, 26 | { 27 | name: "token.umd.js", 28 | content: umdContent, 29 | }, 30 | ]; 31 | 32 | const dirname = pathname("../doc/.access-token"); 33 | if (!fs.existsSync(dirname)) { 34 | fs.mkdirSync(dirname); 35 | } 36 | 37 | for (const { name, content } of files) { 38 | fs.writeFileSync(join(dirname, name), content); 39 | } 40 | -------------------------------------------------------------------------------- /doc/static/img/examples/code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/plugins/plugin-overwrite-slug/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | const fs = require('fs'); 11 | const path = require('path'); 12 | 13 | const DEFAULT_OPTIONS = {}; 14 | 15 | module.exports = (context, options) => { 16 | const opts = {...DEFAULT_OPTIONS, ...options}; 17 | 18 | const {basePath, files} = opts; 19 | 20 | files.forEach((file) => { 21 | const name = path.join(process.cwd(), basePath, file.path); 22 | const content = fs.readFileSync(name, 'utf-8'); 23 | const lines = content.split('\n'); 24 | const overwritten = lines.reduce((acc, line) => { 25 | if (!line.startsWith('slug: ')) { 26 | return acc; 27 | } 28 | return acc.replace(line, `slug: '${file.slug}'`); 29 | }, content); 30 | fs.writeFileSync(name, overwritten); 31 | }); 32 | 33 | return { 34 | name: 'plugin-overwrite-slug', 35 | }; 36 | }; 37 | -------------------------------------------------------------------------------- /test/graph/Sequence.test.ts: -------------------------------------------------------------------------------- 1 | import { SequenceEnt } from "../../src/api/ents/SequenceEnt"; 2 | import { Sequence } from "../../src/graph/Sequence"; 3 | 4 | describe("Sequence", () => { 5 | let sequence: Sequence; 6 | 7 | beforeEach(() => { 8 | let response: SequenceEnt = { 9 | id: "A", 10 | image_ids: ["B", "C", "D", "E"], 11 | }; 12 | 13 | sequence = new Sequence(response); 14 | }); 15 | 16 | it("should create a sequence", () => { 17 | expect(sequence).toBeDefined(); 18 | }); 19 | 20 | it("should find next key when it exists", () => { 21 | expect(sequence.findNext("C")).toEqual("D"); 22 | }); 23 | 24 | it("should find prev key when it exists", () => { 25 | expect(sequence.findPrev("C")).toEqual("B"); 26 | }); 27 | 28 | it("should return null if no next key", () => { 29 | expect(sequence.findNext("E")).toBe(null); 30 | }); 31 | 32 | it("should return null if no prev key", () => { 33 | expect(sequence.findPrev("B")).toBe(null); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /doc/static/img/logo_black.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/static/img/logo_green.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /doc/static/img/examples/rotate.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/component/slider/shaders/spherical_curtain.fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export const sphericalCurtainFrag = ` 2 | #ifdef GL_FRAGMENT_PRECISION_HIGH 3 | precision highp float; 4 | #else 5 | precision mediump float; 6 | #endif 7 | #define tau 6.28318530718 8 | uniform sampler2D projectorTex; 9 | uniform float curtain; 10 | uniform float opacity; 11 | varying vec4 vRstq; 12 | void main() 13 | { 14 | vec3 b = normalize(vRstq.xyz); 15 | float lat = -asin(b.y); 16 | float lng = atan(b.x, b.z); 17 | float x = lng / tau + 0.5; 18 | float y = lat / tau * 2.0 + 0.5; 19 | bool inverted = curtain < 0.5; 20 | float curtainMin = inverted ? curtain + 0.5 : curtain - 0.5; 21 | float curtainMax = curtain; 22 | bool insideCurtain = inverted ? 23 | x > curtainMin || x < curtainMax : 24 | x > curtainMin && x < curtainMax; 25 | vec4 baseColor; 26 | if (insideCurtain) { 27 | baseColor = texture2D(projectorTex, vec2(x, y)); 28 | baseColor.a = opacity; 29 | } else { 30 | baseColor = vec4(0.0, 0.0, 0.0, 0.0); 31 | } 32 | gl_FragColor = baseColor; 33 | } 34 | ` 35 | -------------------------------------------------------------------------------- /src/api/provider/GraphContracts.ts: -------------------------------------------------------------------------------- 1 | // Cluster reconstruction 2 | export interface GraphCameraContract { 3 | focal: number; 4 | k1: number; 5 | k2: number; 6 | projection_type: string; 7 | } 8 | 9 | export interface GraphCameraShotContract { 10 | camera: string; 11 | rotation: number[]; 12 | translation: number[]; 13 | } 14 | 15 | export interface GraphReferenceContract { 16 | altitude: number; 17 | latitude: number; 18 | longitude: number; 19 | } 20 | 21 | export interface GraphPointContract { 22 | color: number[]; 23 | coordinates: number[]; 24 | } 25 | 26 | export interface GraphClusterContract { 27 | cameras: { [cameraId: string]: GraphCameraContract; }; 28 | points: { [pointId: string]: GraphPointContract; }; 29 | reference_lla: GraphReferenceContract, 30 | shots: { [imageKey: string]: GraphCameraShotContract; }; 31 | } 32 | 33 | // General 34 | export interface GraphError { 35 | error: { 36 | code: number; 37 | fbtrace_id: string; 38 | message: string; 39 | type: string; 40 | }; 41 | } 42 | export interface GraphContract { 43 | data: T; 44 | } 45 | -------------------------------------------------------------------------------- /test/component/spatial/SpatialComponent.test.ts: -------------------------------------------------------------------------------- 1 | 2 | import { SpatialComponent } from "../../../src/component/spatial/SpatialComponent"; 3 | import { ContainerMockCreator } from "../../helper/ContainerMockCreator"; 4 | import { NavigatorMockCreator } from "../../helper/NavigatorMockCreator"; 5 | 6 | describe("SpatialComponent.ctor", () => { 7 | it("should be defined", () => { 8 | const component: SpatialComponent = 9 | new SpatialComponent( 10 | SpatialComponent.componentName, 11 | new ContainerMockCreator().create(), 12 | new NavigatorMockCreator().create()); 13 | 14 | expect(component).toBeDefined(); 15 | }); 16 | }); 17 | 18 | describe("SpatialComponent.deactivate", () => { 19 | it("should deactivate properly", () => { 20 | const component: SpatialComponent = 21 | new SpatialComponent( 22 | SpatialComponent.componentName, 23 | new ContainerMockCreator().create(), 24 | new NavigatorMockCreator().create()); 25 | 26 | component.activate(); 27 | component.deactivate(); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Facebook, Inc. and its affiliates. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /doc/src/css/log.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | .example-log-container { 11 | user-select: none; 12 | color: #eee; 13 | position: absolute; 14 | top: 0px; 15 | right: 12px; 16 | width: 200px; 17 | font: 10px 'Lucida Grande', sans-serif; 18 | } 19 | 20 | .example-log-container.option-child { 21 | top: initial; 22 | right: initial; 23 | margin-left: 4px; 24 | width: 196px; 25 | font: 10px 'Lucida Grande', sans-serif; 26 | } 27 | 28 | .example-log-container .header { 29 | border-bottom: 1px solid #2c2c2c; 30 | background-color: #000; 31 | height: 20px; 32 | line-height: 20px; 33 | text-align: center; 34 | } 35 | 36 | .example-log-container .log-item { 37 | text-overflow: ellipsis; 38 | white-space: nowrap; 39 | overflow: hidden; 40 | background-color: #1a1a1a; 41 | padding: 0 4px 0 5px; 42 | height: 18px; 43 | line-height: 18px; 44 | border-bottom: 1px solid #2c2c2c; 45 | border-left: 3px solid #1ed36f; 46 | } 47 | -------------------------------------------------------------------------------- /doc/src/js/components/ViewerComponent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import React from 'react'; 11 | import {accessToken, mapboxAccessToken} from '../../../.access-token/token'; 12 | 13 | import styles from './viewer.module.css'; 14 | 15 | export class ViewerComponent extends React.Component { 16 | constructor(props) { 17 | super(props); 18 | this.containerRef = React.createRef(); 19 | } 20 | 21 | componentDidMount() { 22 | const {init} = this.props; 23 | init({ 24 | accessToken, 25 | mapboxAccessToken, 26 | container: this.containerRef.current, 27 | }); 28 | } 29 | 30 | componentWillUnmount() { 31 | const {dispose} = this.props; 32 | dispose(); 33 | } 34 | 35 | render() { 36 | const {style} = this.props; 37 | return ( 38 |
43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import dts from 'rollup-plugin-dts'; 2 | import { terser } from 'rollup-plugin-terser'; 3 | import { 4 | esm, 5 | srcInput as input, 6 | plugins, 7 | umdOutput, 8 | } from './config/rollup.js'; 9 | 10 | const unminifiedOutput = Object.assign( 11 | { file: 'dist/mapillary.unminified.js' }, 12 | umdOutput); 13 | 14 | const minifiedOutput = Object.assign( 15 | { file: 'dist/mapillary.js' }, 16 | umdOutput); 17 | 18 | const bundles = [ 19 | esm, 20 | { 21 | input, 22 | output: [ 23 | unminifiedOutput 24 | ], 25 | plugins, 26 | }, 27 | { 28 | input, 29 | output: [ 30 | minifiedOutput, 31 | ], 32 | plugins: [ 33 | ...plugins, 34 | terser(), 35 | ], 36 | }, 37 | { 38 | input: 'build/esm/src/mapillary.d.ts', 39 | output: [ 40 | { 41 | file: 'dist/mapillary.d.ts', 42 | format: 'es', 43 | } 44 | ], 45 | plugins: [ 46 | dts(), 47 | ], 48 | }, 49 | ]; 50 | 51 | export default bundles; 52 | -------------------------------------------------------------------------------- /src/component/interfaces/TagConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { ComponentConfiguration } from "./ComponentConfiguration"; 2 | import { TagMode } from "../tag/TagMode"; 3 | 4 | /** 5 | * Interface for configuration of tag component. 6 | * 7 | * @interface 8 | * @example 9 | * ```js 10 | * var viewer = new Viewer({ 11 | * ... 12 | * component: { 13 | * tag: { 14 | * createColor: 0xFF0000, 15 | * mode: TagMode.CreateRect, 16 | * }, 17 | * }, 18 | * ... 19 | * }); 20 | * ``` 21 | */ 22 | export interface TagConfiguration extends ComponentConfiguration { 23 | /** 24 | * The color of vertices and edges for tags that 25 | * are being created. 26 | * 27 | * @default 0xFFFFFF 28 | */ 29 | createColor?: number; 30 | 31 | /** 32 | * Show an indicator at the centroid of the points geometry 33 | * that creates the geometry when clicked. 34 | * @default true 35 | */ 36 | indicatePointsCompleter?: boolean; 37 | 38 | /** 39 | * The interaction mode of the tag component. 40 | * 41 | * @default TagMode.Default 42 | */ 43 | mode?: TagMode; 44 | } 45 | -------------------------------------------------------------------------------- /src/component/slider/shaders/perspective.fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export const perspectiveFrag = ` 2 | #ifdef GL_FRAGMENT_PRECISION_HIGH 3 | precision highp float; 4 | #else 5 | precision mediump float; 6 | #endif 7 | 8 | uniform sampler2D projectorTex; 9 | uniform float opacity; 10 | uniform float focal; 11 | uniform float k1; 12 | uniform float k2; 13 | uniform float scale_x; 14 | uniform float scale_y; 15 | uniform float radial_peak; 16 | 17 | varying vec4 vRstq; 18 | 19 | void main() 20 | { 21 | float x = vRstq.x / vRstq.z; 22 | float y = vRstq.y / vRstq.z; 23 | float r2 = x * x + y * y; 24 | 25 | if (radial_peak > 0. && r2 > radial_peak * sqrt(r2)) { 26 | r2 = radial_peak * radial_peak; 27 | } 28 | 29 | float d = 1.0 + k1 * r2 + k2 * r2 * r2; 30 | float u = scale_x * focal * d * x + 0.5; 31 | float v = - scale_y * focal * d * y + 0.5; 32 | 33 | vec4 baseColor; 34 | if (u >= 0. && u <= 1. && v >= 0. && v <= 1.) { 35 | baseColor = texture2D(projectorTex, vec2(u, v)); 36 | baseColor.a = opacity; 37 | } else { 38 | baseColor = vec4(0.0, 0.0, 0.0, 0.0); 39 | } 40 | 41 | gl_FragColor = baseColor; 42 | } 43 | ` 44 | -------------------------------------------------------------------------------- /doc/src/js/utils/image.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | export function generateImageBuffer(options) { 11 | const {tilesY, tilesX, tileSize} = options; 12 | const w = tileSize; 13 | const h = tileSize; 14 | const canvas = document.createElement('canvas'); 15 | canvas.width = w * tilesX; 16 | canvas.height = h * tilesY; 17 | const ctx = canvas.getContext('2d'); 18 | 19 | for (let y = tilesY - 1; y >= 0; y--) { 20 | for (let x = 0; x < tilesX; x++) { 21 | const r = Math.floor((255 * x) / (tilesX - 1)); 22 | const g = Math.floor((255 * (tilesY - 1 - y)) / (tilesY - 1)); 23 | const b = 0; 24 | ctx.fillStyle = `rgb(${r} ${g} ${b})`; 25 | ctx.fillRect(w * x, h * y, w, h); 26 | } 27 | } 28 | 29 | return new Promise((resolve) => { 30 | canvas.toBlob( 31 | async (blob) => { 32 | const buffer = await blob.arrayBuffer(); 33 | resolve(buffer); 34 | }, 35 | 'image/jpeg', 36 | 1, 37 | ); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /examples/doc/extend-procedural-data-provider.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Extend Procedural Data Provider 5 | 6 | 7 | 11 | 12 | 13 | 14 | 27 | 28 | 29 | 30 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/component/tag/TagDOMRenderer.ts: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import * as vd from "virtual-dom"; 3 | 4 | import { Geometry } from "./geometry/Geometry"; 5 | import { CreateTag } from "./tag/CreateTag"; 6 | import { RenderTag } from "./tag/RenderTag"; 7 | import { Tag } from "./tag/Tag"; 8 | 9 | import { ViewportSize } from "../../render/interfaces/ViewportSize"; 10 | import { ISpriteAtlas } from "../../viewer/interfaces/ISpriteAtlas"; 11 | 12 | export class TagDOMRenderer { 13 | public render( 14 | tags: RenderTag[], 15 | createTag: CreateTag, 16 | atlas: ISpriteAtlas, 17 | camera: THREE.PerspectiveCamera, 18 | size: ViewportSize): vd.VNode { 19 | 20 | let vNodes: vd.VNode[] = []; 21 | 22 | for (const tag of tags) { 23 | vNodes = vNodes.concat(tag.getDOMObjects(atlas, camera, size)); 24 | } 25 | 26 | if (createTag != null) { 27 | vNodes = vNodes.concat(createTag.getDOMObjects(camera, size)); 28 | } 29 | 30 | return vd.h("div.mapillary-tag-container", {}, vNodes); 31 | } 32 | 33 | public clear(): vd.VNode { 34 | return vd.h("div", {}, []); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /doc/src/js/options/OptionController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | import {Controller} from './Controller'; 11 | 12 | export class OptionController extends Controller { 13 | constructor(object, property, opts) { 14 | super(object, property); 15 | 16 | const options = opts.slice(); 17 | this.select = document.createElement('select'); 18 | for (const opt of options) { 19 | const option = document.createElement('option'); 20 | option.innerHTML = opt; 21 | option.setAttribute('value', opt); 22 | this.select.appendChild(option); 23 | } 24 | 25 | this.container.appendChild(this.select); 26 | this.container.classList.add('option'); 27 | 28 | this.select.addEventListener('change', (event) => { 29 | if (!this._onChange) { 30 | return; 31 | } 32 | const index = event.target.selectedIndex; 33 | const value = options[index]; 34 | this.object[this.property] = value; 35 | this._onChange(value); 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/component/tag/handlers/CreatePointHandler.ts: -------------------------------------------------------------------------------- 1 | import { 2 | map, 3 | filter, 4 | } from "rxjs/operators"; 5 | import { Subscription } from "rxjs"; 6 | import { PointGeometry } from "../geometry/PointGeometry"; 7 | import { CreateHandlerBase } from "./CreateHandlerBase"; 8 | 9 | export class CreatePointHandler extends CreateHandlerBase { 10 | private _geometryCreatedSubscription: Subscription; 11 | 12 | protected _enableCreate(): void { 13 | this._container.mouseService.deferPixels(this._name, 4); 14 | 15 | this._geometryCreatedSubscription = this._mouseEventToBasic$(this._container.mouseService.proximateClick$).pipe( 16 | filter(this._validateBasic), 17 | map( 18 | (basic: number[]): PointGeometry => { 19 | return new PointGeometry(basic); 20 | })) 21 | .subscribe(this._geometryCreated$); 22 | } 23 | 24 | protected _disableCreate(): void { 25 | this._container.mouseService.undeferPixels(this._name); 26 | 27 | this._geometryCreatedSubscription.unsubscribe(); 28 | } 29 | 30 | protected _getNameExtension(): string { 31 | return "create-point"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/doc/support.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Support 5 | 6 | 7 | 11 | 12 | 13 | 14 | 27 | 28 | 29 | 30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/component/slider/shaders/perspective_curtain.fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export const perspectiveCurtainFrag = ` 2 | #ifdef GL_FRAGMENT_PRECISION_HIGH 3 | precision highp float; 4 | #else 5 | precision mediump float; 6 | #endif 7 | uniform sampler2D projectorTex; 8 | uniform float opacity; 9 | uniform float focal; 10 | uniform float k1; 11 | uniform float k2; 12 | uniform float scale_x; 13 | uniform float scale_y; 14 | uniform float radial_peak; 15 | uniform float curtain; 16 | varying vec4 vRstq; 17 | void main() 18 | { 19 | float x = vRstq.x / vRstq.z; 20 | float y = vRstq.y / vRstq.z; 21 | float r2 = x * x + y * y; 22 | if (radial_peak > 0. && r2 > radial_peak * sqrt(r2)) { 23 | r2 = radial_peak * radial_peak; 24 | } 25 | float d = 1.0 + k1 * r2 + k2 * r2 * r2; 26 | float u = scale_x * focal * d * x + 0.5; 27 | float v = - scale_y * focal * d * y + 0.5; 28 | vec4 baseColor; 29 | if ((u < curtain || curtain >= 1.0) && u >= 0. && u <= 1. && v >= 0. && v <= 1.) { 30 | baseColor = texture2D(projectorTex, vec2(u, v)); 31 | baseColor.a = opacity; 32 | } else { 33 | baseColor = vec4(0.0, 0.0, 0.0, 0.0); 34 | } 35 | gl_FragColor = baseColor; 36 | } 37 | ` 38 | -------------------------------------------------------------------------------- /src/viewer/enums/CameraControls.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enumeration for camera controls. 3 | * 4 | * @description Specifies different modes for how the 5 | * camera is controlled through pointer, keyboard or 6 | * other modes of input. 7 | * 8 | * @enum {number} 9 | * @readonly 10 | */ 11 | export enum CameraControls { 12 | /** 13 | * Control the camera with custom logic by 14 | * attaching a custom camera controls 15 | * instance to the {@link Viewer}. 16 | */ 17 | Custom, 18 | 19 | /** 20 | * Control the camera from a birds perspective 21 | * to get an overview. 22 | */ 23 | Earth, 24 | 25 | /** 26 | * Control the camera in a first person view 27 | * from the street level perspective. 28 | * 29 | * @description The virtual viewer camera will 30 | * be rotated according to the orientation of 31 | * the images. 32 | */ 33 | Street, 34 | 35 | /** 36 | * Control the camera in a first person view 37 | * from the street level perspective. 38 | * 39 | * @description The virtual viewer camera will 40 | * maintain gravity alignment for its up vector 41 | * at all times. 42 | */ 43 | Gravity, 44 | } 45 | -------------------------------------------------------------------------------- /src/component/interfaces/PointerConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { ComponentConfiguration } from "./ComponentConfiguration"; 2 | 3 | /** 4 | * Interface for configuration of mouse component. 5 | * 6 | * @interface 7 | * @example 8 | * ```js 9 | * var viewer = new Viewer({ 10 | * ... 11 | * component: { 12 | * pointer: { 13 | * dragPan: false, 14 | * scrollZoom: false, 15 | * touchZoom: false, 16 | * }, 17 | * }, 18 | * ... 19 | * }); 20 | * ``` 21 | */ 22 | export interface PointerConfiguration extends ComponentConfiguration { 23 | /** 24 | * Activate or deactivate the `DragPanHandler`. 25 | * 26 | * @default true 27 | */ 28 | dragPan?: boolean; 29 | 30 | /** 31 | * Activate or deactivate the `EarthControlHandler`. 32 | * 33 | * @default true 34 | */ 35 | earthControl?: boolean; 36 | 37 | /** 38 | * Activate or deactivate the `ScrollZoomHandler`. 39 | * 40 | * @default true 41 | */ 42 | scrollZoom?: boolean; 43 | 44 | /** 45 | * Activate or deactivate the `TouchZoomHandler`. 46 | * 47 | * @default true 48 | */ 49 | touchZoom?: boolean; 50 | } 51 | -------------------------------------------------------------------------------- /examples/doc/viewer-options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Viewer Options 5 | 6 | 7 | 11 | 12 | 13 | 14 | 27 | 28 | 29 | 30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/api/CellMath.ts: -------------------------------------------------------------------------------- 1 | import { IGeometryProvider } from "./interfaces/IGeometryProvider"; 2 | 3 | export function connectedComponent( 4 | cellId: string, 5 | depth: number, 6 | geometry: IGeometryProvider) 7 | : string[] { 8 | 9 | const cells = new Set(); 10 | cells.add(cellId); 11 | connectedComponentRecursive(cells, [cellId], 0, depth, geometry); 12 | return Array.from(cells); 13 | } 14 | 15 | function connectedComponentRecursive( 16 | cells: Set, 17 | current: string[], 18 | currentDepth: number, 19 | maxDepth: number, 20 | geometry: IGeometryProvider) 21 | : void { 22 | 23 | if (currentDepth >= maxDepth) { return; } 24 | 25 | const adjacent: string[] = []; 26 | for (const cellId of current) { 27 | const aCells = geometry.getAdjacent(cellId); 28 | adjacent.push(...aCells); 29 | } 30 | 31 | const newCells: string[] = []; 32 | for (const a of adjacent) { 33 | if (cells.has(a)) { continue; } 34 | cells.add(a); 35 | newCells.push(a); 36 | } 37 | 38 | connectedComponentRecursive( 39 | cells, 40 | newCells, 41 | currentDepth + 1, 42 | maxDepth, 43 | geometry); 44 | } 45 | -------------------------------------------------------------------------------- /examples/doc/extend-animation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Extend Animation 5 | 6 | 7 | 11 | 12 | 13 | 14 | 27 | 28 | 29 | 30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /doc/docusaurus.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | const path = require('path'); 11 | const docsConfig = require('./docusaurus.docs.config.js'); 12 | 13 | const config = {...docsConfig}; 14 | config.plugins = config.plugins.slice(); 15 | config.plugins.push( 16 | [ 17 | 'docusaurus-plugin-typedoc', 18 | { 19 | sidebar: {sidebarFile: null}, 20 | }, 21 | ], 22 | [ 23 | path.resolve(__dirname, 'plugins/plugin-overwrite-slug'), 24 | { 25 | basePath: 'api', 26 | files: [ 27 | { 28 | path: 'index.md', 29 | slug: '/', 30 | }, 31 | ], 32 | }, 33 | ], 34 | [ 35 | '@docusaurus/plugin-content-docs', 36 | { 37 | id: 'api', 38 | path: 'api', 39 | routeBasePath: 'api', 40 | sidebarPath: require.resolve('./sidebars/api.sidebars.js'), 41 | editUrl: 'https://github.com/mapillary/mapillary-js/edit/main/doc', 42 | }, 43 | ], 44 | ); 45 | 46 | /** @type {import('@docusaurus/types').DocusaurusConfig} */ 47 | module.exports = config; 48 | -------------------------------------------------------------------------------- /examples/doc/extend-fly-controls.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Extend Fly Controls 5 | 6 | 7 | 11 | 12 | 13 | 14 | 27 | 28 | 29 | 30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /examples/doc/extend-webgl-renderer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Extend WebGL Renderer 5 | 6 | 7 | 11 | 12 | 13 | 14 | 27 | 28 | 29 | 30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /examples/doc/viewer-initialization.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Viewer Initialization 5 | 6 | 7 | 11 | 12 | 13 | 14 | 27 | 28 | 29 | 30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /examples/doc/extend-three-renderer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Extend Three.js Renderer 5 | 6 | 7 | 11 | 12 | 13 | 14 | 27 | 28 | 29 | 30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/component/interfaces/KeyboardConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { ComponentConfiguration } from "./ComponentConfiguration"; 2 | 3 | /** 4 | * Interface for configuration of keyboard component. 5 | * 6 | * @interface 7 | * @example 8 | * ```js 9 | * var viewer = new Viewer({ 10 | * ... 11 | * component: { 12 | * keyboard: { 13 | * keyZoom: false, 14 | * keySequenceNavigation: false, 15 | * keySpatialNavigation: false, 16 | * }, 17 | * }, 18 | * ... 19 | * }); 20 | * ``` 21 | */ 22 | export interface KeyboardConfiguration extends ComponentConfiguration { 23 | /** 24 | * Enable or disable the `KeyPlayHandler`. 25 | * 26 | * @default true 27 | */ 28 | keyPlay?: boolean; 29 | 30 | /** 31 | * Enable or disable the `KeySequenceNavigationHandler`. 32 | * 33 | * @default true 34 | */ 35 | keySequenceNavigation?: boolean; 36 | 37 | /** 38 | * Enable or disable the `KeySpatialNavigationHandler`. 39 | * 40 | * @default true 41 | */ 42 | keySpatialNavigation?: boolean; 43 | 44 | /** 45 | * Enable or disable the `KeyZoomHandler`. 46 | * 47 | * @default true 48 | */ 49 | keyZoom?: boolean; 50 | } 51 | -------------------------------------------------------------------------------- /examples/doc/extend-graphics-developer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Extend Graphics Developer 5 | 6 | 7 | 11 | 12 | 13 | 14 | 27 | 28 | 29 | 30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /examples/doc/viewer-events.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Viewer Events 5 | 6 | 7 | 11 | 12 | 13 | 14 | 15 | 28 | 29 | 30 | 31 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/component/slider/shaders/fisheye.fragment.glsl.ts: -------------------------------------------------------------------------------- 1 | export const fisheyeFrag = ` 2 | #ifdef GL_FRAGMENT_PRECISION_HIGH 3 | precision highp float; 4 | #else 5 | precision mediump float; 6 | #endif 7 | 8 | uniform sampler2D projectorTex; 9 | uniform float opacity; 10 | uniform float focal; 11 | uniform float k1; 12 | uniform float k2; 13 | uniform float scale_x; 14 | uniform float scale_y; 15 | uniform float radial_peak; 16 | 17 | varying vec4 vRstq; 18 | 19 | void main() 20 | { 21 | float x = vRstq.x; 22 | float y = vRstq.y; 23 | float z = vRstq.z; 24 | 25 | float r = sqrt(x * x + y * y); 26 | float theta = atan(r, z); 27 | 28 | if (radial_peak > 0. && theta > radial_peak) { 29 | theta = radial_peak; 30 | } 31 | 32 | float theta2 = theta * theta; 33 | float theta_d = theta * (1.0 + theta2 * (k1 + theta2 * k2)); 34 | float s = focal * theta_d / r; 35 | 36 | float u = scale_x * s * x + 0.5; 37 | float v = -scale_y * s * y + 0.5; 38 | 39 | vec4 baseColor; 40 | if (u >= 0. && u <= 1. && v >= 0. && v <= 1.) { 41 | baseColor = texture2D(projectorTex, vec2(u, v)); 42 | baseColor.a = opacity; 43 | } else { 44 | baseColor = vec4(0.0, 0.0, 0.0, 0.0); 45 | } 46 | 47 | gl_FragColor = baseColor; 48 | } 49 | ` 50 | --------------------------------------------------------------------------------