Skip to content

Commit

Permalink
Add SVGOverlay component
Browse files Browse the repository at this point in the history
  • Loading branch information
fenech committed Oct 16, 2019
1 parent 2c8fe10 commit 01500eb
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 0 deletions.
12 changes: 12 additions & 0 deletions docs/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ You can check out the [event handling example](https://github.com/PaulLeCam/reac
- [Vector Layers](#vector-layers)
- [Circle](#circle)
- [CircleMarker](#circlemarker)
- [SVGOverlay](#svgoverlay)
- [Polyline](#polyline)
- [Polygon](#polygon)
- [Rectangle](#rectangle)
Expand Down Expand Up @@ -319,6 +320,17 @@ properties.
- `radius: number` (optional)
- `attribution: string` (optional)

### SVGOverlay

[🍃 Leaflet reference](https://leafletjs.com/reference-1.5.0.html#svgoverlay)[🔍 Source](https://github.com/PaulLeCam/react-leaflet/blob/master/src/SVGOverlay.js)

**Dynamic properties**

- `bounds: bounds` (required)
- `opacity: number` (optional)
- `zIndex: number` (optional)
- `attribution: string` (optional)

### Polyline

[🍃 Leaflet reference](http://leafletjs.com/reference-1.5.0.html#polyline)[🔍 Source](https://github.com/PaulLeCam/react-leaflet/blob/master/src/Polyline.js)
Expand Down
1 change: 1 addition & 0 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Different examples are available in the [example folder](https://github.com/Paul
- [Event handling](https://github.com/PaulLeCam/react-leaflet/blob/master/example/components/events.js)
- [Viewport usage](https://github.com/PaulLeCam/react-leaflet/blob/master/example/components/viewport.js)
- [Vector layers (Rectangle, Circle, etc.)](https://github.com/PaulLeCam/react-leaflet/blob/master/example/components/vector-layers.js)
- [SVG Overlay](https://github.com/PaulLeCam/react-leaflet/blob/master/example/components/svg-overlay.js)
- [Other layers (LayerGroup, FeatureGroup)](https://github.com/PaulLeCam/react-leaflet/blob/master/example/components/other-layers.js)
- [Tooltips](https://github.com/PaulLeCam/react-leaflet/blob/master/example/components/tooltip.js)
- [Custom zoom control](https://github.com/PaulLeCam/react-leaflet/blob/master/example/components/zoom-control.js)
Expand Down
3 changes: 3 additions & 0 deletions example/components/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import PaneExample from './pane'
import WMSTileLayerExample from './wms-tile-layer'
import VideoOverlayExample from './video-overlay'
import CustomIcons from './custom-icons'
import SVGOverlayExample from './svg-overlay'

Leaflet.Icon.Default.imagePath =
'//cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/images/'
Expand All @@ -37,6 +38,8 @@ const App = () => (
<ViewportExample />
<h2>Vector layers</h2>
<VectorLayersExample />
<h2>SVG Overlay</h2>
<SVGOverlayExample />
<h2>Other layers</h2>
<OtherLayersExample />
<h2>GeoJSON with Popup</h2>
Expand Down
23 changes: 23 additions & 0 deletions example/components/svg-overlay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// @flow

import React, { Component } from 'react'
import { Map, SVGOverlay } from '../../src'

const center = [51.505, -0.09]
const rectangle = [[51.49, -0.08], [51.5, -0.06]]

export default class SVGOverlayExample extends Component<{}> {
render() {
return (
<Map center={center} zoom={13}>
<SVGOverlay bounds={rectangle}>
<rect x="0" y="0" width="100%" height="100%" fill="blue" />
<circle r="5" cx="10" cy="10" fill="red" />
<text x="50%" y="50%" fill="white">
text
</text>
</SVGOverlay>
</Map>
)
}
}
93 changes: 93 additions & 0 deletions src/SVGOverlay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// @flow

import { Layer, LatLngBounds, SVGOverlay as LeafletSVGOverlay } from 'leaflet'

import { createPortal } from 'react-dom'
import type { LeafletContext, SVGOverlayProps } from './types'
import { withLeaflet } from './context'
import MapComponent from './MapComponent'

type SVGOverlayTypes = {
attribution?: string,
bounds: LatLngBounds,
opacity?: number,
zIndex?: number,
}

export class SVGOverlay<
LeafletElement: LeafletSVGOverlay,
Props: SVGOverlayProps,
> extends MapComponent<LeafletElement & SVGOverlayTypes, Props> {
contextValue: ?LeafletContext
leafletElement: LeafletElement
container: SVGSVGElement

constructor(props: Props) {
super(props)
this.leafletElement = this.createLeafletElement(props)
}

get layerContainer(): Layer {
return this.props.leaflet.layerContainer || this.props.leaflet.map
}

createLeafletElement(_props: Props): LeafletElement {
this.container = document.createElementNS(
'http://www.w3.org/2000/svg',
'svg',
)
return new LeafletSVGOverlay(
this.container,
_props.bounds,
this.getOptions(_props),
)
}

updateLeafletElement(_fromProps: Props, _toProps: Props) {
if (_toProps.bounds !== _fromProps.bounds) {
this.leafletElement.setBounds(_toProps.bounds)
}
if (_toProps.opacity !== _fromProps.opacity) {
this.leafletElement.setOpacity(_toProps.opacity)
}
if (_toProps.zIndex !== _fromProps.zIndex) {
this.leafletElement.setZIndex(_toProps.zIndex)
}
}

componentDidMount() {
super.componentDidMount()
this.layerContainer.addLayer(this.leafletElement)
}

componentDidUpdate(prevProps: Props) {
super.componentDidUpdate(prevProps)

if (this.props.attribution !== prevProps.attribution) {
const { map } = this.props.leaflet
if (map != null && map.attributionControl != null) {
map.attributionControl.removeAttribution(prevProps.attribution)
map.attributionControl.addAttribution(this.props.attribution)
}
}

this.updateLeafletElement(prevProps, this.props)
}

componentWillUnmount() {
super.componentWillUnmount()
this.layerContainer.removeLayer(this.leafletElement)
this.container = null
}

render() {
const { children } = this.props
if (children == null || this.container == null) {
return null
}

return createPortal(children, this.container)
}
}

export default withLeaflet(SVGOverlay)
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export { default as Polyline } from './Polyline'
export { default as Popup } from './Popup'
export { default as Rectangle } from './Rectangle'
export { default as ScaleControl } from './ScaleControl'
export { default as SVGOverlay } from './SVGOverlay'
export { default as TileLayer } from './TileLayer'
export { default as Tooltip } from './Tooltip'
export { default as VideoOverlay } from './VideoOverlay'
Expand Down
19 changes: 19 additions & 0 deletions src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,19 @@ export type DivOverlayOptions = {
onOpen?: () => void,
}

export type CrossOrigin = boolean | string

export type ImageOverlayOptions = {
opacity?: number,
alt?: string,
interactive?: boolean,
attribution?: string,
crossOrigin?: CrossOrigin,
errorOverlayUrl?: string,
zIndex?: number,
className?: string,
}

export type LeafletProps = { leaflet: LeafletContext }

export type MapControlProps = {
Expand All @@ -111,3 +124,9 @@ export type MapLayerProps = {
export type GridLayerProps = MapLayerProps & GridLayerOptions

export type PathProps = MapLayerProps & PathOptions

export type SVGOverlayProps = MapComponentProps &
ImageOverlayOptions & {
bounds: LatLngBounds,
children?: Node,
}

0 comments on commit 01500eb

Please sign in to comment.