mirror of
https://github.com/mempool/mempool.git
synced 2024-11-20 02:11:49 +01:00
Rewrite channels map component using native echart
This commit is contained in:
parent
c0e6b7af58
commit
d6a42cdf6b
@ -20,7 +20,11 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
|
||||
@Input() publicKey: string | undefined;
|
||||
|
||||
observable$: Observable<any>;
|
||||
center: number[] | undefined = undefined;
|
||||
|
||||
center: number[] | undefined;
|
||||
zoom: number | undefined;
|
||||
channelWidth = 0.6;
|
||||
channelOpacity = 0.1;
|
||||
|
||||
chartInstance = undefined;
|
||||
chartOptions: EChartsOption = {};
|
||||
@ -42,7 +46,8 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
|
||||
ngOnDestroy(): void {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.center = this.style === 'widget' ? [0, 0, -10] : undefined;
|
||||
this.center = this.style === 'widget' ? [0, 40] : [0, 5];
|
||||
this.zoom = this.style === 'widget' ? 3.5 : 1.3;
|
||||
|
||||
if (this.style === 'graph') {
|
||||
this.seoService.setTitle($localize`Lightning nodes channels world map`);
|
||||
@ -69,29 +74,46 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
|
||||
thisNodeGPS = [channel[6], channel[7]];
|
||||
}
|
||||
|
||||
channelsLoc.push([[channel[2], channel[3]], [channel[6], channel[7]]]);
|
||||
// We add a bit of noise so nodes at the same location are not all
|
||||
// on top of each other
|
||||
let random = Math.random() * 2 * Math.PI;
|
||||
let random2 = Math.random() * 0.01;
|
||||
|
||||
if (!nodesPubkeys[channel[0]]) {
|
||||
nodes.push({
|
||||
publicKey: channel[0],
|
||||
name: channel[1],
|
||||
value: [channel[2], channel[3]],
|
||||
});
|
||||
nodesPubkeys[channel[0]] = true;
|
||||
nodes.push([
|
||||
channel[2] + random2 * Math.cos(random),
|
||||
channel[3] + random2 * Math.sin(random),
|
||||
1,
|
||||
channel[0],
|
||||
channel[1]
|
||||
]);
|
||||
nodesPubkeys[channel[0]] = nodes[nodes.length - 1];
|
||||
}
|
||||
|
||||
random = Math.random() * 2 * Math.PI;
|
||||
random2 = Math.random() * 0.01;
|
||||
|
||||
if (!nodesPubkeys[channel[4]]) {
|
||||
nodes.push({
|
||||
publicKey: channel[4],
|
||||
name: channel[5],
|
||||
value: [channel[6], channel[7]],
|
||||
});
|
||||
nodesPubkeys[channel[4]] = true;
|
||||
nodes.push([
|
||||
channel[6] + random2 * Math.cos(random),
|
||||
channel[7] + random2 * Math.sin(random),
|
||||
1,
|
||||
channel[4],
|
||||
channel[5]
|
||||
]);
|
||||
nodesPubkeys[channel[4]] = nodes[nodes.length - 1];
|
||||
}
|
||||
|
||||
const channelLoc = [];
|
||||
channelLoc.push(nodesPubkeys[channel[0]].slice(0, 2));
|
||||
channelLoc.push(nodesPubkeys[channel[4]].slice(0, 2));
|
||||
channelsLoc.push(channelLoc);
|
||||
}
|
||||
if (this.style === 'nodepage' && thisNodeGPS) {
|
||||
// 1ML 0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266
|
||||
// New York GPS [-74.0068, 40.7123]
|
||||
// Map center [-20.55, 0, -9.85]
|
||||
this.center = [thisNodeGPS[0] * -20.55 / -74.0068, 0, thisNodeGPS[1] * -9.85 / 40.7123];
|
||||
this.center = [thisNodeGPS[0], thisNodeGPS[1]];
|
||||
this.zoom = 10;
|
||||
this.channelWidth = 1;
|
||||
this.channelOpacity = 1;
|
||||
}
|
||||
|
||||
this.prepareChartOptions(nodes, channelsLoc);
|
||||
@ -115,87 +137,84 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
this.chartOptions = {
|
||||
silent: this.style === 'widget' ? true : false,
|
||||
silent: this.style === 'widget',
|
||||
title: title ?? undefined,
|
||||
geo3D: {
|
||||
map: 'world',
|
||||
shading: 'color',
|
||||
tooltip: {},
|
||||
geo: {
|
||||
animation: false,
|
||||
silent: true,
|
||||
postEffect: {
|
||||
enable: true,
|
||||
bloom: {
|
||||
intensity: 0.1,
|
||||
}
|
||||
},
|
||||
viewControl: {
|
||||
center: this.center,
|
||||
minDistance: 1,
|
||||
maxDistance: 60,
|
||||
distance: this.style === 'widget' ? 22 : this.style === 'nodepage' ? 22 : 60,
|
||||
alpha: 90,
|
||||
rotateSensitivity: 0,
|
||||
panSensitivity: this.style === 'widget' ? 0 : 1,
|
||||
zoomSensitivity: this.style === 'widget' ? 0 : 0.5,
|
||||
panMouseButton: this.style === 'widget' ? null : 'left',
|
||||
rotateMouseButton: undefined,
|
||||
center: this.center,
|
||||
zoom: this.zoom,
|
||||
tooltip: {
|
||||
show: true
|
||||
},
|
||||
map: 'world',
|
||||
roam: this.style === 'widget' ? false : true,
|
||||
itemStyle: {
|
||||
color: 'white',
|
||||
opacity: 0.02,
|
||||
borderWidth: 1,
|
||||
borderColor: 'black',
|
||||
color: '#ffffff44'
|
||||
},
|
||||
regionHeight: 0.01,
|
||||
scaleLimit: {
|
||||
min: 1.3,
|
||||
max: 100000,
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
// @ts-ignore
|
||||
type: 'lines3D',
|
||||
coordinateSystem: 'geo3D',
|
||||
blendMode: 'lighter',
|
||||
lineStyle: {
|
||||
width: 1,
|
||||
opacity: ['widget', 'graph'].includes(this.style) ? 0.025 : 1,
|
||||
large: true,
|
||||
progressive: 200,
|
||||
type: 'scatter',
|
||||
data: nodes,
|
||||
coordinateSystem: 'geo',
|
||||
geoIndex: 0,
|
||||
symbolSize: 4,
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(17, 19, 31, 1)',
|
||||
borderRadius: 4,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||
textStyle: {
|
||||
color: '#b1b1b1',
|
||||
align: 'left',
|
||||
},
|
||||
borderColor: '#000',
|
||||
formatter: (value) => {
|
||||
const data = value.data;
|
||||
const alias = data[4].length > 0 ? data[4] : data[3].slice(0, 20);
|
||||
return `<b style="color: white">${alias}</b>`;
|
||||
}
|
||||
},
|
||||
data: channels
|
||||
itemStyle: {
|
||||
color: 'white',
|
||||
borderColor: 'black',
|
||||
borderWidth: 2,
|
||||
opacity: 1,
|
||||
},
|
||||
blendMode: 'lighter',
|
||||
zlevel: 1,
|
||||
},
|
||||
{
|
||||
// @ts-ignore
|
||||
type: 'scatter3D',
|
||||
symbol: 'circle',
|
||||
blendMode: 'lighter',
|
||||
coordinateSystem: 'geo3D',
|
||||
symbolSize: 3,
|
||||
itemStyle: {
|
||||
color: '#BBFFFF',
|
||||
opacity: 1,
|
||||
borderColor: '#FFFFFF00',
|
||||
large: true,
|
||||
progressive: 200,
|
||||
silent: true,
|
||||
type: 'lines',
|
||||
coordinateSystem: 'geo',
|
||||
data: channels,
|
||||
lineStyle: {
|
||||
opacity: this.channelOpacity,
|
||||
width: this.channelWidth,
|
||||
curveness: 0,
|
||||
color: '#466d9d',
|
||||
},
|
||||
data: nodes,
|
||||
emphasis: {
|
||||
label: {
|
||||
position: 'top',
|
||||
color: 'white',
|
||||
fontSize: 16,
|
||||
formatter: function(value) {
|
||||
return value.name;
|
||||
},
|
||||
show: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
blendMode: 'lighter',
|
||||
tooltip: {
|
||||
show: false,
|
||||
},
|
||||
zlevel: 2,
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
@HostListener('window:wheel', ['$event'])
|
||||
onWindowScroll(e): void {
|
||||
// Not very smooth when using the mouse
|
||||
if (this.style === 'widget' && e.target.tagName === 'CANVAS') {
|
||||
window.scrollBy({left: 0, top: e.deltaY, behavior: 'auto'});
|
||||
}
|
||||
}
|
||||
|
||||
onChartInit(ec) {
|
||||
if (this.chartInstance !== undefined) {
|
||||
return;
|
||||
@ -213,12 +232,32 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
this.chartInstance.on('click', (e) => {
|
||||
if (e.data && e.data.publicKey) {
|
||||
if (e.data) {
|
||||
this.zone.run(() => {
|
||||
const url = new RelativeUrlPipe(this.stateService).transform(`/lightning/node/${e.data.publicKey}`);
|
||||
const url = new RelativeUrlPipe(this.stateService).transform(`/lightning/node/${e.data[3]}`);
|
||||
this.router.navigate([url]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.chartInstance.on('georoam', (e) => {
|
||||
if (!e.zoom || this.style === 'nodepage') {
|
||||
return;
|
||||
}
|
||||
|
||||
const speed = 0.005;
|
||||
const chartOptions = {
|
||||
series: this.chartOptions.series
|
||||
};
|
||||
|
||||
chartOptions.series[1].lineStyle.opacity += e.zoom > 1 ? speed : -speed;
|
||||
chartOptions.series[1].lineStyle.width += e.zoom > 1 ? speed : -speed;
|
||||
chartOptions.series[0].symbolSize += e.zoom > 1 ? speed * 10 : -speed * 10;
|
||||
chartOptions.series[1].lineStyle.opacity = Math.max(0.05, Math.min(0.5, chartOptions.series[1].lineStyle.opacity));
|
||||
chartOptions.series[1].lineStyle.width = Math.max(0.5, Math.min(1, chartOptions.series[1].lineStyle.width));
|
||||
chartOptions.series[0].symbolSize = Math.max(4, Math.min(5.5, chartOptions.series[0].symbolSize));
|
||||
|
||||
this.chartInstance.setOption(chartOptions);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user