ng-environment-setup
Version:
ng environment setup
418 lines (387 loc) • 10.6 kB
text/typescript
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import * as echarts from 'echarts'
import { ChartService } from '@app/core/chart.service';
import { HttpService } from '@app/core/http.service';
import { Subject } from 'rxjs';
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.scss']
})
export class MapComponent implements OnInit {
constructor(
public chart: ChartService,
public http: HttpService,
) { }
// 地图配置
public options: any = {}
// 标记数据
public data: any = {
// 城市编码
code: 150000,
// 热力图
hot: {},
// 线路图
line: {},
// 线路点标记
point: {},
// 图标标记
market: {},
// 柱状标记
bar: {},
// geo配置
geo: null,
// regions配置
regions: null,
// 提示框配置
tooltip: null,
// 地图颜色列表
colorList: []
}
// 图形标记
public symbol = {
wind: 'image:///assets/img/wind.svg',
fire: 'image:///assets/img/fire.svg',
water: 'image:///assets/img/water.svg',
light: 'image:///assets/img/light.svg',
electricity: 'image:///assets/img/electricity.svg'
}
// 图表加载完毕
public chartFinished = new Subject()
// 地图数据配置
@Input()
set config(data: any) {
if (data) {
this.data = data
this.getGeoJson(data.code || 150000)
}
}
get config(): any {
return this.data
}
// 是否有背景
@Input() hasBackground = true
// 改变城市
@Output() cityChange = new EventEmitter<any>()
/**
* 图表初始化
* @param instance 图表实例
*/
chartInit(instance: any) {
instance.on('finished', () => {
this.chartFinished.next(instance)
})
}
/**
* 地图点击事件
* @param params 当前标记点数据
*/
chartClick(params: any) {
const { data } = params
if (data && data.code && data.level === 'city') {
this.cityChange.emit(data.code)
}
}
/**
* 设置基础地图配置
* @param cityCode 城市编码
* @param features 当前地图子级数据
* @param base 基础地图配置
*/
setBaseOptions(cityCode: number | string, features: any[] = [], base: any = {}) {
const { tooltip = {}, geo, regions, colorList, ...others } = this.getObjectData(base)
const colors = (this.isArray(colorList) && colorList.length) ? colorList
: ['#5AD7FF', '#17DCE4', '#17DCE4', '#618AFF', '#10C5FF', '#93E5FF', '#10C5FF', '#6077DB', '#58FEFE', '#58FEFE', '#10C5FF', '#17DCE4']
return {
tooltip: {
trigger: 'item',
...tooltip
},
geo: {
map: cityCode,
scaleLimit: {
min: 1.2,
max: 1.2
},
label: {
color: '#333',
},
emphasis: {
label: {
color: '#333',
}
},
regions: this.isArray(features) ? features.map((x, xIndex) => ({
name: x.properties && x.properties.name,
label: {
show: true,
color: '#fff'
},
itemStyle: {
color: colors[xIndex % colors.length]
},
emphasis: {
label: {
color: '#fff'
},
itemStyle: {
color: '#ffe364'
}
},
...regions
})) : [],
...geo
},
series: [],
...others
}
}
/**
* 设置热力图配置
* @param options 当前配置
* @param features 当前地图子级数据
* @param hot 热力图配置
*/
setHotOptions(options: any = {}, features: any[] = [], hot: any = {}) {
const { data, visualMap = {}, unit = '' } = this.getObjectData(hot)
if (this.isArray(data) && this.isArray(features)) {
const values = data.map(x => x.value)
const min = Math.min(...values)
const max = Math.max(...values)
options.visualMap = {
seriesIndex: 0,
bottom: 100,
right: 30,
hoverLink: false,
textStyle: {
color: '#A7D3FF'
},
inRange: {
color: ['#945EFF', '#10C5FF', '#58FEFE']
},
min,
max,
text: [min + unit, max + unit],
...visualMap
}
options.series.push({
type: 'map',
geoIndex: 0,
data: features.map((x) => {
const properties = x.properties || {}
const find = data.find(f => f.name === properties.name) || {}
return {
...find,
name: properties.name,
code: properties.adcode,
level: properties.level,
value: find.value || 0
}
})
})
}
return options
}
/**
* 设置线路图配置
* @param options 当前配置
* @param line 线路图配置
*/
setLineOptions(options: any = {}, line: any = {}) {
const { data, legend = {}, color = [] } = this.getObjectData(line)
if (this.isArray(data)) {
options.legend = {
data: data.map((d, dIndex) => ({
name: d.name,
itemStyle: {
color: color[dIndex % color.length]
}
})),
icon: 'circle',
itemWidth: 12,
itemHeight: 12,
itemGap: 10,
bottom: 20,
right: 30,
width: 50,
orient: 'vertical',
textStyle: {
fontSize: 12,
padding: [3, 0, 0, 3],
color: '#A7D3FF'
},
...legend
}
options.series.push(...data.map((d, dIndex) => ({
type: 'lines',
coordinateSystem: 'geo',
zlevel: 2,
effect: {
show: true,
constantSpeed: 30,
symbol: 'arrow',
color: '#fff',
symbolSize: 6,
trailLength: 0,
},
lineStyle: {
width: 2,
opacity: 1,
curveness: 0.2,
color: color[dIndex % color.length]
},
...d,
})))
}
return options
}
/**
* 设置线路图点标记配置
* @param options 当前配置
* @param point 线路图点标记配置
*/
setPointOptions(options: any = {}, point: any = {}) {
const { data, series = {} } = this.getObjectData(point)
if (this.isArray(data)) {
options.series.push({
name: '地点',
type: 'scatter',
coordinateSystem: 'geo',
symbolSize: 10,
data,
...series
})
}
return options
}
/**
* 设置图标标记配置
* @param options 当前配置
* @param market 图标标记配置
*/
setMarketOptions(options: any = {}, market: any= {}) {
const { data, series = {} } = this.getObjectData(market)
if (this.isArray(data)) {
options.series.push({
name: '图标标记',
type: 'scatter',
coordinateSystem: 'geo',
symbolSize: 20,
data: data.map(d => ({
...d,
...(d.symbol ? { symbol: this.symbol[d.symbol] || d.symbol } : {})
})),
...series
})
}
return options
}
/**
* 设置柱状图标记配置
* @param bar 柱状图标记配置
*/
setBarOptions(bar: any= {}): void {
const { data, scale = 0.16, grid = {}, xAxis = {}, yAxis = {}, series = {} } = this.getObjectData(bar)
if (this.isArray(data)) {
this.chartFinished.subscribe((chartInstance: any) => {
const options = chartInstance.getOption()
options.grid = []
options.yAxis = []
options.xAxis = []
data.map((m, mIndex) => {
const pixel = chartInstance.convertToPixel('geo', m.value)
const height = Math.floor(m.data * scale)
options.grid.push({
width: 14,
height,
left: pixel[0],
top: pixel[1] - height,
...grid
})
options.yAxis.push({
type: 'value',
show: false,
gridIndex: mIndex,
...yAxis
})
options.xAxis.push({
type: 'value',
show: false,
gridIndex: mIndex,
...xAxis
})
options.series.push({
data: [m.data],
type: 'bar',
barWidth: 14,
zlevel: 5,
xAxisIndex: mIndex,
yAxisIndex: mIndex,
label: {
show: true,
position: 'top',
color: '#fff',
fontSize: 16,
fontWeight: 500
},
itemStyle: {
color: '#FA8E01',
barBorderRadius: 10
},
...series
})
})
chartInstance.setOption(options)
chartInstance.off('finished')
})
}
}
/**
* 获取城市geo数据
* @param cityCode 城市名称
*/
getGeoJson(cityCode: number) {
this.http.get(`${location.origin}/assets/${cityCode}.json`)
.subscribe((res: any) => {
if (res) {
echarts.registerMap(cityCode, res)
const { hot, line, point, market, bar, ...others } = this.data
// 设置基础地图配置
let options = this.setBaseOptions(cityCode, res.features, others)
// 设置热力图配置
options = this.setHotOptions(options, res.features, hot)
// 设置线路图配置
options = this.setLineOptions(options, line)
// 设置线路图点标记配置
options = this.setPointOptions(options, point)
// 设置图标标记配置
options = this.setMarketOptions(options, market)
// 设置柱状图标记配置
this.setBarOptions(bar)
this.options = { ...options }
}
})
}
/**
* 判断是否是数组
* @param data 数据
*/
isArray(data: any): boolean {
return data instanceof Array
}
/**
* 获取对象数据
* @param data 数据
*/
getObjectData(data: any) {
if (this.isArray(data)) {
return { data }
}
return data
}
/**
* 初始化
*/
ngOnInit() {
}
}