Tuesday, 30 June 2020
Monday, 29 June 2020
ionic react Here route optimize waypoint sequence
code link: https://github.com/chuanshuoge6/Ionic-Here
long press to add way points, tap to set destination
drive though way points sequentially, route back and forth
check optimize route, way points are reordered for fastest route to cover all way points
route always starts at way point 1 and ends at destination
plan a trip through several cities with route optimization
//here6.jsimport React, { useState, useEffect } from 'react';
import PageForm from './PageForm'
import axios from 'axios';
export default function Here6() {
const [map, setMap] = useState(null)
const [layer, setLayer] = useState(null)
const [optimizeWayPoint, setOptimizeWayPoint] = useState(true)
useEffect(() => {
getMap()
setTimeout(() => {
document.getElementById('refreshButton').click()
}, 1000);
return () => map.dispose();
}, []);
const H = window.H;
const platform = new H.service.Platform({
apikey: "JNIn_O9OQdca51JT5ofoou0WOKdp69bNG-XxHaHqPLo"
});
const defaultLayers = platform.createDefaultLayers();
const getMap = () => {
// Create an instance of the map
const map = new H.Map(
document.getElementById('mapView'),
layer ? layer : defaultLayers.raster.normal.map,
{
// This map is centered over Europe
zoom: 10,
center: { lat: 51.048615, lng: -114.070847 },
pixelRatio: window.devicePixelRatio || 1
}
);
// Enable the event system on the map instance:
const mapEvents = new H.mapevents.MapEvents(map);
let markerNum = 1
// Add longpress listeners:
map.addEventListener('longpress', function (evt) {
const coord = map.screenToGeo(evt.currentPointer.viewportX,
evt.currentPointer.viewportY);
//add a marker with number on left
const svgMarkup = '<svg width="24" height="24" ' +
'xmlns="http://www.w3.org/2000/svg">' +
'<path d="M16.5 24.447v-0.996c3.352 0.099 5.993 1.174 5.993 2.487 0 1.379-2.906 2.56-6.492 2.56s-6.492-1.181-6.492-2.56c0-1.313 2.641-2.389 5.992-2.487v0.996c-2.799 0.069-4.993 0.71-4.993 1.491 0 0.827 2.459 1.623 5.493 1.623 3.033 0 5.492-0.796 5.492-1.623-0.001-0.781-2.194-1.421-4.993-1.491zM10.516 8.995c0-3.033 2.521-5.493 5.556-5.493 3.034 0 5.493 2.46 5.493 5.493 0 2.607-1.818 4.786-4.256 5.348l-1.309 13.219-1.313-13.256c-2.362-0.615-4.171-2.756-4.171-5.311zM16 7.524c0-0.828-0.671-1.498-1.498-1.498s-1.499 0.67-1.499 1.498c0 0.827 0.671 1.498 1.499 1.498s1.498-0.67 1.498-1.498z"></path>' +
'<text x="6" y="18" font-size="12pt" font-family="Arial" font-weight="bold" ' +
'text-anchor="middle" fill="black">${markerText}</text>' +
'</svg>';
const icon = new H.map.Icon(svgMarkup.replace('${markerText}', markerNum))
const marker = new H.map.Marker(coord, { icon: icon })
// add custom data to the marker
marker.setData(markerNum);
markerNum++
map.addObject(marker);
});
let destinationMarker = null
let routeLine = null
// Add tap listeners:
map.addEventListener('tap', function (evt) {
const coord = map.screenToGeo(evt.currentPointer.viewportX,
evt.currentPointer.viewportY);
//remove last destination
if (destinationMarker) { map.removeObject(destinationMarker) }
//remove last route line
if (routeLine) { map.removeObject(routeLine) }
//find nearest marker
calculateRouteFromAtoB(coord)
//add a destination marker
const svgMarkup = '<svg width="24" height="24" ' +
'xmlns="http://www.w3.org/2000/svg">' +
'<path d="M26 4v12h-16v12h-4v-24h20z"></path>' +
'</svg>';
const icon = new H.map.Icon(svgMarkup)
destinationMarker = new H.map.Marker(coord, { icon: icon });
map.addObject(destinationMarker);
})
function calculateRouteFromAtoB(coords) {
//get start and way points
const objects = map.getObjects()
if (objects.length === 0) { return }
var router = platform.getRoutingService(),
routeRequestParams = {
mode: 'fastest;car',
representation: 'display',
routeattributes: 'waypoints,summary,shape,legs',
maneuverattributes: 'direction,action',
//waypoint0: start.lat + ',' + start.lng, // start
//waypoint1: stop1.lat + ',' + stop1.lng, // stop1
//waypoint2: coords.lat + ',' + coords.lng // destination
};
if (document.getElementById('optimizeWayPointCheckBox').checked) {
//reorder waypoint first, then route
let webString = 'https://wse.ls.hereapi.com/2/findsequence.json?start=start;'
+ objects[0].b.lat + ',' + objects[0].b.lng + '&'
let j = 1
for (; j < objects.length; j++) {
const wayPoint = objects[j].b
webString = webString + 'destination' + j.toString() + '=stop' + j.toString() + ';' + wayPoint.lat + ',' + wayPoint.lng + '&'
}
webString = webString + 'end=' + 'destination' + ';' + coords.lat + ',' + coords.lng + '&'
+ 'mode=fastest;car&'
+ 'apiKey=' + 'JNIn_O9OQdca51JT5ofoou0WOKdp69bNG-XxHaHqPLo'
//console.log(webString)
axios.get(webString)
.then(function (response) {
// handle success
const orderedWayPoint = response.data.results[0].waypoints
//console.log(orderedWayPoint);
for (let i = 0; i < orderedWayPoint.length; i++) {
routeRequestParams['waypoint' + i.toString()] = orderedWayPoint[i].lat + ',' + orderedWayPoint[i].lng
}
router.calculateRoute(
routeRequestParams,
onSuccess,
onError
);
})
.catch(function (error) {
// handle error
console.log(error);
})
}
else {
//route waypoint in sequence without optimization
//start and stop on the way
let i = 0
for (; i < objects.length; i++) {
const wayPoint = objects[i].b
routeRequestParams['waypoint' + i.toString()] = wayPoint.lat + ',' + wayPoint.lng
}
//destination
routeRequestParams['waypoint' + i.toString()] = coords.lat + ',' + coords.lng
//console.log(routeRequestParams)
router.calculateRoute(
routeRequestParams,
onSuccess,
onError
);
}
}
function onSuccess(result) {
var route = result.response.route[0];
console.log(route)
//add route to map
var lineString = new H.geo.LineString(),
routeShape = route.shape
routeShape.forEach(function (point) {
var parts = point.split(',');
lineString.pushLatLngAlt(parts[0], parts[1]);
});
routeLine = new H.map.Polyline(lineString, {
style: {
lineWidth: 3,
strokeColor: 'rgba(0, 128, 255, 0.7)'
}
});
// Add the polyline to the map
map.addObject(routeLine);
// And zoom to its bounding rectangle
map.getViewModel().setLookAtData({
bounds: routeLine.getBoundingBox()
});
}
function onError(error) {
alert('Can\'t reach the remote server');
}
// Instantiate the default behavior, providing the mapEvents object:
const behavior = new H.mapevents.Behavior(mapEvents);
setMap(map)
}
const layerChange = async (selected) => {
switch (selected) {
case '1':
await setLayer(defaultLayers.raster.normal.map)
break
case '2':
await setLayer(defaultLayers.raster.normal.transit)
break
case '3':
await setLayer(defaultLayers.raster.normal.mapnight)
break
case '4':
await setLayer(defaultLayers.raster.normal.trafficincidents)
break
case '5':
await setLayer(defaultLayers.raster.normal.xbase)
break
case '6':
await setLayer(defaultLayers.raster.satellite.map)
break
case '7':
await setLayer(defaultLayers.raster.satellite.xbase)
break
case '8':
await setLayer(defaultLayers.raster.terrain.map)
break
case '9':
await setLayer(defaultLayers.raster.terrain.xbase)
break
default:
break
}
document.getElementById('refreshButton').click()
}
return (
// Set a height on the map so it will display
<div id='mapView' style={{ height: '100%' }}>
<button id='refreshButton' onClick={() => { map.dispose(); getMap() }}
style={{
position: 'fixed', top: '10px', left: '10px', zIndex: 2,
border: '2px solid green'
}}
>refresh</button>
<select style={{
position: 'fixed', top: '10px', left: '80px',
height: '18px', width: '90px', zIndex: 2, fontSize: '13px'
}}
onChange={e => layerChange(e.target.value)}
>
<option value="1">default layer</option>
<option value="2">transit</option>
<option value="3">night</option>
<option value="4">accident</option>
<option value="5">xbase</option>
<option value="6">satellite</option>
<option value="7">satellite xbase</option>
<option value="8">terrain</option>
<option value="9">terrain xbase</option>
</select>
<button style={{ position: 'fixed', top: '10px', right: '10px', zIndex: 2 }}
onClick={() => {
const formStyle = document.getElementById('pageForm').style
if (formStyle.display === 'none') {
formStyle.position = 'fixed'
formStyle.top = '30px'
formStyle.right = '10px'
formStyle.zIndex = 2
formStyle.display = 'block'
formStyle.backgroundColor = 'white'
}
else {
formStyle.display = 'none'
}
}}>
<i class="fa fa-bars"></i></button>
<PageForm />
<form style={{
position: 'fixed', top: '40px', left: '10px', zIndex: 2,
backgroundColor: 'white', fontSize: '13px', color: 'red'
}}>
<input type="checkbox" id="optimizeWayPointCheckBox" name="checkbox1"></input>
<label for="checkbox1"><i> optimize route</i></label>
</form>
</div>
);
}
------------------------------
//logs showing way points are reordered
(6) […]
0: Object { id: "start", lat: 41.84166172009164, lng: -87.66660758898932, … }
1: Object { id: "stop2", lat: 44.98497733195176, lng: -93.20431174861855, … }
2: Object { id: "stop4", lat: 39.239226589028085, lng: -94.6008687062527, … }
3: Object { id: "stop3", lat: 38.79007613047233, lng: -90.265330250886, … }
4: Object { id: "stop1", lat: 43.66199109727469, lng: -79.38986887781479, … }
5: Object { id: "destination", lat: 45.47785582867173, lng: -75.69460228415073, … }
length: 6
reference:
http://chuanshuoge2.blogspot.com/2020/06/ionic-react-here-driving-route.html
Optimized Waypoint Sequence for Fastest Car Route
https://developer.here.com/documentation/routing-waypoints/dev_guide/topics/quick-start-simple-car.html
Sunday, 28 June 2020
ionic react Here driving route
code link: https://github.com/chuanshuoge6/Ionic-Here
long press to add start, tap to add destination, fastest route is calculated
add stop on the way
find the fastest route from LA to Alaska via Seattle and Vancouver
//here6.jsimport React, { useState, useEffect } from 'react';
import PageForm from './PageForm'
import { star } from 'ionicons/icons';
export default function Here6() {
const [map, setMap] = useState(null)
const [layer, setLayer] = useState(null)
useEffect(() => {
getMap()
setTimeout(() => {
document.getElementById('refreshButton').click()
}, 1000);
return () => map.dispose();
}, []);
const H = window.H;
const platform = new H.service.Platform({
apikey: "JNIn_O9OQdca51JT5ofoou0WOKdp69bNG-XxHaHqPLo"
});
const defaultLayers = platform.createDefaultLayers();
const getMap = () => {
// Create an instance of the map
const map = new H.Map(
document.getElementById('mapView'),
layer ? layer : defaultLayers.raster.normal.map,
{
// This map is centered over Europe
zoom: 10,
center: { lat: 51.048615, lng: -114.070847 },
pixelRatio: window.devicePixelRatio || 1
}
);
// Enable the event system on the map instance:
const mapEvents = new H.mapevents.MapEvents(map);
let markerNum = 1
// Add longpress listeners:
map.addEventListener('longpress', function (evt) {
const coord = map.screenToGeo(evt.currentPointer.viewportX,
evt.currentPointer.viewportY);
//add a marker with number on left
const svgMarkup = '<svg width="24" height="24" ' +
'xmlns="http://www.w3.org/2000/svg">' +
'<path d="M16.5 24.447v-0.996c3.352 0.099 5.993 1.174 5.993 2.487 0 1.379-2.906 2.56-6.492 2.56s-6.492-1.181-6.492-2.56c0-1.313 2.641-2.389 5.992-2.487v0.996c-2.799 0.069-4.993 0.71-4.993 1.491 0 0.827 2.459 1.623 5.493 1.623 3.033 0 5.492-0.796 5.492-1.623-0.001-0.781-2.194-1.421-4.993-1.491zM10.516 8.995c0-3.033 2.521-5.493 5.556-5.493 3.034 0 5.493 2.46 5.493 5.493 0 2.607-1.818 4.786-4.256 5.348l-1.309 13.219-1.313-13.256c-2.362-0.615-4.171-2.756-4.171-5.311zM16 7.524c0-0.828-0.671-1.498-1.498-1.498s-1.499 0.67-1.499 1.498c0 0.827 0.671 1.498 1.499 1.498s1.498-0.67 1.498-1.498z"></path>' +
'<text x="6" y="18" font-size="12pt" font-family="Arial" font-weight="bold" ' +
'text-anchor="middle" fill="black">${markerText}</text>' +
'</svg>';
const icon = new H.map.Icon(svgMarkup.replace('${markerText}', markerNum))
const marker = new H.map.Marker(coord, { icon: icon })
// add custom data to the marker
marker.setData(markerNum);
markerNum++
map.addObject(marker);
});
let destinationMarker = null
let routeLine = null
// Add tap listeners:
map.addEventListener('tap', function (evt) {
const coord = map.screenToGeo(evt.currentPointer.viewportX,
evt.currentPointer.viewportY);
//remove last destination
if (destinationMarker) { map.removeObject(destinationMarker) }
//remove last route line
if (routeLine) { map.removeObject(routeLine) }
//find nearest marker
calculateRouteFromAtoB(coord)
//add a destination marker
const svgMarkup = '<svg width="24" height="24" ' +
'xmlns="http://www.w3.org/2000/svg">' +
'<path d="M26 4v12h-16v12h-4v-24h20z"></path>' +
'</svg>';
const icon = new H.map.Icon(svgMarkup)
destinationMarker = new H.map.Marker(coord, { icon: icon });
map.addObject(destinationMarker);
})
function calculateRouteFromAtoB(coords) {
//get start and way points
const objects = map.getObjects()
if (objects.length === 0) { return }
//const start = objects[0].b
//const stop1 = objects[1].b
console.log(objects.length)
var router = platform.getRoutingService(),
routeRequestParams = {
mode: 'fastest;car',
representation: 'display',
routeattributes: 'waypoints,summary,shape,legs',
maneuverattributes: 'direction,action',
//waypoint0: start.lat + ',' + start.lng, // start
//waypoint1: stop1.lat + ',' + stop1.lng, // stop1
//waypoint2: coords.lat + ',' + coords.lng // destination
};
//start and stop on the way
let i = 0
for (; i < objects.length; i++) {
const wayPoint = objects[i].b
routeRequestParams['waypoint' + i.toString()] = wayPoint.lat + ',' + wayPoint.lng
}
//destination
routeRequestParams['waypoint' + i.toString()] = coords.lat + ',' + coords.lng
//console.log(routeRequestParams)
router.calculateRoute(
routeRequestParams,
onSuccess,
onError
);
}
function onSuccess(result) {
var route = result.response.route[0];
console.log(route)
//add route to map
var lineString = new H.geo.LineString(),
routeShape = route.shape
routeShape.forEach(function (point) {
var parts = point.split(',');
lineString.pushLatLngAlt(parts[0], parts[1]);
});
routeLine = new H.map.Polyline(lineString, {
style: {
lineWidth: 3,
strokeColor: 'rgba(0, 128, 255, 0.7)'
}
});
// Add the polyline to the map
map.addObject(routeLine);
// And zoom to its bounding rectangle
map.getViewModel().setLookAtData({
bounds: routeLine.getBoundingBox()
});
}
function onError(error) {
alert('Can\'t reach the remote server');
}
// Instantiate the default behavior, providing the mapEvents object:
const behavior = new H.mapevents.Behavior(mapEvents);
setMap(map)
}
const layerChange = async (selected) => {
switch (selected) {
case '1':
await setLayer(defaultLayers.raster.normal.map)
break
case '2':
await setLayer(defaultLayers.raster.normal.transit)
break
case '3':
await setLayer(defaultLayers.raster.normal.mapnight)
break
case '4':
await setLayer(defaultLayers.raster.normal.trafficincidents)
break
case '5':
await setLayer(defaultLayers.raster.normal.xbase)
break
case '6':
await setLayer(defaultLayers.raster.satellite.map)
break
case '7':
await setLayer(defaultLayers.raster.satellite.xbase)
break
case '8':
await setLayer(defaultLayers.raster.terrain.map)
break
case '9':
await setLayer(defaultLayers.raster.terrain.xbase)
break
default:
break
}
document.getElementById('refreshButton').click()
}
return (
// Set a height on the map so it will display
<div id='mapView' style={{ height: '100%' }}>
<button id='refreshButton' onClick={() => { map.dispose(); getMap() }}
style={{
position: 'fixed', top: '10px', left: '10px', zIndex: 2,
border: '2px solid green'
}}
>refresh</button>
<select style={{
position: 'fixed', top: '10px', left: '80px',
height: '18px', width: '90px', zIndex: 2, fontSize: '13px'
}}
onChange={e => layerChange(e.target.value)}
>
<option value="1">default layer</option>
<option value="2">transit</option>
<option value="3">night</option>
<option value="4">accident</option>
<option value="5">xbase</option>
<option value="6">satellite</option>
<option value="7">satellite xbase</option>
<option value="8">terrain</option>
<option value="9">terrain xbase</option>
</select>
<button style={{ position: 'fixed', top: '10px', right: '10px', zIndex: 2 }}
onClick={() => {
const formStyle = document.getElementById('pageForm').style
if (formStyle.display === 'none') {
formStyle.position = 'fixed'
formStyle.top = '30px'
formStyle.right = '10px'
formStyle.zIndex = 2
formStyle.display = 'block'
}
else {
formStyle.display = 'none'
}
}}>
<i class="fa fa-bars"></i></button>
<PageForm />
</div>
);
}
reference:
http://chuanshuoge2.blogspot.com/2020/06/ionic-react-here-find-distance-to.html
Map with Driving Route from A to B
https://developer.here.com/documentation/examples/maps-js/services/map-with-route-from-a-to-b
Saturday, 27 June 2020
ionic react Here geolocate
code link: https://github.com/chuanshuoge6/Ionic-Here
app opens, press search address
type in address, submit
map is zoomed in and centered at address found
zoom out view
if more than 1 address found, map is centered at first address
zoom out and see the second address found
press search button to collapse addresses, press menu button to switch to other pages
//here5.jsimport React, { useState, useEffect } from 'react';
import { Plugins } from '@capacitor/core';
export default function Here5() {
const [map, setMap] = useState(null)
const [layer, setLayer] = useState(null)
const [houseNumber, setHouseNumber] = useState('')
const [street, setStreet] = useState('')
const [city, setCity] = useState('')
const [country, setCountry] = useState('')
const { Geolocation } = Plugins;
useEffect(() => {
getMap()
setTimeout(() => {
document.getElementById('refreshButton').click()
}, 1000);
return () => map.dispose();
}, []);
const H = window.H;
const platform = new H.service.Platform({
apikey: "JNIn_O9OQdca51JT5ofoou0WOKdp69bNG-XxHaHqPLo"
});
const defaultLayers = platform.createDefaultLayers();
const getMap = () => {
// Create an instance of the map
const map = new H.Map(
document.getElementById('mapView'),
layer ? layer : defaultLayers.raster.normal.map,
{
// This map is centered over Europe
zoom: 3,
center: { lat: 48.30432303555956, lng: -104.94466241321628 },
pixelRatio: window.devicePixelRatio || 1
}
);
// Enable the event system on the map instance:
const mapEvents = new H.mapevents.MapEvents(map);
// Instantiate the default behavior, providing the mapEvents object:
const behavior = new H.mapevents.Behavior(mapEvents);
function geocode() {
var geocoder = platform.getGeocodingService()
if (country === '') { return }
var geocodingParameters = {
housenumber: houseNumber,
street: street,
city: city,
country: country,
jsonattributes: 1
};
geocoder.geocode(
geocodingParameters,
onSuccess,
onError
);
}
function onSuccess(result) {
var locations = result.response.view[0].result;
var center = null
for (let i = 0; i < locations.length; i++) {
const svgMarkup = '<svg width="24" height="24" ' +
'xmlns="http://www.w3.org/2000/svg">' +
'<path d="M16.5 24.447v-0.996c3.352 0.099 5.993 1.174 5.993 2.487 0 1.379-2.906 2.56-6.492 2.56s-6.492-1.181-6.492-2.56c0-1.313 2.641-2.389 5.992-2.487v0.996c-2.799 0.069-4.993 0.71-4.993 1.491 0 0.827 2.459 1.623 5.493 1.623 3.033 0 5.492-0.796 5.492-1.623-0.001-0.781-2.194-1.421-4.993-1.491zM10.516 8.995c0-3.033 2.521-5.493 5.556-5.493 3.034 0 5.493 2.46 5.493 5.493 0 2.607-1.818 4.786-4.256 5.348l-1.309 13.219-1.313-13.256c-2.362-0.615-4.171-2.756-4.171-5.311zM16 7.524c0-0.828-0.671-1.498-1.498-1.498s-1.499 0.67-1.499 1.498c0 0.827 0.671 1.498 1.499 1.498s1.498-0.67 1.498-1.498z"></path>' +
'<text x="6" y="18" font-size="12pt" font-family="Arial" font-weight="bold" ' +
'text-anchor="middle" fill="black">${markerText}</text>' +
'</svg>';
const icon = new H.map.Icon(svgMarkup.replace('${markerText}', i + 1))
const position = locations[i].location.displayPosition
console.log(position)
const coord = { lat: position.latitude, lng: position.longitude }
if (i === 0) { center = coord }
const marker = new H.map.Marker(coord, { icon: icon })
map.addObject(marker);
}
//zoom into 1st location found
//create boundary
var CircleBoundary = new H.map.Circle(
new H.geo.Point(center.lat, center.lng), //center
11703, // Radius
{ style: { fillColor: 'rgba(0, 0, 0, 0)' } }
);
map.getViewModel().setLookAtData({
zoom: 15,
bounds: CircleBoundary.getBoundingBox()
});
}
function onError(error) {
alert('Can\'t reach the remote server');
}
geocode()
setMap(map)
}
const layerChange = async (selected) => {
switch (selected) {
case '1':
await setLayer(defaultLayers.raster.normal.map)
break
case '2':
await setLayer(defaultLayers.raster.normal.transit)
break
case '3':
await setLayer(defaultLayers.raster.normal.mapnight)
break
case '4':
await setLayer(defaultLayers.raster.normal.trafficincidents)
break
case '5':
await setLayer(defaultLayers.raster.normal.xbase)
break
case '6':
await setLayer(defaultLayers.raster.satellite.map)
break
case '7':
await setLayer(defaultLayers.raster.satellite.xbase)
break
case '8':
await setLayer(defaultLayers.raster.terrain.map)
break
case '9':
await setLayer(defaultLayers.raster.terrain.xbase)
break
default:
break
}
document.getElementById('refreshButton').click()
}
return (
// Set a height on the map so it will display
<div id='mapView' style={{ height: '100%' }}>
<button id='refreshButton' onClick={() => { map.dispose(); getMap() }}
style={{
position: 'fixed', top: '10px', left: '10px', zIndex: 2,
border: '2px solid green'
}}
>refresh</button>
<select style={{
position: 'fixed', top: '10px', left: '80px',
height: '18px', width: '90px', zIndex: 2, fontSize: '13px'
}}
onChange={e => layerChange(e.target.value)}
>
<option value="1">default layer</option>
<option value="2">transit</option>
<option value="3">night</option>
<option value="4">accident</option>
<option value="5">xbase</option>
<option value="6">satellite</option>
<option value="7">satellite xbase</option>
<option value="8">terrain</option>
<option value="9">terrain xbase</option>
</select>
<span id='headingDom' style={{
position: 'fixed', top: '40px', left: '10px',
zIndex: 2, fontSize: '13px'
}}></span>
<button style={{ position: 'fixed', top: '10px', right: '10px', zIndex: 2 }}
onClick={() => {
const formStyle = document.getElementById('pageForm').style
if (formStyle.display === 'none') {
formStyle.position = 'fixed'
formStyle.top = '30px'
formStyle.right = '10px'
formStyle.zIndex = 2
formStyle.display = 'block'
}
else {
formStyle.display = 'none'
}
}}>
<i class="fa fa-bars"></i></button>
<form id='pageForm' style={{ display: 'none' }}>
<input id='page1' name='page' type='radio' onClick={() => window.location.href = '/tab1'}></input>
<label for="page1" style={{ fontSize: '13px' }}> measure</label><br></br>
<input id='page2' name='page' type='radio' onClick={() => window.location.href = '/tab2'}></input>
<label for="page2" style={{ fontSize: '13px' }}> domMarker</label><br></br>
<input id='page3' name='page' type='radio' onClick={() => window.location.href = '/tab3'}></input>
<label for="page3" style={{ fontSize: '13px' }}> cluster</label><br />
<input id='page4' name='page' type='radio' onClick={() => window.location.href = '/tab4'}></input>
<label for="page4" style={{ fontSize: '13px' }}> kml</label><br />
<input id='page5' name='page' type='radio' onClick={() => window.location.href = '/tab5'}></input>
<label for="page5" style={{ fontSize: '13px' }}> search</label><br />
</form>
<button onClick={() => {
const searchFormStyle = document.getElementById('searchForm').style
if (searchFormStyle.display === 'none') {
searchFormStyle.display = 'block'
searchFormStyle.position = 'fixed'
searchFormStyle.top = '60px'
searchFormStyle.left = '10px'
searchFormStyle.zIndex = 2
}
else {
searchFormStyle.display = 'none'
}
}}
style={{
position: 'fixed', top: '40px', left: '10px', zIndex: 2,
border: '2px solid green'
}}
>search address</button>
<form id='searchForm' style={{ display: 'none' }} onSubmit={e => e.preventDefault()}>
<input id='houseNumber' placeholder='house #' style={{ width: '150px' }}
onChange={e => { setHouseNumber(e.target.value); }}>
</input><br />
<input id='street' placeholder='street' style={{ width: '150px' }}
onChange={e => setStreet(e.target.value)}>
</input><br />
<input id='city' placeholder='city' style={{ width: '150px' }}
onChange={e => setCity(e.target.value)}>
</input><br />
<input id='country' placeholder='country' style={{ width: '150px' }}
onChange={e => setCountry(e.target.value)}></input><br />
<button style={{ border: '2px solid green' }}
onClick={() => {
document.getElementById('refreshButton').click();
setTimeout(() => {
document.getElementById('refreshButton').click();
}, 1000);
}}>
submit</button>
</form>
</div>
);
}
reference:
https://developer.here.com/documentation/examples/maps-js/services/geocode-a-location-from-structured-address
zoom in boundary
https://developer.here.com/documentation/examples/maps-js/maps/custom-zooming-into-bounds
https://developer.here.com/documentation/examples/maps-js/maps/map-using-view-bounds
Friday, 26 June 2020
ionic react Here display kml
draw area on https://google.com/maps/d, export to kml
copy kml file in public folder
open app
tap on area will alter area name
//here4.jsimport React, { useState, useEffect } from 'react';
import { Plugins } from '@capacitor/core';
export default function Here4() {
const [map, setMap] = useState(null)
const [layer, setLayer] = useState(null)
const { Geolocation } = Plugins;
useEffect(() => {
getMap()
setTimeout(() => {
document.getElementById('refreshButton').click()
}, 1000);
return () => map.dispose();
}, []);
const H = window.H;
const platform = new H.service.Platform({
apikey: "JNIn_O9OQdca51JT5ofoou0WOKdp69bNG-XxHaHqPLo"
});
const defaultLayers = platform.createDefaultLayers();
const getMap = () => {
// Create an instance of the map
const map = new H.Map(
document.getElementById('mapView'),
layer ? layer : defaultLayers.raster.normal.map,
{
// This map is centered over Europe
zoom: 2,
center: { lat: 48.30432303555956, lng: -104.94466241321628 },
pixelRatio: window.devicePixelRatio || 1
}
);
// Enable the event system on the map instance:
const mapEvents = new H.mapevents.MapEvents(map);
// Instantiate the default behavior, providing the mapEvents object:
const behavior = new H.mapevents.Behavior(mapEvents);
function renderKML() {
// Create a reader object passing in the URL of our KML file
const reader = new H.data.kml.Reader('areas.kml');
reader.addEventListener("statechange", function (evt) {
if (evt.state === H.data.AbstractReader.State.READY) {
// Get KML layer from the reader object and add it to the map
map.addLayer(reader.getLayer());
reader.getLayer().getProvider().addEventListener("tap", (evt) => {
alert(evt.target.getData().name)
});
}
if (evt.state === H.data.AbstractReader.State.ERROR) {
alert('KML parsing error')
}
});
// Parse the document
reader.parse();
}
renderKML()
setMap(map)
}
const layerChange = async (selected) => {
switch (selected) {
case '1':
await setLayer(defaultLayers.raster.normal.map)
break
case '2':
await setLayer(defaultLayers.raster.normal.transit)
break
case '3':
await setLayer(defaultLayers.raster.normal.mapnight)
break
case '4':
await setLayer(defaultLayers.raster.normal.trafficincidents)
break
case '5':
await setLayer(defaultLayers.raster.normal.xbase)
break
case '6':
await setLayer(defaultLayers.raster.satellite.map)
break
case '7':
await setLayer(defaultLayers.raster.satellite.xbase)
break
case '8':
await setLayer(defaultLayers.raster.terrain.map)
break
case '9':
await setLayer(defaultLayers.raster.terrain.xbase)
break
default:
break
}
document.getElementById('refreshButton').click()
}
return (
// Set a height on the map so it will display
<div id='mapView' style={{ height: '100%' }}>
<button id='refreshButton' onClick={() => { map.dispose(); getMap() }}
style={{
position: 'fixed', top: '10px', left: '10px', zIndex: 2,
border: '2px solid green'
}}
>refresh</button>
<select style={{
position: 'fixed', top: '10px', left: '80px',
height: '18px', width: '90px', zIndex: 2, fontSize: '13px'
}}
onChange={e => layerChange(e.target.value)}
>
<option value="1">default layer</option>
<option value="2">transit</option>
<option value="3">night</option>
<option value="4">accident</option>
<option value="5">xbase</option>
<option value="6">satellite</option>
<option value="7">satellite xbase</option>
<option value="8">terrain</option>
<option value="9">terrain xbase</option>
</select>
<span id='headingDom' style={{
position: 'fixed', top: '40px', left: '10px',
zIndex: 2, fontSize: '13px'
}}></span>
<form style={{ position: 'fixed', top: '10px', right: '10px', zIndex: 2 }}>
<input id='page1' name='page' type='radio' onClick={() => window.location.href = '/tab1'}></input>
<label for="page1" style={{ fontSize: '13px' }}> page 1</label><br></br>
<input id='page2' name='page' type='radio' onClick={() => window.location.href = '/tab2'}></input>
<label for="page2" style={{ fontSize: '13px' }}> page 2</label><br></br>
<input id='page3' name='page' type='radio' onClick={() => window.location.href = '/tab3'}></input>
<label for="page3" style={{ fontSize: '13px' }}> page 3</label>
</form>
</div>
);
}
reference:
https://developer.here.com/blog/how-to-migrate-kml-from-google-to-here-maps-and-xyz
https://developer.here.com/documentation/examples/maps-js/maps/display-kml-on-map
Export map data from Google My Maps to a KML file
https://help.scribblemaps.com/knowledgebase/articles/1917415-export-map-data-from-google-my-maps-to-a-kml-file
https://google.com/maps/d
H.data.kml.Reader
https://developer.here.com/cn/documentation/maps/hls-chn/topics_api/h-data-kml-reader.html
Thursday, 25 June 2020
ionic react Here reverse geocode
tap on point, id and address are shown
addresses are looked up from point latitude and longitude
//here3.js
import React, { useState, useEffect } from 'react';
import { Plugins } from '@capacitor/core';
import '../pages/Tab3.css';
export default function Here3() {
const [map, setMap] = useState(null)
const [layer, setLayer] = useState(null)
const [data, setData] = useState([])
const { Geolocation } = Plugins;
useEffect(() => {
getMap()
generateMarkers()
setTimeout(() => {
document.getElementById('refreshButton').click()
}, 1000);
return () => map.dispose();
}, []);
const generateMarkers = () => {
const xMin = 50.84561389596551
const xMax = 51.21708943492305
const xDiff = xMax - xMin
const yMax = -113.80644441313935
const yMin = -114.36916364528605
const yDiff = yMax - yMin
const randomPositions = []
for (let i = 0; i < 1000; i++) {
const position = {
lat: Math.random() * xDiff + xMin,
lng: Math.random() * yDiff + yMin
}
randomPositions.push(position)
}
setData(randomPositions)
}
const H = window.H;
const platform = new H.service.Platform({
apikey: "JNIn_O9OQdca51JT5ofoou0WOKdp69bNG-XxHaHqPLo"
});
const defaultLayers = platform.createDefaultLayers();
const getMap = () => {
// Create an instance of the map
const map = new H.Map(
document.getElementById('mapView'),
layer ? layer : defaultLayers.raster.normal.map,
{
// This map is centered over Europe
zoom: 10,
center: { lat: 51.048615, lng: -114.070847 },
pixelRatio: window.devicePixelRatio || 1
}
);
// Enable the event system on the map instance:
const mapEvents = new H.mapevents.MapEvents(map);
// Instantiate the default behavior, providing the mapEvents object:
const behavior = new H.mapevents.Behavior(mapEvents);
// create the default UI component, for displaying bubbles
var ui = H.ui.UI.createDefault(map, defaultLayers);
function startClustering(map, data) {
// First we need to create an array of DataPoint objects,
// for the ClusterProvider
var dataPoints = data.map(function (item, index) {
//datapoint ={lat, lng, attitude, data}, id is stored in point.data,
//image URL can be stored in data as well
return new H.clustering.DataPoint(item.lat, item.lng, null, index);
});
// Create a clustering provider with custom options for clusterizing the input
var clusteredDataProvider = new H.clustering.Provider(dataPoints, {
clusteringOptions: {
// Maximum radius of the neighbourhood
eps: 32,
// minimum weight of points required to form a cluster
minWeight: 2
}
});
function reverseGeocode(location) {
var geocoder = platform.getGeocodingService(),
reverseGeocodingParameters = {
prox: location.lat.toString() + ',' + location.lng.toString(),
mode: 'retrieveAddresses',
maxresults: '1',
jsonattributes: 1
};
geocoder.reverseGeocode(
reverseGeocodingParameters,
reverseGeocodeSuccess,
reverseGeocodeError
);
}
function reverseGeocodeSuccess(result) {
const address = result.response.view[0].result;
console.log(address)
document.getElementById('bubbleDomTextArea').innerHTML = address[0].location.address.label
}
function reverseGeocodeError(error) {
console.log(error)
}
// Note that we attach the event listener to the cluster provider, and not to
// the individual markers
clusteredDataProvider.addEventListener('tap', e => {
// Get position of the "clicked" marker
const position = e.target.getGeometry();
const viewportX = (e.currentPointer.viewportX - 70).toString() + 'px'
const viewportY = (e.currentPointer.viewportY - 160).toString() + 'px'
const bubbleId = e.target.data.a.data;
const bubbleDom = document.getElementById('bubbleDom')
bubbleDom.style.position = 'fixed'
bubbleDom.style.top = viewportY
bubbleDom.style.left = viewportX
bubbleDom.style.display = 'block'
bubbleDom.style.zIndex = 2
bubbleDom.style.backgroundColor = 'white'
bubbleDom.style.fontSize = '13px'
bubbleDom.style.width = '150px'
reverseGeocode(position)
document.getElementById('bubbleDomText').innerHTML =
'ID: ' + bubbleId + '<br/>'
// + 'Lat: ' + position.lat.toString() + '<br/>Lng' + position.lng.toString()
}
);
// Create a layer tha will consume objects from our clustering provider
var clusteringLayer = new H.map.layer.ObjectLayer(clusteredDataProvider);
// To make objects from clustering provder visible,
// we need to add our layer to the map
map.addLayer(clusteringLayer);
}
if (data.length > 0) {
startClustering(map, data);
}
setMap(map)
}
const layerChange = async (selected) => {
switch (selected) {
case '1':
await setLayer(defaultLayers.raster.normal.map)
break
case '2':
await setLayer(defaultLayers.raster.normal.transit)
break
case '3':
await setLayer(defaultLayers.raster.normal.mapnight)
break
case '4':
await setLayer(defaultLayers.raster.normal.trafficincidents)
break
case '5':
await setLayer(defaultLayers.raster.normal.xbase)
break
case '6':
await setLayer(defaultLayers.raster.satellite.map)
break
case '7':
await setLayer(defaultLayers.raster.satellite.xbase)
break
case '8':
await setLayer(defaultLayers.raster.terrain.map)
break
case '9':
await setLayer(defaultLayers.raster.terrain.xbase)
break
default:
break
}
document.getElementById('refreshButton').click()
}
return (
// Set a height on the map so it will display
<div id='mapView' style={{ height: '100%' }}>
<button id='refreshButton' onClick={() => { map.dispose(); getMap() }}
style={{
position: 'fixed', top: '10px', left: '10px', zIndex: 2,
border: '2px solid green'
}}
>refresh</button>
<select style={{
position: 'fixed', top: '10px', left: '80px',
height: '18px', width: '90px', zIndex: 2, fontSize: '13px'
}}
onChange={e => layerChange(e.target.value)}
>
<option value="1">default layer</option>
<option value="2">transit</option>
<option value="3">night</option>
<option value="4">accident</option>
<option value="5">xbase</option>
<option value="6">satellite</option>
<option value="7">satellite xbase</option>
<option value="8">terrain</option>
<option value="9">terrain xbase</option>
</select>
<span id='headingDom' style={{
position: 'fixed', top: '40px', left: '10px',
zIndex: 2, fontSize: '13px'
}}></span>
<form style={{ position: 'fixed', top: '10px', right: '10px', zIndex: 2 }}>
<input id='page1' name='page' type='radio' onClick={() => window.location.href = '/tab1'}></input>
<label for="page1" style={{ fontSize: '13px' }}> page 1</label><br></br>
<input id='page2' name='page' type='radio' onClick={() => window.location.href = '/tab2'}></input>
<label for="page2" style={{ fontSize: '13px' }}> page 2</label><br></br>
<input id='page3' name='page' type='radio' onClick={() => window.location.href = '/tab3'}></input>
<label for="page3" style={{ fontSize: '13px' }}> page 3</label>
</form>
<div id='bubbleDom' style={{ display: 'none' }}>
<span style={{ float: 'right', fontSize: '20px', cursor: 'pointer' }}
onClick={() => document.getElementById('bubbleDom').style.display = 'none'}>
X</span>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQleYrlNGWPV7IqQspqT71rj9Ht-gFTGRku4q7anMgFqymF-qDI&usqp=CAU"
style={{ marginLeft: '20px' }}
alt="house for sale" width="100" height="100"></img><br />
<span id='bubbleDomText'></span>
<textarea id='bubbleDomTextArea' rows='2' cols='20' wrap="hard"
style={{ resize: 'none', borderWidth: 0 }}></textarea>
</div>
</div>
);
}
reference:
https://developer.here.com/documentation/examples/maps-js/services/reverse-geocode-an-address-from-location
http://chuanshuoge2.blogspot.com/2020/06/ionic-react-here-marker-cluster-2.html
Subscribe to:
Posts (Atom)