mirror of https://gitee.com/antv-l7/antv-l7
parent
985caab0d4
commit
540014e853
|
@ -138,7 +138,11 @@ export default class PickingService implements IPickingService {
|
|||
const pickedFeatureIdx = decodePickingColor(color);
|
||||
if (pickedFeatureIdx !== -1 && !featuresIdMap[pickedFeatureIdx]) {
|
||||
const rawFeature = layer.getSource().getFeatureById(pickedFeatureIdx);
|
||||
features.push(rawFeature);
|
||||
features.push({
|
||||
// @ts-ignore
|
||||
...rawFeature,
|
||||
pickedFeatureIdx,
|
||||
});
|
||||
featuresIdMap[pickedFeatureIdx] = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -250,3 +250,92 @@ export function bBoxToBounds(b1: BBox): IBounds {
|
|||
[b1[2], b1[3]],
|
||||
];
|
||||
}
|
||||
|
||||
export function calDistance(p1: Point, p2: Point) {
|
||||
return Math.sqrt(Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2));
|
||||
}
|
||||
|
||||
function dotMul(v1: Point, v2: Point) {
|
||||
return v1[0] * v2[0] + v1[1] * v2[1];
|
||||
}
|
||||
|
||||
function getMod(v: Point) {
|
||||
return Math.sqrt(v[0] * v[0] + v[1] * v[1]);
|
||||
}
|
||||
|
||||
export function calAngle(v1: Point, v2: Point) {
|
||||
return (
|
||||
(Math.acos(dotMul(v1, v2) / (getMod(v1) * getMod(v2))) * 180) / Math.PI
|
||||
);
|
||||
}
|
||||
|
||||
export function getAngle(v1: Point, v2: Point) {
|
||||
// if(v2[0] < 0) {
|
||||
// return calAngle(v1, v2) + 180
|
||||
// } else {
|
||||
// return calAngle(v1, v2)
|
||||
// }
|
||||
|
||||
if (v2[0] > 0) {
|
||||
if (v2[1] > 0) {
|
||||
// 1
|
||||
return 90 - (Math.atan(v2[1] / v2[0]) * 180) / Math.PI;
|
||||
} else {
|
||||
// 2
|
||||
return 90 + (Math.atan(-v2[1] / v2[0]) * 180) / Math.PI;
|
||||
}
|
||||
} else {
|
||||
if (v2[1] < 0) {
|
||||
// 3
|
||||
return 180 + (90 - (Math.atan(v2[1] / v2[0]) * 180) / Math.PI);
|
||||
} else {
|
||||
// 4
|
||||
return 270 + (Math.atan(v2[1] / -v2[0]) * 180) / Math.PI;
|
||||
}
|
||||
}
|
||||
}
|
||||
interface IPathPoint {
|
||||
start: Point;
|
||||
end: Point;
|
||||
dis: number;
|
||||
rotation: number;
|
||||
duration: number;
|
||||
}
|
||||
|
||||
export function flow(coords: Point[], time: number = 100) {
|
||||
if (!coords || coords.length < 2) {
|
||||
return;
|
||||
}
|
||||
const originVec2: Point = [0, 1];
|
||||
let totalDis = 0;
|
||||
const path: IPathPoint[] = [];
|
||||
for (let i = 0; i < coords.length - 1; i++) {
|
||||
const p1: Point = coords[i];
|
||||
const p2: Point = coords[i + 1];
|
||||
const dis = calDistance(p1, p2);
|
||||
totalDis += dis;
|
||||
|
||||
const direct: Point = [p1[0] - p2[0], p1[1] - p2[1]];
|
||||
// const direct: Point = [p2[0] - p1[0], p2[1] - p1[1]];
|
||||
|
||||
let rotation = getAngle(originVec2, direct);
|
||||
if (i > 0) {
|
||||
const lastRotation = path[i - 1].rotation;
|
||||
if (lastRotation - rotation > 360 - lastRotation + rotation) {
|
||||
rotation = rotation + 360;
|
||||
}
|
||||
}
|
||||
|
||||
path.push({
|
||||
start: p1,
|
||||
end: p2,
|
||||
dis,
|
||||
rotation,
|
||||
duration: 0,
|
||||
});
|
||||
}
|
||||
path.map((point) => {
|
||||
point.duration = time * (point.dis / totalDis);
|
||||
});
|
||||
return path;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,46 @@
|
|||
import { LineLayer, Scene, PointLayer } from '@antv/l7';
|
||||
import {
|
||||
LineLayer,
|
||||
Scene,
|
||||
PointLayer,
|
||||
flow,
|
||||
MarkerLayer,
|
||||
Marker,
|
||||
} from '@antv/l7';
|
||||
import { GaodeMap } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
import { animate, linear } from 'popmotion';
|
||||
|
||||
interface IObject {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
function parseCSV(data: string) {
|
||||
let arr = data.split('\n');
|
||||
if (arr && arr[0]) {
|
||||
let columns = arr[0].replace('\r', '').split(',');
|
||||
let rows = arr.slice(1).map((d: string) => d.split(','));
|
||||
|
||||
let json = rows.map((row: string[]) => {
|
||||
let object: IObject = {};
|
||||
row.map((e: string, i: number) => {
|
||||
let str = e.replace('\r', '');
|
||||
let key = columns[i].replace('\n', '');
|
||||
// console.log('key', key)
|
||||
object[key] = str;
|
||||
return '';
|
||||
});
|
||||
return object;
|
||||
});
|
||||
return json;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function getLngLat(data: any) {
|
||||
return data.map((d: any) => {
|
||||
return [+d.lng, +d.lat];
|
||||
});
|
||||
}
|
||||
export default class Amap2demo_road extends React.Component {
|
||||
// @ts-ignore
|
||||
private scene: Scene;
|
||||
|
@ -14,121 +53,155 @@ export default class Amap2demo_road extends React.Component {
|
|||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new GaodeMap({
|
||||
center: [120.1145, 30.221],
|
||||
pitch: 50,
|
||||
zoom: 16.8,
|
||||
viewMode: '3D',
|
||||
center: [116.35, 40],
|
||||
zoom: 12,
|
||||
// zoom: 3
|
||||
}),
|
||||
});
|
||||
this.scene = scene;
|
||||
|
||||
scene.on('loaded', () => {
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/91d27a97-869a-459b-a617-498dcc9c3e7f.json',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/89aa8682-2245-448b-be0d-710308cd63a6.csv',
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.then((res) => res.text())
|
||||
.then((data) => {
|
||||
scene.addImage(
|
||||
'road',
|
||||
'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*haGlTpW2BQgAAAAAAAAAAAAAARQnAQ',
|
||||
);
|
||||
// @ts-ignore
|
||||
const layer = new LineLayer()
|
||||
.source(data)
|
||||
.size(10)
|
||||
.shape('line')
|
||||
.texture('road')
|
||||
.color('rgb(20, 180, 90)')
|
||||
.animate({
|
||||
interval: 1, // 间隔
|
||||
duration: 1, // 持续时间,延时
|
||||
trailLength: 2, // 流线长度
|
||||
})
|
||||
.style({
|
||||
lineTexture: true, // 开启线的贴图功能
|
||||
iconStep: 200, // 设置贴图纹理的间距
|
||||
});
|
||||
scene.addLayer(layer);
|
||||
const jsonData = parseCSV(data);
|
||||
const lnglatData = getLngLat(jsonData);
|
||||
|
||||
scene.addImage(
|
||||
'start',
|
||||
'https://gw.alipayobjects.com/zos/bmw-prod/ebb0af57-4a8a-46e0-a296-2d51f9fa8007.svg',
|
||||
);
|
||||
scene.addImage(
|
||||
'visitor',
|
||||
'https://gw.alipayobjects.com/zos/bmw-prod/64db255d-b636-4929-b072-068e75178b23.svg',
|
||||
);
|
||||
scene.addImage(
|
||||
'museum',
|
||||
'https://gw.alipayobjects.com/zos/bmw-prod/0630591d-64db-4057-a04d-d65f43aebf0f.svg',
|
||||
);
|
||||
scene.addImage(
|
||||
'supermarket',
|
||||
'https://gw.alipayobjects.com/zos/bmw-prod/ab42799d-dea6-4d37-bd62-3ee3e06bf6c0.svg',
|
||||
);
|
||||
scene.addImage(
|
||||
'tower',
|
||||
'https://gw.alipayobjects.com/zos/bmw-prod/6d27cf89-638c-432b-a8c4-cac289ee98a8.svg',
|
||||
);
|
||||
scene.addImage(
|
||||
'end',
|
||||
'https://gw.alipayobjects.com/zos/bmw-prod/59717737-5652-479f-9e6b-e7d2c5441446.svg',
|
||||
);
|
||||
const imageLayer = new PointLayer()
|
||||
.source(
|
||||
[
|
||||
{
|
||||
lng: 120.11025885601617,
|
||||
lat: 30.22006389085372,
|
||||
icon: 'start',
|
||||
},
|
||||
{
|
||||
lng: 120.11123578376913,
|
||||
lat: 30.220443561196277,
|
||||
icon: 'visitor',
|
||||
},
|
||||
{
|
||||
lng: 120.11408457779198,
|
||||
lat: 30.22019805564678,
|
||||
icon: 'museum',
|
||||
},
|
||||
{
|
||||
lng: 120.11683172384723,
|
||||
lat: 30.21875509667716,
|
||||
icon: 'supermarket',
|
||||
},
|
||||
{
|
||||
lng: 120.11945546294194,
|
||||
lat: 30.218724022876376,
|
||||
icon: 'tower',
|
||||
},
|
||||
{
|
||||
lng: 120.1184189041221,
|
||||
lat: 30.21783201718256,
|
||||
icon: 'end',
|
||||
},
|
||||
],
|
||||
const sd = {
|
||||
type: 'FeatureCollection',
|
||||
name: 'dl2',
|
||||
crs: {
|
||||
type: 'name',
|
||||
properties: { name: 'urn:ogc:def:crs:OGC:1.3:CRS84' },
|
||||
},
|
||||
features: [
|
||||
{
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
type: 'Feature',
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: 'MultiLineString',
|
||||
coordinates: [
|
||||
[
|
||||
// [120.10236740112303, 30.25469303741397],
|
||||
// [120.104341506958, 30.252542952311455],
|
||||
// [120.10622978210449, 30.250096246503063],
|
||||
// [120.10974884033202, 30.248613364842253],
|
||||
// [120.11017799377441, 30.24661143909856],
|
||||
// [120.11069297790527, 30.244387029323946],
|
||||
// [120.11120796203613, 30.24245916678936],
|
||||
// [120.11404037475586, 30.24156937132543],
|
||||
// [120.11773109436037, 30.24194012041444],
|
||||
// [120.12099266052248, 30.241865970708517],
|
||||
// [120.12073516845703, 30.24053126643564],
|
||||
// [120.12219429016112, 30.238455023761645],
|
||||
// [120.12537002563475, 30.240086360983426],
|
||||
// [120.12837409973145, 30.242533316047716],
|
||||
// [120.12760162353517, 30.24661143909856],
|
||||
// [120.12605667114256, 30.249503096524485],
|
||||
// [120.12639999389648, 30.2540999151896],
|
||||
// [120.12579917907715, 30.25521201642245],
|
||||
// [120.12339591979979, 30.25521201642245],
|
||||
// [120.12219429016112, 30.253729211980726],
|
||||
// [120.11979103088379, 30.253877493432157],
|
||||
// [120.11893272399901, 30.251282535717067],
|
||||
// [120.11773109436037, 30.249280664359304],
|
||||
// [120.11507034301759, 30.249058231690526],
|
||||
|
||||
...lnglatData,
|
||||
|
||||
// [
|
||||
// 120.11507034301759,
|
||||
// 30.249058231690526
|
||||
// ],
|
||||
// [
|
||||
// 120.12,
|
||||
// 30.249058231690526
|
||||
// ]
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
.shape('icon', [
|
||||
'start',
|
||||
'visitor',
|
||||
'museum',
|
||||
'supermarket',
|
||||
'tower',
|
||||
'end',
|
||||
])
|
||||
.size(35)
|
||||
],
|
||||
};
|
||||
|
||||
const linelayer = new LineLayer({ blend: 'normal' })
|
||||
.source(sd)
|
||||
.size(2)
|
||||
.shape('line')
|
||||
.color('#8C1EB2')
|
||||
// .animate({
|
||||
// interval: 1, // 间隔
|
||||
// duration: 1, // 持续时间,延时
|
||||
// trailLength: 2, // 流线长度
|
||||
// })
|
||||
.style({
|
||||
offsets: [0, 20],
|
||||
// opacity: 'opacity',
|
||||
sourceColor: '#f00', // 起点颜色
|
||||
targetColor: '#0f0', // 终点颜色
|
||||
});
|
||||
scene.addLayer(imageLayer);
|
||||
|
||||
linelayer.on('inited', () => {
|
||||
const source = linelayer.getSource();
|
||||
const coords = source?.data?.dataArray[0]?.coordinates;
|
||||
|
||||
const path = flow(coords, 50000);
|
||||
|
||||
runPath(path, 0);
|
||||
|
||||
// @ts-ignore
|
||||
function runPath(pathData: any, startIndex: number) {
|
||||
const path = pathData[startIndex];
|
||||
|
||||
if (!path) return;
|
||||
const { start, end, duration, rotation } = path;
|
||||
let startRotation = 360 - scene.getRotation();
|
||||
let timer0 = animate({
|
||||
from: {
|
||||
rotation: startRotation,
|
||||
},
|
||||
to: {
|
||||
rotation: rotation,
|
||||
},
|
||||
ease: linear,
|
||||
duration: 600,
|
||||
onUpdate: (o) => {
|
||||
scene.setRotation(o.rotation);
|
||||
},
|
||||
onComplete: () => {
|
||||
timer0.stop();
|
||||
// @ts-ignore
|
||||
timer0 = null;
|
||||
|
||||
let timer = animate({
|
||||
from: {
|
||||
lng: start[0],
|
||||
lat: start[1],
|
||||
},
|
||||
to: {
|
||||
lng: end[0],
|
||||
lat: end[1],
|
||||
},
|
||||
ease: linear,
|
||||
duration,
|
||||
onUpdate: (o) => {
|
||||
scene.setCenter([o.lng, o.lat]);
|
||||
},
|
||||
onComplete: () => {
|
||||
timer.stop();
|
||||
// @ts-ignore
|
||||
timer = null;
|
||||
setTimeout(() => {
|
||||
runPath(pathData, startIndex + 1);
|
||||
}, 500);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
scene.addLayer(linelayer);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { LineLayer, Scene, PointLayer } from '@antv/l7';
|
||||
import { LineLayer, Scene, PointLayer, Marker, MarkerLayer } from '@antv/l7';
|
||||
import { GaodeMap, GaodeMapV2, Map } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
import { animate, easeInOut } from 'popmotion';
|
||||
|
@ -132,138 +132,15 @@ export default class GridTile2 extends React.Component {
|
|||
lat: 26.852646,
|
||||
},
|
||||
];
|
||||
const planeTarget = {
|
||||
lng2: 111.616049,
|
||||
lat2: 26.335053,
|
||||
};
|
||||
const airLineData = [
|
||||
{
|
||||
name: '常德桃花源机场',
|
||||
lng: 111.641101,
|
||||
lat: 28.91165,
|
||||
...planeTarget,
|
||||
},
|
||||
{
|
||||
name: '芷江机场',
|
||||
lng: 109.709699,
|
||||
lat: 27.442172,
|
||||
...planeTarget,
|
||||
},
|
||||
{
|
||||
name: '铜仁凤凰机场',
|
||||
lng: 109.313971,
|
||||
lat: 27.880629,
|
||||
...planeTarget,
|
||||
},
|
||||
{
|
||||
name: '桂林两江国际机场',
|
||||
lng: 110.049256,
|
||||
lat: 25.210065,
|
||||
...planeTarget,
|
||||
},
|
||||
{
|
||||
name: '长沙黄花国际机场',
|
||||
lng: 113.216412,
|
||||
lat: 28.183613,
|
||||
...planeTarget,
|
||||
},
|
||||
{
|
||||
name: '井冈山机场',
|
||||
lng: 114.745845,
|
||||
lat: 26.852646,
|
||||
...planeTarget,
|
||||
},
|
||||
];
|
||||
|
||||
scene.addImage(
|
||||
'plane',
|
||||
'https://gw.alipayobjects.com/zos/bmw-prod/96327aa6-7fc5-4b5b-b1d8-65771e05afd8.svg',
|
||||
);
|
||||
const airPrtsLayer = new PointLayer()
|
||||
.source(airPorts, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
})
|
||||
.shape('name', 'text')
|
||||
.color('rgb(22,119,255)')
|
||||
.size(10);
|
||||
|
||||
const airLineLayer = new LineLayer({ blend: 'normal' })
|
||||
.source(airLineData, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
x1: 'lng2',
|
||||
y1: 'lat2',
|
||||
},
|
||||
})
|
||||
.shape('arc3d')
|
||||
.size(1)
|
||||
.color('#f00')
|
||||
.style({
|
||||
sourceColor: 'rgb(22,119,255)',
|
||||
targetColor: 'rgba(242,246,250,0.1)',
|
||||
});
|
||||
|
||||
const airPlaneLayer = new LineLayer({ blend: 'normal', zIndex: 1 })
|
||||
.source(airLineData, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng2',
|
||||
y: 'lat2',
|
||||
x1: 'lng',
|
||||
y1: 'lat',
|
||||
},
|
||||
})
|
||||
.shape('arc3d')
|
||||
.texture('plane')
|
||||
.size(30)
|
||||
.color('#f00')
|
||||
.animate({
|
||||
duration: 0.2,
|
||||
interval: 0.2,
|
||||
trailLength: 0.2,
|
||||
})
|
||||
.style({
|
||||
textureBlend: 'replace',
|
||||
lineTexture: true, // 开启线的贴图功能
|
||||
iconStep: 6, // 设置贴图纹理的间距
|
||||
});
|
||||
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/ec5351c9-d22b-4918-ad6c-1838064d3a64.json',
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const layer = new LineLayer({})
|
||||
.source(data)
|
||||
.size(30000)
|
||||
.shape('wall')
|
||||
.style({
|
||||
opacity: 0.4,
|
||||
sourceColor: '#0DCCFF',
|
||||
targetColor: 'rbga(255,255,255, 0)',
|
||||
heightfixed: true,
|
||||
});
|
||||
// scene.addLayer(layer);
|
||||
|
||||
const nameLayer = new PointLayer({ zIndex: 3 })
|
||||
.source(data)
|
||||
.color('rgb(22,119,255)')
|
||||
.size(15)
|
||||
.shape('name', 'text');
|
||||
// scene.addLayer(nameLayer);
|
||||
});
|
||||
|
||||
const img: HTMLImageElement = new Image();
|
||||
img.crossOrigin = 'none';
|
||||
img.src =
|
||||
// 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*UkvYRYS5jTAAAAAAAAAAAAAAARQnAQ';
|
||||
// 'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*6dzKS42L8_8AAAAAAAAAAAAAARQnAQ'
|
||||
'https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*dPgXQJ9eUtoAAAAAAAAAAAAAARQnAQ';
|
||||
img.onload = function() {
|
||||
const data = getImageData(img);
|
||||
|
@ -299,73 +176,51 @@ export default class GridTile2 extends React.Component {
|
|||
.color('rgb(22, 119, 255)')
|
||||
.style({
|
||||
vertexHeightScale: 2000,
|
||||
// opacity: 0.4,
|
||||
sourceColor: '#f00',
|
||||
targetColor: '#0f0',
|
||||
});
|
||||
scene.addLayer(layer);
|
||||
};
|
||||
|
||||
const waveLayer = new PointLayer({ zIndex: 2, blend: 'additive' })
|
||||
scene.addImage(
|
||||
'start',
|
||||
'https://gw.alipayobjects.com/zos/bmw-prod/ebb0af57-4a8a-46e0-a296-2d51f9fa8007.svg',
|
||||
);
|
||||
const imageLayer = new PointLayer()
|
||||
.source(
|
||||
[
|
||||
{ lng: 113, lat: 29, size: 10000 },
|
||||
{ lng: 113.5, lat: 29.5, size: 30000 },
|
||||
{
|
||||
lng: 111.641101,
|
||||
lat: 28.91165,
|
||||
cityData: '城市数据',
|
||||
},
|
||||
],
|
||||
{
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
},
|
||||
)
|
||||
.shape('cityData', 'text')
|
||||
.size(16)
|
||||
.style({
|
||||
textAnchor: 'left', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
|
||||
textOffset: [0, 0], // 文本相对锚点的偏移量 [水平, 垂直]
|
||||
spacing: 2, // 字符间距
|
||||
padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
|
||||
stroke: '#ffffff', // 描边颜色
|
||||
strokeWidth: 0.3, // 描边宽度
|
||||
strokeOpacity: 1.0,
|
||||
});
|
||||
|
||||
const pointLayer = new PointLayer()
|
||||
.source(
|
||||
[
|
||||
{
|
||||
lng: 110.23681640625,
|
||||
lat: 29.64509464986076,
|
||||
size: 74020.50373907911,
|
||||
},
|
||||
{
|
||||
lng: 115.01586914062499,
|
||||
lat: 26.88777988202911,
|
||||
size: 22908.885529976185,
|
||||
},
|
||||
{
|
||||
lng: 111.181640625,
|
||||
lat: 28.724313406473463,
|
||||
size: 73359.37302978932,
|
||||
},
|
||||
{
|
||||
lng: 112.686767578125,
|
||||
lat: 29.257648503615542,
|
||||
size: 18500.90838085843,
|
||||
},
|
||||
{
|
||||
lng: 114.664306640625,
|
||||
lat: 28.98892237190413,
|
||||
size: 20293.183968726793,
|
||||
},
|
||||
{
|
||||
lng: 113.90075683593749,
|
||||
lat: 28.17855984939698,
|
||||
size: 18051.412077639496,
|
||||
},
|
||||
{
|
||||
lng: 111.51123046875,
|
||||
lat: 27.45466493898314,
|
||||
size: 37645.94186119526,
|
||||
},
|
||||
{
|
||||
lng: 110.67626953125,
|
||||
lat: 28.004101830368654,
|
||||
size: 4214.588023703825,
|
||||
},
|
||||
{
|
||||
lng: 114.43359375,
|
||||
lat: 29.477861195816843,
|
||||
size: 61722.01580332115,
|
||||
},
|
||||
{
|
||||
lng: 110.445556640625,
|
||||
lat: 26.96124577052697,
|
||||
size: 70806.75519747598,
|
||||
},
|
||||
{
|
||||
lng: 113.75244140624999,
|
||||
lat: 27.88278388425912,
|
||||
size: 70930.24993464859,
|
||||
lng: 111.641101,
|
||||
lat: 28.91165,
|
||||
},
|
||||
],
|
||||
{
|
||||
|
@ -377,96 +232,45 @@ export default class GridTile2 extends React.Component {
|
|||
},
|
||||
)
|
||||
.shape('circle')
|
||||
.color('rgb(22, 119, 255)')
|
||||
.size('size', (v) => v)
|
||||
.animate(true)
|
||||
.style({
|
||||
unit: 'meter',
|
||||
});
|
||||
.size(35)
|
||||
.color('#fff')
|
||||
.style({});
|
||||
const height = 200;
|
||||
const dom = document.createElement('div');
|
||||
dom.innerHTML = `
|
||||
<div style="width:100px;height:${height}px;position:relative;">
|
||||
<div style="position: absolute;width: 8px;height: 8px;top: 10px;border-radius:5px;background: rgba(150, 238, 150, 1.0);"></div>
|
||||
<div style="position: absolute;width: 2px;height: 100%;top: 10px;left: 3px;background-image: linear-gradient(rgba(150, 238, 150, 0.4), rgba(150, 238, 150, 0))"></div>
|
||||
<div style="
|
||||
position: absolute;
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
left: 15px;top: 5px;
|
||||
background-image: linear-gradient(to right, rgba(150, 238, 150, 0.4), rgba(150, 238, 150, 0));
|
||||
color: #fff;
|
||||
padding-left: 15px;
|
||||
line-height: 20px;
|
||||
font-size: 12px;
|
||||
">
|
||||
城市数据
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const barLayer = new PointLayer({ zIndex: 2, depth: false })
|
||||
.source(
|
||||
[
|
||||
{ lng: 113, lat: 29, size: 10000 },
|
||||
{ lng: 113.5, lat: 29.5, size: 30000 },
|
||||
|
||||
{
|
||||
lng: 110.23681640625,
|
||||
lat: 29.64509464986076,
|
||||
size: 74020.50373907911,
|
||||
},
|
||||
{
|
||||
lng: 115.01586914062499,
|
||||
lat: 26.88777988202911,
|
||||
size: 22908.885529976185,
|
||||
},
|
||||
{
|
||||
lng: 111.181640625,
|
||||
lat: 28.724313406473463,
|
||||
size: 73359.37302978932,
|
||||
},
|
||||
{
|
||||
lng: 112.686767578125,
|
||||
lat: 29.257648503615542,
|
||||
size: 18500.90838085843,
|
||||
},
|
||||
{
|
||||
lng: 114.664306640625,
|
||||
lat: 28.98892237190413,
|
||||
size: 20293.183968726793,
|
||||
},
|
||||
{
|
||||
lng: 113.90075683593749,
|
||||
lat: 28.17855984939698,
|
||||
size: 18051.412077639496,
|
||||
},
|
||||
{
|
||||
lng: 111.51123046875,
|
||||
lat: 27.45466493898314,
|
||||
size: 37645.94186119526,
|
||||
},
|
||||
{
|
||||
lng: 110.67626953125,
|
||||
lat: 28.004101830368654,
|
||||
size: 4214.588023703825,
|
||||
},
|
||||
{
|
||||
lng: 114.43359375,
|
||||
lat: 29.477861195816843,
|
||||
size: 61722.01580332115,
|
||||
},
|
||||
{
|
||||
lng: 110.445556640625,
|
||||
lat: 26.96124577052697,
|
||||
size: 70806.75519747598,
|
||||
},
|
||||
{
|
||||
lng: 113.75244140624999,
|
||||
lat: 27.88278388425912,
|
||||
size: 70930.24993464859,
|
||||
},
|
||||
],
|
||||
{
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
},
|
||||
)
|
||||
.shape('cylinder')
|
||||
.color('rgb(22, 119, 255)')
|
||||
.size('size', (v) => [5, 5, v / 350])
|
||||
.animate(true)
|
||||
.style({
|
||||
opacityLinear: {
|
||||
enable: true, // true - false
|
||||
dir: 'up', // up - down
|
||||
},
|
||||
lightEnable: false,
|
||||
});
|
||||
const markerLayer = new MarkerLayer({});
|
||||
const marker = new Marker()
|
||||
.setLnglat({
|
||||
lng: 111.641101,
|
||||
lat: 28.91165,
|
||||
})
|
||||
.setElement(dom);
|
||||
markerLayer.addMarker(marker);
|
||||
|
||||
scene.on('loaded', () => {
|
||||
// scene.addLayer(pointLayer);
|
||||
// scene.addLayer(imageLayer);
|
||||
scene.addMarkerLayer(markerLayer);
|
||||
|
||||
// scene.addLayer(waveLayer);
|
||||
// scene.addLayer(barLayer);
|
||||
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
import {
|
||||
LineLayer,
|
||||
Scene,
|
||||
PointLayer,
|
||||
flow,
|
||||
MarkerLayer,
|
||||
Marker,
|
||||
} from '@antv/l7';
|
||||
import { GaodeMap } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
interface IObject {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
function parseCSV(data: string) {
|
||||
let arr = data.split('\n');
|
||||
if (arr && arr[0]) {
|
||||
let columns = arr[0].replace('\r', '').split(',');
|
||||
let rows = arr.slice(1).map((d: string) => d.split(','));
|
||||
|
||||
let json = rows.map((row: string[]) => {
|
||||
let object: IObject = {};
|
||||
row.map((e: string, i: number) => {
|
||||
let str = e.replace('\r', '');
|
||||
let key = columns[i].replace('\n', '');
|
||||
object[key] = str;
|
||||
return '';
|
||||
});
|
||||
return object;
|
||||
});
|
||||
return json;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function getLngLat2(data: any) {
|
||||
let res = [];
|
||||
for (let i = 0; i < data.length - 1; i++) {
|
||||
let start = data[i];
|
||||
let end = data[i + 1];
|
||||
res.push({
|
||||
lng1: start.lng,
|
||||
lat1: start.lat,
|
||||
lng2: end.lng,
|
||||
lat2: end.lat,
|
||||
opacity: 0.6,
|
||||
});
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function createMarker(
|
||||
lng: number,
|
||||
lat: number,
|
||||
time: string,
|
||||
loc: string,
|
||||
event: string,
|
||||
) {
|
||||
const dom = document.createElement('div');
|
||||
dom.innerHTML = `
|
||||
<div class="infoPlane" style="
|
||||
zIndex: 99;
|
||||
padding: 5px;
|
||||
border-radius: 6px;
|
||||
background: rgba(173,216,230, 0.8);
|
||||
color: #DC143C;
|
||||
">
|
||||
<div style="
|
||||
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
border-bottom: 1px #DC143C;
|
||||
">${time}</div>
|
||||
|
||||
<div style="
|
||||
height: 1px;
|
||||
width: 95%;
|
||||
margin: 0 auto;
|
||||
background: #DC143C;
|
||||
"></div>
|
||||
|
||||
<div style="
|
||||
font-size: 12px;
|
||||
">${loc}</div>
|
||||
|
||||
<div style="
|
||||
font-size: 12px;
|
||||
">${event}</div>
|
||||
|
||||
</div>
|
||||
`;
|
||||
const marker = new Marker().setLnglat({ lng, lat }).setElement(dom);
|
||||
return marker;
|
||||
}
|
||||
export default class Amap2demo_road extends React.Component {
|
||||
// @ts-ignore
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new GaodeMap({
|
||||
center: [116.35, 40],
|
||||
zoom: 3,
|
||||
style: 'dark',
|
||||
}),
|
||||
});
|
||||
this.scene = scene;
|
||||
|
||||
scene.on('loaded', () => {
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/89aa8682-2245-448b-be0d-710308cd63a6.csv',
|
||||
)
|
||||
.then((res) => res.text())
|
||||
.then((data) => {
|
||||
const jsonData = parseCSV(data);
|
||||
const lnglatData2 = getLngLat2(jsonData);
|
||||
|
||||
const pointLayers = new PointLayer()
|
||||
.source(jsonData, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
})
|
||||
.shape('circle')
|
||||
.size(5)
|
||||
.color('#DC143C');
|
||||
|
||||
scene.addLayer(pointLayers);
|
||||
|
||||
const linelayer = new LineLayer({ blend: 'normal', autoFit: true })
|
||||
.source(lnglatData2, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng1',
|
||||
y: 'lat1',
|
||||
x1: 'lng2',
|
||||
y1: 'lat2',
|
||||
},
|
||||
})
|
||||
.size(2)
|
||||
.shape('arc')
|
||||
.color('#DC143C')
|
||||
.animate({
|
||||
interval: 1, // 间隔
|
||||
duration: 1, // 持续时间,延时
|
||||
trailLength: 2, // 流线长度
|
||||
})
|
||||
.style({
|
||||
opacity: 'opacity',
|
||||
});
|
||||
scene.addLayer(linelayer);
|
||||
|
||||
setTimeout(() => {
|
||||
addMarker(jsonData, 0);
|
||||
}, 600);
|
||||
|
||||
function addMarker(data: any[], index: number) {
|
||||
let d = data[index];
|
||||
if (!d) {
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
let m = createMarker(d.lng, d.lat, d.time, d.loc, d.do);
|
||||
scene.addMarker(m);
|
||||
|
||||
let lineData = cloneDeep(lnglatData2);
|
||||
if (lineData[index]) {
|
||||
lineData[index].opacity = 1;
|
||||
linelayer.setData(lineData);
|
||||
}
|
||||
|
||||
addMarker(data, index + 1);
|
||||
}, 400);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
import {
|
||||
LineLayer,
|
||||
Scene,
|
||||
PointLayer,
|
||||
flow,
|
||||
MarkerLayer,
|
||||
Marker,
|
||||
} from '@antv/l7';
|
||||
import { GaodeMap } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
interface IObject {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
function parseCSV(data: string) {
|
||||
let arr = data.split('\n');
|
||||
if (arr && arr[0]) {
|
||||
let columns = arr[0].replace('\r', '').split(',');
|
||||
let rows = arr.slice(1).map((d: string) => d.split(','));
|
||||
|
||||
let json = rows.map((row: string[]) => {
|
||||
let object: IObject = {};
|
||||
row.map((e: string, i: number) => {
|
||||
let str = e.replace('\r', '');
|
||||
let key = columns[i].replace('\n', '');
|
||||
object[key] = str;
|
||||
return '';
|
||||
});
|
||||
return object;
|
||||
});
|
||||
return json;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function getLngLat2(data: any) {
|
||||
let res = [];
|
||||
for (let i = 0; i < data.length - 1; i++) {
|
||||
let start = data[i];
|
||||
let end = data[i + 1];
|
||||
res.push({
|
||||
lng1: start.lng,
|
||||
lat1: start.lat,
|
||||
lng2: end.lng,
|
||||
lat2: end.lat,
|
||||
opacity: 0.4,
|
||||
});
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
export default class Amap2demo_road extends React.Component {
|
||||
// @ts-ignore
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new GaodeMap({
|
||||
center: [116.35, 40],
|
||||
zoom: 3,
|
||||
style: 'dark',
|
||||
}),
|
||||
});
|
||||
this.scene = scene;
|
||||
|
||||
scene.on('loaded', () => {
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/89aa8682-2245-448b-be0d-710308cd63a6.csv',
|
||||
)
|
||||
.then((res) => res.text())
|
||||
.then((data) => {
|
||||
const jsonData = parseCSV(data);
|
||||
jsonData.map((d: any, i: number) => (d.index = i + 1));
|
||||
|
||||
const lnglatData2 = getLngLat2(jsonData);
|
||||
|
||||
const pointLayers = new PointLayer()
|
||||
.source([jsonData[0]], {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
})
|
||||
.shape('circle')
|
||||
.size(5)
|
||||
.color('#DC143C')
|
||||
.style({
|
||||
opacity: 0.5,
|
||||
});
|
||||
scene.addLayer(pointLayers);
|
||||
|
||||
const pointLayer2 = new PointLayer()
|
||||
.source([jsonData[0]], {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
})
|
||||
.shape('circle')
|
||||
.size(14)
|
||||
.color('rgba(255, 0, 0, 0.01)')
|
||||
// .color('')
|
||||
.style({
|
||||
strokeWidth: 2,
|
||||
stroke: '#f00',
|
||||
opacity: 1,
|
||||
offsets: [21, 2],
|
||||
});
|
||||
scene.addLayer(pointLayer2);
|
||||
|
||||
const pointText = new PointLayer()
|
||||
.source([jsonData[0]], {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
})
|
||||
.shape('index', 'text')
|
||||
.size(18)
|
||||
.color('#f00')
|
||||
.style({
|
||||
textAnchor: 'center',
|
||||
textOffset: [28, 0],
|
||||
textAllowOverlap: true,
|
||||
});
|
||||
|
||||
scene.addLayer(pointText);
|
||||
|
||||
const linelayer = new LineLayer({ blend: 'normal', autoFit: true })
|
||||
.source(lnglatData2, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng1',
|
||||
y: 'lat1',
|
||||
x1: 'lng2',
|
||||
y1: 'lat2',
|
||||
},
|
||||
})
|
||||
.size(2)
|
||||
.shape('arc')
|
||||
.color('#DC143C')
|
||||
.animate({
|
||||
interval: 1, // 间隔
|
||||
duration: 1, // 持续时间,延时
|
||||
trailLength: 2, // 流线长度
|
||||
})
|
||||
.style({
|
||||
opacity: 'opacity',
|
||||
});
|
||||
scene.addLayer(linelayer);
|
||||
setTimeout(() => {
|
||||
addPoint(0);
|
||||
}, 600);
|
||||
function addPoint(index: number) {
|
||||
let d = data[index];
|
||||
if (!d) {
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
let pointData = cloneDeep(jsonData);
|
||||
|
||||
pointLayers.setData(pointData.slice(0, index + 1));
|
||||
pointLayer2.setData(pointData.slice(0, index + 1));
|
||||
pointText.setData(pointData.slice(0, index + 1));
|
||||
|
||||
let lineData = cloneDeep(lnglatData2);
|
||||
if (lineData[index]) {
|
||||
lineData[index].opacity = 1;
|
||||
linelayer.setData(lineData);
|
||||
}
|
||||
|
||||
addPoint(index + 1);
|
||||
}, 400);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
import { LineLayer, Scene } from '@antv/l7';
|
||||
import { LineLayer, Scene, flow } from '@antv/l7';
|
||||
import { GaodeMap } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class Amap2demo_lineLinear extends React.Component {
|
||||
// @ts-ignore
|
||||
private scene: Scene;
|
||||
|
@ -75,6 +74,7 @@ export default class Amap2demo_lineLinear extends React.Component {
|
|||
targetColor: 'rgba(0, 255, 0, 0.2)',
|
||||
})
|
||||
.active(true);
|
||||
|
||||
scene.addLayer(layer);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -75,6 +75,8 @@ import LineWall from './components/linewall'
|
|||
import GridTile from './components/gridTile'
|
||||
import GridTile2 from './components/gridTile2'
|
||||
import Cluster from './components/cluster'
|
||||
import Hot from './components/hot'
|
||||
import Hot2 from './components/hot2'
|
||||
|
||||
// @ts-ignore
|
||||
storiesOf('地图方法', module)
|
||||
|
@ -154,3 +156,6 @@ storiesOf('地图方法', module)
|
|||
.add('GridTile', () => <GridTile/>)
|
||||
.add('GridTile2', () => <GridTile2/>)
|
||||
.add('Cluster', () => <Cluster/>)
|
||||
.add('Hot1', () => <Hot/>)
|
||||
.add('Hot2', () => <Hot2/>)
|
||||
|
||||
|
|
Loading…
Reference in New Issue