UNPKG

transitive-js

Version:

A tool for generating dynamic stylized transit maps that are easy to understand.

178 lines (147 loc) 4.89 kB
// Note: this code is duplicated from @opentripplanner/transitive-overlay package // with the transitive-js imports replaced with local imports. // See https://github.com/opentripplanner/otp-ui/blob/master/packages/transitive-overlay/src/index.js import L from 'leaflet' import isEqual from 'lodash.isequal' import { MapLayer, withLeaflet } from 'react-leaflet' import Transitive from '../lib/transitive' import transitiveStyles from './transitive-styles' require('./leaflet-canvas-layer') // TODO: move to util? function checkHiPPI(canvas) { if (window.devicePixelRatio > 1) { const PIXEL_RATIO = 2 canvas.style.width = `${canvas.width}px` canvas.style.height = `${canvas.height}px` canvas.width *= PIXEL_RATIO canvas.height *= PIXEL_RATIO const context = canvas.getContext('2d') context.scale(PIXEL_RATIO, PIXEL_RATIO) } } const DEFAULT_ZOOM_FACTORS = [ { angleConstraint: 5, gridCellSize: 0, internalVertexFactor: 0, mergeVertexThreshold: 0, minScale: 0, useGeographicRendering: true } ] // By default, only bus segments are labeled. // (See /lib/util/index.js#otpModeToGtfsType for mode type codes.) const DEFAULT_LABELED_MODES = [3] class TransitiveCanvasOverlay extends MapLayer { // React Lifecycle Methods componentDidMount() { const { map } = this.props.leaflet L.canvasLayer() .delegate(this) // -- if we do not inherit from L.CanvasLayer we can setup a delegate to receive events from L.CanvasLayer .addTo(map) } componentDidUpdate(prevProps) { // Check if we received new transitive data if ( this.transitive && !isEqual(prevProps.transitiveData, this.props.transitiveData) ) { this.transitive.updateData(this.props.transitiveData) if (!this.props.transitiveData) this.transitive.render() else this.updateBoundsAndRender() } if ( // this block only applies for profile trips where active option changed this.props.routingType === 'PROFILE' && prevProps.activeItinerary !== this.props.activeItinerary ) { if (this.props.activeItinerary == null) { // no option selected clear focus this.transitive.focusJourney(null) this.transitive.render() } else if (this.props.transitiveData) { this.transitive.focusJourney( this.props.transitiveData.journeys[this.props.activeItinerary] .journey_id ) this.transitive.render() } } } componentWillUnmount() { if (this.transitive) { this.transitive.updateData(null) this.transitive.render() } } // Internal Methods initTransitive(canvas) { const { labeledModes = DEFAULT_LABELED_MODES, leaflet, styles = transitiveStyles, transitiveData, zoomFactors = DEFAULT_ZOOM_FACTORS } = this.props const { map } = leaflet // set up the transitive instance const mapBounds = map.getBounds() this.transitive = new Transitive({ autoResize: false, canvas, data: transitiveData, display: 'canvas', initialBounds: [ [mapBounds.getWest(), mapBounds.getSouth()], [mapBounds.getEast(), mapBounds.getNorth()] ], labeledModes, styles, zoomEnabled: false, zoomFactors }) checkHiPPI(canvas) // the initial map draw this.updateBoundsAndRender() } updateBoundsAndRender() { if (!this.transitive) { console.log( 'WARNING: Transitive object not set in transitive-canvas-overlay' ) return } const mapBounds = this.props.leaflet.map.getBounds() this.transitive.setDisplayBounds([ [mapBounds.getWest(), mapBounds.getSouth()], [mapBounds.getEast(), mapBounds.getNorth()] ]) this.transitive.render() } // Leaflet Layer API Methods onDrawLayer(info) { if (!this.transitive) this.initTransitive(info.canvas) const mapSize = this.props.leaflet.map.getSize() if ( this.lastMapSize && (mapSize.x !== this.lastMapSize.x || mapSize.y !== this.lastMapSize.y) ) { const canvas = info.canvas checkHiPPI(canvas) this.transitive.display.setDimensions(mapSize.x, mapSize.y) this.transitive.display.setCanvas(canvas) } this.updateBoundsAndRender() this.lastMapSize = this.props.leaflet.map.getSize() } // the next line might be needed for react-leaflet // eslint-disable-next-line @typescript-eslint/no-empty-function createTile() {} // the next line might be needed for react-leaflet // eslint-disable-next-line @typescript-eslint/no-empty-function createLeafletElement() {} // the next line might be needed for react-leaflet // eslint-disable-next-line @typescript-eslint/no-empty-function updateLeafletElement() {} } export default withLeaflet(TransitiveCanvasOverlay)