React JSON ファイルを地理的な場所にバインド
Ignite UI for React Map マップは、さまざまな種類のファイルからロードされた地理データをプロットできます。たとえば、JavaScript Object Notation (JSON) ファイルから地理的位置をロードできます。
React JSON ファイルを地理的な場所にバインドの例
export default class WorldUtils {
public static calcPaths(origin: any, dest: any): any[] {
let interval = 200;
let paths: any[] = [[]];
let pathID = 0;
let distance = this.calcDistance(origin, dest);
if (distance <= interval) {
paths[pathID].push({ x: origin.lon, y: origin.lat });
paths[pathID].push({ x: dest.lon, y: dest.lat });
} else {
let current = origin;
let previous = origin;
for (let dist = interval; dist <= distance; dist += interval)
{
previous = current
paths[pathID].push({ x: current.lon, y: current.lat });
let bearing = this.calcBearing(current, dest);
current = this.calcDestination(current, bearing, interval);
if (previous.lon > 150 && current.lon < -150) {
paths[pathID].push({ x: 180, y: current.lat });
paths.push([]);
pathID++
current = { lon: -180, lat: current.lat }
} else if (previous.lon < -150 && current.lon > 150) {
paths[pathID].push({ x: -180, y: current.lat });
paths.push([]);
pathID++
current = { lon: 180, lat: current.lat }
}
}
paths[pathID].push({ x: dest.lon, y: dest.lat });
}
return paths;
}
public static calcBearing(origin: any, dest: any): number
{
origin = this.toRadianLocation(origin);
dest = this.toRadianLocation(dest);
let range = (dest.lon - origin.lon);
let y = Math.sin(range) * Math.cos(dest.lat);
let x = Math.cos(origin.lat) * Math.sin(dest.lat) -
Math.sin(origin.lat) * Math.cos(dest.lat) * Math.cos(range);
let angle = Math.atan2(y, x);
return this.toDegreesNormalized(angle);
}
public static calcDestination(origin: any, bearing: number, distance: number): any {
let radius = 6371.0;
origin = this.toRadianLocation(origin);
bearing = this.toRadians(bearing);
distance = distance / radius;
let lat = Math.asin(Math.sin(origin.lat) * Math.cos(distance) +
Math.cos(origin.lat) * Math.sin(distance) * Math.cos(bearing));
let x = Math.sin(bearing) * Math.sin(distance) * Math.cos(origin.lat);
let y = Math.cos(distance) - Math.sin(origin.lat) * Math.sin(origin.lat);
let lon = origin.lon + Math.atan2(x, y);
lon = (lon + 3 * Math.PI) % (2 * Math.PI) - Math.PI;
lon = this.toDegrees(lon);
lat = this.toDegrees(lat);
return { lon: lon, lat: lat };
}
public static calcDistance(origin: any, dest: any): number {
origin = this.toRadianLocation(origin);
dest = this.toRadianLocation(dest);
let sinProd = Math.sin(origin.lat) * Math.sin(dest.lat);
let cosProd = Math.cos(origin.lat) * Math.cos(dest.lat);
let lonDelta = (dest.lon - origin.lon);
let angle = Math.acos(sinProd + cosProd * Math.cos(lonDelta));
let distance = angle * 6371.0;
return distance;
}
public static toRadianLocation(geoPoint: any): any {
let x = this.toRadians(geoPoint.lon);
let y = this.toRadians(geoPoint.lat);
return { lon: x, lat: y };
}
public static toRadians(degrees: number): number
{
return degrees * Math.PI / 180;
}
public static toDegrees(radians: number): number {
return (radians * 180.0 / Math.PI);
}
public static toDegreesNormalized(radians: number): number
{
let degrees = this.toDegrees(radians);
degrees = (degrees + 360) % 360;
return degrees;
}
public static toStringLat(latitude: number): string {
let str = Math.abs(latitude).toFixed(1) + "°";
return latitude > 0 ? str + "N" : str + "S";
}
public static toStringLon(coordinate: number): string {
let val = Math.abs(coordinate);
let str = val < 100 ? val.toFixed(1) : val.toFixed(0);
return coordinate > 0 ? str + "°E" : str + "°W";
}
public static toStringAbbr(value: number): string {
if (value > 1000000000000) {
return (value / 1000000000000).toFixed(1) + " T"
} else if (value > 1000000000) {
return (value / 1000000000).toFixed(1) + " B"
} else if (value > 1000000) {
return (value / 1000000).toFixed(1) + " M"
} else if (value > 1000) {
return (value / 1000).toFixed(1) + " K"
}
return value.toFixed(0);
}
public static getLongitude(location: any): number {
if (location.x) return location.x;
if (location.lon) return location.lon;
if (location.longitude) return location.longitude;
return Number.NaN;
}
public static getLatitude(location: any): number {
if (location.y) return location.y;
if (location.lat) return location.lat;
if (location.latitude) return location.latitude;
return Number.NaN;
}
public static getBounds(locations: any[]): any {
let minLat = 90;
let maxLat = -90;
let minLon = 180;
let maxLon = -180;
for (const location of locations) {
const crrLon = this.getLongitude(location);
if (!Number.isNaN(crrLon)) {
minLon = Math.min(minLon, crrLon);
maxLon = Math.max(maxLon, crrLon);
}
const crrLat = this.getLatitude(location);
if (!Number.isNaN(crrLat)) {
minLat = Math.min(minLat, crrLat);
maxLat = Math.max(maxLat, crrLat);
}
}
const geoBounds = {
left: minLon,
top: minLat,
width: Math.abs(maxLon - minLon),
height: Math.abs(maxLat - minLat)
};
return geoBounds;
}
public static getNightShapes(): any[] {
let nightShape = [];
let line: any[] = [];
for (let lon = -180; lon <= 180; lon += 1) {
let x = lon;
let y = 75 * Math.cos(lon * Math.PI / 180);
line.push({x: x, y: y});
}
let coordinateLine = {points: [line]};
nightShape.push(coordinateLine);
return nightShape;
}
}
ts
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import WorldUtils from "./WorldUtils"
import { IgrGeographicMapModule } from "@infragistics/igniteui-react-maps";
import { IgrGeographicMap } from "@infragistics/igniteui-react-maps";
import { IgrGeographicSymbolSeries } from "@infragistics/igniteui-react-maps";
import { IgrDataChartInteractivityModule } from "@infragistics/igniteui-react-charts";
import { IgrDataContext } from "@infragistics/igniteui-react-core";
import { MarkerType } from "@infragistics/igniteui-react-charts";
IgrGeographicMapModule.register();
IgrDataChartInteractivityModule.register();
export default class MapBindingDataJsonPoints extends React.Component {
public geoMap: IgrGeographicMap;
constructor(props: any) {
super(props);
this.onMapRef = this.onMapRef.bind(this);
}
public render(): JSX.Element {
return (
<div className="container sample">
<div className="container" >
<IgrGeographicMap
ref={this.onMapRef}
width="100%"
height="100%"
zoomable="true"/>
</div>
<div className="overlay-bottom-right overlay-border">Imagery Tiles: @OpenStreetMap</div>
</div>
);
}
public onMapRef(geoMap: IgrGeographicMap) {
if (!geoMap) { return; }
this.geoMap = geoMap;
this.geoMap.updateZoomWindow({ left: 0.2, top: 0.1, width: 0.6, height: 0.6 });
}
public componentDidMount() {
fetch("https://static.infragistics.com/xplatform/data/WorldCities.json")
.then((response) => response.json())
.then(data => this.onDataLoaded(data));
}
public onDataLoaded(jsonData: any[]) {
const geoLocations: any[] = [];
for (const jsonItem of jsonData) {
if (jsonItem.cap) {
const location = {
latitude: jsonItem.lat,
longitude: jsonItem.lon,
population: jsonItem.pop,
city: jsonItem.name,
country: jsonItem.country
};
geoLocations.push(location);
}
}
const geoSeries = new IgrGeographicSymbolSeries( { name: "series" });
geoSeries.dataSource = geoLocations;
geoSeries.markerType = MarkerType.Circle;
geoSeries.latitudeMemberPath = "latitude";
geoSeries.longitudeMemberPath = "longitude";
geoSeries.markerBrush = "LightGray";
geoSeries.markerOutline = "Black";
geoSeries.tooltipTemplate = this.createTooltip;
this.geoMap.series.add(geoSeries);
}
public createTooltip(context: any) {
const dataContext = context.dataContext as IgrDataContext;
if (!dataContext) return null;
const series = dataContext.series as any;
if (!series) return null;
const dataItem = dataContext.item as any;
if (!dataItem) return null;
const pop = dataItem.population.toFixed(1) + " M";
const lat = WorldUtils.toStringLat(dataItem.latitude);
const lon = WorldUtils.toStringLon(dataItem.longitude);
return <div>
<div className="tooltipTitle" >{dataItem.city}</div>
<div className="tooltipBox">
<div className="tooltipRow">
<div className="tooltipLbl">Latitude:</div>
<div className="tooltipVal">{lat}</div>
</div>
<div className="tooltipRow">
<div className="tooltipLbl">Longitude:</div>
<div className="tooltipVal">{lon}</div>
</div>
<div className="tooltipRow">
<div className="tooltipLbl">Population</div>
<div className="tooltipVal">{pop}</div>
</div>
</div>
</div>
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<MapBindingDataJsonPoints/>);
tsx
このサンプルが気に入りましたか? 完全な Ignite UI for Reactツールキットにアクセスして、すばやく独自のアプリの作成を開始します。無料でダウンロードできます。
データ例
JSON ファイルからのデータの例:
[
{ "name": "Sydney Island", "lat": -16.68972, "lon": 139.45917 },
{ "name": "Sydney Creek", "lat": -16.3, "lon": 128.95 },
{ "name": "Mount Sydney", "lat": -21.39864, "lon": 121.193 },
]
json
コード スニペット
以下のコードは、マップコンポーネント内の IgrGeographicHighDensityScatterSeries
を、ロードされた JSON ファイルから作成された地理的位置を含むオブジェクトの配列にバインドします。
import { IgrGeographicSymbolSeries } from 'igniteui-react-maps';
import { MarkerType } from 'igniteui-react-charts';
public componentDidMount() {
fetch(url + "/Data/WorldCities.json")
.then((response) => response.text())
.then(data => this.onDataLoaded(data));
}
public onDataLoaded(jsonData: any[]) {
const geoLocations: any[] = [];
for (const jsonItem of jsonData) {
if (jsonItem.cap) {
const location = {
latitude: jsonItem.lat,
longitude: jsonItem.lon,
population: jsonItem.pop,
city: jsonItem.name,
country: jsonItem.country
};
geoLocations.push(location);
}
}
const geoSeries = new IgrGeographicSymbolSeries( { name: "series" });
geoSeries.dataSource = geoLocations;
geoSeries.markerType = MarkerType.Circle;
geoSeries.latitudeMemberPath = "latitude";
geoSeries.longitudeMemberPath = "longitude";
geoSeries.markerBrush = "LightGray";
geoSeries.markerOutline = "Black";
this.geoMap.series.add(geoSeries);
}
ts
API リファレンス