Skip to content
Snippets Groups Projects
AppleMaps.js 8.46 KiB
Newer Older
tonyduanesmith's avatar
tonyduanesmith committed
import React, { Component } from 'react'

class AppleMaps extends Component {
tonyduanesmith's avatar
tonyduanesmith committed
	componentDidMount() {
		const { token, children, initialMapType } = this.props
tonyduanesmith's avatar
tonyduanesmith committed
		this.canvas = document.createElement('canvas')
		this.canvas.id = 'currentLocationOverride'
tonyduanesmith's avatar
tonyduanesmith committed
		mapkit.init({
			authorizationCallback: function(done) {
				done(token)
			}
		})

		this.map = new mapkit.Map('map')
		// Set initial mapType
		if(initialMapType !== undefined) {
			this.map.mapType = initialMapType
		}

tonyduanesmith's avatar
tonyduanesmith committed
		if (children !== undefined && children.length) {
tonyduanesmith's avatar
tonyduanesmith committed
			children.forEach(child => {
				if (child.props.isAnnotation) {
tonyduanesmith's avatar
tonyduanesmith committed
				}
			})
tonyduanesmith's avatar
tonyduanesmith committed
		} else if (children !== undefined && children.props) {
			if (children.props.isAnnotation) {
tonyduanesmith's avatar
tonyduanesmith committed
		//	Image Annotations
		if (children !== undefined && children.length) {
			children.forEach(child => {
				if (child.props.isImageAnnotation) {
tonyduanesmith's avatar
tonyduanesmith committed
					this.createImageAnnotation(child.props)
				}
			})
		} else if (children !== undefined && children.props) {
			if (children.props.isImageAnnotation) {
tonyduanesmith's avatar
tonyduanesmith committed
				this.createImageAnnotation(children.props)
			}
		}

		// Current Location Override
		if (children !== undefined && children.length) {
tonyduanesmith's avatar
tonyduanesmith committed
			children.forEach(child => {
tonyduanesmith's avatar
tonyduanesmith committed
				if (child.type.name === 'CurrentLocationOverride') {
					this.createCurrentLocationOverride(child.props)
tonyduanesmith's avatar
tonyduanesmith committed
				}
			})
		} else if (children !== undefined && children.props) {
tonyduanesmith's avatar
tonyduanesmith committed
			if (children.type.name === 'CurrentLocationOverride') {
				this.createCurrentLocationOverride(children.props)
			}
tonyduanesmith's avatar
tonyduanesmith committed
		}
tonyduanesmith's avatar
tonyduanesmith committed
	componentDidUpdate(prevProps) {
		const {
			children,
			latitude,
			longitude,
			spanLat,
			spanLong,
			prevProps.latitude !== latitude ||
			prevProps.longitude !== longitude ||
			prevProps.spanLat !== spanLat ||
			prevProps.spanLong !== spanLong ||
			prevProps.zoomLevel !== zoomLevel ||
			prevProps.width !== width ||
			prevProps.height !== height ||
			prevProps.autoAdjust !== autoAdjust
		) && autoAdjust) {
		if (children !== undefined && children.length) {
			children.forEach(child => {
				if (child.props.isAnnotation) {
					if(child.props.id) {
						currentAnnotationIds.push(child.props.id)
					}
					this.updateAnnotation(child.props)
				}
			})
		} else if (children !== undefined && children.props) {
			if (children.props.isAnnotation) {
				if(children.props.id) {
					currentAnnotationIds.push(children.props.id)
				}
		const prevChildren = prevProps.children
		if (prevChildren !== undefined && prevChildren.length) {
			prevChildren.forEach(child => {
				const id = child.props.id
				if(id === undefined) {
					return
				}
				if(child.props.isAnnotation && !currentAnnotationIds.includes(id) && id in this.annotations) {
					this.removeAnnotation(child.props)
				}
			})
		} else if (prevChildren !== undefined && prevChildren.props) {
			const child = prevChildren
			const id = child.props.id
			if(id === undefined) {
				return
			}
			if(child.props.isAnnotation && !currentAnnotationIds.includes(id) && id in this.annotations) {
				this.removeAnnotation(child.props)
			}
		}

		let checkCurrentLocationLatitudeChange, checkCurrentLocationLongitudeChange, checkCurrentLocationDirectionChange
tonyduanesmith's avatar
tonyduanesmith committed
		if (typeof children !== 'undefined') {
			const firstChild = children[0] ? children[0] : children
			const prevFirstChild = prevProps.children[0] ? prevProps.children[0] : prevProps.children
			if(firstChild.props && prevFirstChild.props) {
				checkCurrentLocationLatitudeChange = firstChild.props.latitude !== prevFirstChild.props.latitude
				checkCurrentLocationLongitudeChange = firstChild.props.longitude !== prevFirstChild.props.longitude
				checkCurrentLocationDirectionChange = firstChild.props.direction !== prevFirstChild.props.direction
			} else if(firstChild.props && !prevFirstChild.props) {
				checkCurrentLocationLatitudeChange = true
				checkCurrentLocationLongitudeChange = true
				checkCurrentLocationDirectionChange = true
			checkCurrentLocationLatitudeChange ||
			checkCurrentLocationLongitudeChange ||
			checkCurrentLocationDirectionChange
tonyduanesmith's avatar
tonyduanesmith committed
		) {
			if (children !== undefined && children.length) {
				children.forEach(child => {
tonyduanesmith's avatar
tonyduanesmith committed
					if (child.type.name === 'CurrentLocationOverride') {
						this.updateCurrentLocationOverride(child.props)
					}
				})
			} else if (children !== undefined && children.props) {
tonyduanesmith's avatar
tonyduanesmith committed
				if (children.type.name === 'CurrentLocationOverride') {
					this.updateCurrentLocationOverride(children.props)
tonyduanesmith's avatar
tonyduanesmith committed
	createAnnotation(annotationOptions) {
tonyduanesmith's avatar
tonyduanesmith committed
			glyphImage,
			subtitle,
			visible
		let MarkerAnnotation = mapkit.MarkerAnnotation
		let coords = new mapkit.Coordinate(latitude, longitude)
tonyduanesmith's avatar
tonyduanesmith committed
		let newAnnotation = new MarkerAnnotation(coords, {
			color,
			title,
			subtitle,
			selected,
			visible
tonyduanesmith's avatar
tonyduanesmith committed
		})
		glyphText ? (newAnnotation.glyphText = glyphText) : ''
tonyduanesmith's avatar
tonyduanesmith committed
		glyphImage ? (newAnnotation.glyphImage = { 1: glyphImage }) : ''
			console.warn("Apple MapKitJS annotation created without id prop!")
	updateAnnotation(annotationOptions) {
		const {
			id,
			latitude,
			longitude
		} = annotationOptions

		if(id === undefined) {
			return
		}

		if(!(id in this.annotations)) {
			this.createAnnotation(annotationOptions)
			return
		}
		if(latitude !== annotation.coordinate.latitude || longitude !== annotation.coordinate.longitude) {
			annotation.coordinate = new mapkit.Coordinate(latitude, longitude)
		}
	}

	removeAnnotation(annotationOptions) {
		const { id } = annotationOptions

		if(id === undefined) {
			return
		}
		if(!(id in this.annotations)) {
			return
		}

		this.map.removeAnnotation(this.annotations[id])
		delete this.annotations[id]
	}

tonyduanesmith's avatar
tonyduanesmith committed
	createImageAnnotation(annotationOptions) {
		const {
			longitude,
			latitude,
			url,
			selected,
			title,
			subtitle,
			visible
tonyduanesmith's avatar
tonyduanesmith committed
		} = annotationOptions
		let ImageAnnotation = mapkit.ImageAnnotation
		let coords = new mapkit.Coordinate(latitude, longitude)
tonyduanesmith's avatar
tonyduanesmith committed
		let newAnnotation = new ImageAnnotation(coords, {
			title,
			subtitle,
			selected,
tonyduanesmith's avatar
tonyduanesmith committed
			url: { 1: url }
		})
	createCurrentLocationOverride(locationOptions) {
		const { longitude, latitude, direction } = locationOptions
		// AppleMaps needs options structured this way
		const options = {
			data: {
				direction: direction
			}
		}
		const coordinate = new mapkit.Coordinate(latitude, longitude)
		this.currentLocation = new mapkit.Annotation(
tonyduanesmith's avatar
tonyduanesmith committed
				let ctx = this.canvas.getContext('2d')
				ctx.beginPath()
				ctx.translate(150, 135)
				ctx.rotate((options.data.direction * Math.PI) / 180)
				ctx.lineCap = 'round'
				ctx.moveTo(0, 7)
				ctx.lineTo(10, 12)
				ctx.lineTo(0, -13)
				ctx.lineTo(-10, 12)
				ctx.lineTo(0, 7)
				ctx.fillStyle = '#08F'
				ctx.strokeStyle = '#08F'
				ctx.stroke()
				ctx.fill()
tonyduanesmith's avatar
tonyduanesmith committed
				return this.canvas
		this.map.showItems([this.currentLocation])
	}

	updateCurrentLocationOverride(locationOptions) {
		const { longitude, latitude } = locationOptions
		const coordinate = new mapkit.Coordinate(latitude, longitude)
		this.currentLocation.coordinate = coordinate
tonyduanesmith's avatar
tonyduanesmith committed
	setMainCoords() {
		const { longitude, latitude, spanLat, spanLong } = this.props
		this.map.region = new mapkit.CoordinateRegion(
			new mapkit.Coordinate(latitude, longitude),
			new mapkit.CoordinateSpan(spanLat ? spanLat : this.zoomLevel(), spanLong ? spanLong : this.zoomLevel())
tonyduanesmith's avatar
tonyduanesmith committed
	zoomLevel() {
		const { zoomLevel } = this.props
tonyduanesmith's avatar
tonyduanesmith committed
		switch (zoomLevel) {
			case 0:
				return 300
			case 1:
				return 75
			case 2:
				return 18.75
			case 3:
				return 4.68
			case 4:
				return 1.17
			case 5:
				return 0.39
			case 6:
				return 0.073
			case 7:
				return 0.018
			case 8:
				return 0.0045
			default:
				return 0.35
		}
	}

tonyduanesmith's avatar
tonyduanesmith committed
	render() {
		const { width, height } = this.props
tonyduanesmith's avatar
tonyduanesmith committed
		return (
			<div
				id='map'
tonyduanesmith's avatar
tonyduanesmith committed
					width: width,
}

AppleMaps.defaultProps = {
	width: '100wh',
	height: '100vh',
tonyduanesmith's avatar
tonyduanesmith committed
	zoomLevel: 6,
	longitude: 53.8008,
	latitude: -1.5491,
	autoAdjust: false
tonyduanesmith's avatar
tonyduanesmith committed
export default AppleMaps