perf: 地图热力图优化,淡化logo

This commit is contained in:
chenjinsong
2021-08-15 17:01:46 +08:00
parent cad7c9a12b
commit 2c66482fbb
3 changed files with 509 additions and 23 deletions

View File

@@ -64,3 +64,9 @@ th *:first-letter,
.el-table__empty-block { .el-table__empty-block {
width: 100% !important; width: 100% !important;
} }
/* 淡化amcharts的logo */
g [aria-labelledby$=-title] {
opacity: 0.1;
transform: translate(calc(100% - 76px), calc(100% - 25px));
}

View File

@@ -0,0 +1,485 @@
/**
* HeatLegend module
*/
import { __extends } from 'tslib'
/**
* ============================================================================
* IMPORTS
* ============================================================================
* @hidden
*/
import { Container } from '@amcharts/amcharts4/.internal/core/Container'
import { LinearGradient } from '@amcharts/amcharts4/.internal/core/rendering/fills/LinearGradient'
import { registry } from '@amcharts/amcharts4/.internal/core/Registry'
import { toColor, Color } from '@amcharts/amcharts4/.internal/core/utils/Color'
import { ListTemplate, ListDisposer } from '@amcharts/amcharts4/.internal/core/utils/List'
import { percent } from '@amcharts/amcharts4/.internal/core/utils/Percent'
import { ValueAxis } from '@amcharts/amcharts4/.internal/charts/axes/ValueAxis'
import { AxisRendererX } from '@amcharts/amcharts4/.internal/charts/axes/AxisRendererX'
import { AxisRendererY } from '@amcharts/amcharts4/.internal/charts/axes/AxisRendererY'
import * as $iter from '@amcharts/amcharts4/.internal/core/utils/Iterator'
import * as $type from '@amcharts/amcharts4/.internal/core/utils/Type'
import * as $colors from '@amcharts/amcharts4/.internal/core/utils/Colors'
import { RoundedRectangle } from '@amcharts/amcharts4/.internal/core/elements/RoundedRectangle'
/**
* ============================================================================
* MAIN CLASS
* ============================================================================
* @hidden
*/
/**
* This class creates a link (waved color-filled line) between two nodes in a
* Sankey Diagram.
*
* @see {@link IHeatLegendEvents} for a list of available events
* @see {@link IHeatLegendAdapters} for a list of available Adapters
* @important
*/
const HeatLegend = /** @class */ (function (_super) {
__extends(HeatLegend, _super)
/**
* Constructor
*/
function HeatLegend () {
const _this = _super.call(this) || this
_this.className = 'HeatLegend'
_this.markerContainer = _this.createChild(Container)
_this.markerContainer.shouldClone = false
_this.markerCount = 1
// Create a template container and list for the a marker
const marker = new RoundedRectangle()
marker.minHeight = 6
marker.minWidth = 20
marker.interactionsEnabled = false
marker.fillOpacity = 1
marker.cornerRadius(0, 0, 0, 0)
_this.markerContainer.minHeight = 6
_this.markerContainer.minWidth = 20
_this.orientation = 'horizontal'
_this.markers = new ListTemplate(marker)
_this._disposers.push(new ListDisposer(_this.markers))
_this._disposers.push(_this.markers.template)
_this.applyTheme()
return _this
}
HeatLegend.prototype.getMinFromRules = function (property) {
const series = this.series
if (series) {
let minValue_1
$iter.eachContinue(series.heatRules.iterator(), function (heatRule) {
if (heatRule.property == property) {
minValue_1 = heatRule.min
return false
}
return true
})
return minValue_1
}
}
HeatLegend.prototype.getMaxFromRules = function (property) {
const series = this.series
if (series) {
let maxValue_1
$iter.each(series.heatRules.iterator(), function (heatRule) {
if (heatRule.property == property) {
maxValue_1 = heatRule.max
return false
}
return true
})
return maxValue_1
}
}
/**
*
* @ignore Exclude from docs
*/
HeatLegend.prototype.validate = function () {
_super.prototype.validate.call(this)
this.valueAxis.renderer.inversed = this.reverseOrder
const series = this.series
let minColor = this.minColor
let maxColor = this.maxColor
if (!$type.hasValue(minColor)) {
minColor = toColor(this.getMinFromRules('fill'))
}
if (!$type.hasValue(maxColor)) {
maxColor = toColor(this.getMaxFromRules('fill'))
}
if (series) {
const seriesFill = series.fill
if (!$type.hasValue(minColor) && seriesFill instanceof Color) {
minColor = seriesFill
}
if (!$type.hasValue(maxColor) && seriesFill instanceof Color) {
maxColor = seriesFill
}
}
if (!$type.hasValue(maxColor)) {
maxColor = toColor(this.getMaxFromRules('fill'))
}
let minOpacity = $type.toNumber(this.getMinFromRules('fillOpacity'))
if (!$type.isNumber(minOpacity)) {
minOpacity = 1
}
let maxOpacity = $type.toNumber(this.getMaxFromRules('fillOpacity'))
if (!$type.isNumber(maxOpacity)) {
maxOpacity = 1
}
let minStrokeOpacity = $type.toNumber(this.getMinFromRules('strokeOpacity'))
if (!$type.isNumber(minStrokeOpacity)) {
minStrokeOpacity = 1
}
let maxStrokeOpacity = $type.toNumber(this.getMaxFromRules('strokeOpacity'))
if (!$type.isNumber(maxStrokeOpacity)) {
maxStrokeOpacity = 1
}
const minStroke = toColor(this.getMinFromRules('stroke'))
const maxStroke = toColor(this.getMaxFromRules('stroke'))
// if (series) {
for (var i = 0; i < this.markerCount; i++) {
let marker = this.markers.getIndex(i)
if (!marker) {
marker = this.markers.create()
marker.parent = this.markerContainer
marker.height = percent(100)
marker.width = percent(100)
}
if (this.markerCount == 1) {
const gradient = new LinearGradient()
if (this.reverseOrder) {
gradient.addColor(maxColor, maxOpacity)
gradient.addColor(minColor, minOpacity)
} else {
gradient.addColor(minColor, minOpacity)
gradient.addColor(maxColor, maxOpacity)
}
if (this.orientation == 'vertical') {
gradient.rotation = -90
}
marker.fill = gradient
if ($type.hasValue(minStroke) && $type.hasValue(maxStroke)) {
const strokeGradient = new LinearGradient()
if (this.reverseOrder) {
strokeGradient.addColor(maxStroke, maxStrokeOpacity)
strokeGradient.addColor(minStroke, minStrokeOpacity)
} else {
strokeGradient.addColor(minStroke, minStrokeOpacity)
strokeGradient.addColor(maxStroke, maxStrokeOpacity)
}
if (this.orientation == 'vertical') {
strokeGradient.rotation = -90
}
marker.stroke = strokeGradient
}
} else {
let c = i
if (this.reverseOrder) {
c = this.markerCount - i - 1
}
const color = new Color($colors.interpolate(minColor.rgb, maxColor.rgb, c / this.markerCount))
marker.fill = color
const opacity = minOpacity + (maxOpacity - minOpacity) * c / this.markerCount
marker.fillOpacity = opacity
if ($type.hasValue(minStroke) && $type.hasValue(maxStroke)) {
const color_1 = new Color($colors.interpolate(minStroke.rgb, maxStroke.rgb, c / this.markerCount))
marker.stroke = color_1
const opacity_1 = minStrokeOpacity + (maxStrokeOpacity - minStrokeOpacity) * c / this.markerCount
marker.strokeOpacity = opacity_1
}
}
}
const renderer = this.valueAxis.renderer
if (this.markerCount > 1) {
if (this.orientation == 'horizontal') {
renderer.minGridDistance = this.measuredWidth / this.markerCount
} else {
renderer.minGridDistance = this.measuredHeight / this.markerCount
}
}
this.valueAxis.invalidate()
for (var i = this.markerCount, len = this.markers.length; i < len; i++) {
this.markers.getIndex(i).parent = undefined
}
}
Object.defineProperty(HeatLegend.prototype, 'minColor', {
/**
* Returns minColor value
* @return {Color}
*/
get: function () {
return this.getPropertyValue('minColor')
},
/**
* Min color of a heat legend. If a series is set for the legend, minColor is taken from series.
*
* @param {Color}
*/
set: function (value) {
if (!(value instanceof Color)) {
value = toColor(value)
}
this.setColorProperty('minColor', value, true)
},
enumerable: true,
configurable: true
})
Object.defineProperty(HeatLegend.prototype, 'maxColor', {
/**
* Returns maxColor value
* @return {Color}
*/
get: function () {
return this.getPropertyValue('maxColor')
},
/**
* Max color of a heat legend. If a series is set for the legend, maxColor is taken from series.
*
* @param {Color}
*/
set: function (value) {
if (!(value instanceof Color)) {
value = toColor(value)
}
this.setColorProperty('maxColor', value, true)
},
enumerable: true,
configurable: true
})
Object.defineProperty(HeatLegend.prototype, 'markerCount', {
/**
* Returns number of color squares (markers).
* @return {number}
*/
get: function () {
return this.getPropertyValue('markerCount')
},
/**
* Number of color squares (markers) in the heat legend. If only 1 marker is used, it will be filled with gradient.
*
* @param {number}
*/
set: function (value) {
this.setPropertyValue('markerCount', value, true)
},
enumerable: true,
configurable: true
})
Object.defineProperty(HeatLegend.prototype, 'minValue', {
/**
* Returns minimum value of heat legend.
* @return {number}
*/
get: function () {
return this.getPropertyValue('minValue')
},
/**
* Minimum value of heat legend's value axis. If a series is set for the legend, min is taken from series.
*
* @param {number}
*/
set: function (value) {
this.setPropertyValue('minValue', value)
this.valueAxis.min = value
},
enumerable: true,
configurable: true
})
Object.defineProperty(HeatLegend.prototype, 'maxValue', {
/**
* Returns maximum value of heat legend.
* @return {number}
*/
get: function () {
return this.getPropertyValue('maxValue')
},
/**
* Maximum value of heat legend's value axis. If a series is set for the legend, max is taken from series.
*
* @param {number}
*/
set: function (value) {
this.setPropertyValue('maxValue', value)
this.valueAxis.max = value
},
enumerable: true,
configurable: true
})
Object.defineProperty(HeatLegend.prototype, 'orientation', {
/**
* Returns orientation value.
*
* @return {"horizontal" | "vertical"}
*/
get: function () {
return this.getPropertyValue('orientation')
},
/**
* Heat legend orientation. Note, if you change orientation of a heat legend, you must set value axis renderer properties after that, as with orientation renderer changes.
*
* @param {"horizontal" | "vertical"}
*/
set: function (value) {
this.setPropertyValue('orientation', value, true)
const markerContainer = this.markerContainer
const valueAxis = this.valueAxis
// HORIZONTAL
if (value == 'horizontal') {
if (!$type.hasValue(this.width)) {
this.width = 200
}
this.height = undefined
valueAxis.width = percent(100)
valueAxis.height = undefined
valueAxis.tooltip.pointerOrientation = 'vertical'
this.layout = 'vertical'
markerContainer.width = percent(100)
markerContainer.height = undefined
if (!(valueAxis.renderer instanceof AxisRendererX)) {
valueAxis.renderer = new AxisRendererX()
}
}
// VERTICAL
else {
if (!$type.hasValue(this.height)) {
this.height = 200
}
this.width = undefined
this.layout = 'horizontal'
markerContainer.width = undefined
markerContainer.height = percent(100)
valueAxis.height = percent(100)
valueAxis.width = undefined
valueAxis.tooltip.pointerOrientation = 'horizontal'
if (!(valueAxis.renderer instanceof AxisRendererY)) {
valueAxis.renderer = new AxisRendererY()
}
valueAxis.renderer.inside = true
valueAxis.renderer.labels.template.inside = true
this.markerContainer.reverseOrder = true
}
const renderer = valueAxis.renderer
renderer.grid.template.disabled = true
renderer.axisFills.template.disabled = true
renderer.baseGrid.disabled = true
renderer.labels.template.padding(2, 3, 2, 3)
renderer.minHeight = undefined
renderer.minWidth = undefined
this.markerContainer.layout = value
},
enumerable: true,
configurable: true
})
Object.defineProperty(HeatLegend.prototype, 'valueAxis', {
/**
* Returns valueAxis value.
* @return {ValueAxis}
*/
get: function () {
if (!this._valueAxis) {
this.valueAxis = this.createChild(ValueAxis)
this.valueAxis.shouldClone = false
}
return this._valueAxis
},
/**
* Sets a value axis of heat legend. Value axis for heat legend is created automatically.
* @param {ValueAxis}
*/
set: function (valueAxis) {
this._valueAxis = valueAxis
valueAxis.parent = this
valueAxis.strictMinMax = true
this.orientation = this.orientation
},
enumerable: true,
configurable: true
})
Object.defineProperty(HeatLegend.prototype, 'series', {
/**
* Returns series value.
* @return {Series}
*/
get: function () {
return this._series
},
/**
* You can set series for heat legend. It will take min, max, minColor and maxColor values from this series.
* @param series
*/
set: function (series) {
const _this = this
this._series = series
let dataField = 'value'
try {
const dataFieldDefined = series.heatRules.getIndex(0).dataField
if (dataFieldDefined) {
dataField = dataFieldDefined
}
} catch (err) {
}
this.updateMinMax(series.dataItem.values[dataField].low, series.dataItem.values[dataField].high)
series.dataItem.events.on('calculatedvaluechanged', function (event) {
_this.updateMinMax(series.dataItem.values[dataField].low, series.dataItem.values[dataField].high)
}, undefined, false)
series.heatRules.events.on('inserted', this.invalidate, this, false)
series.heatRules.events.on('removed', this.invalidate, this, false)
},
enumerable: true,
configurable: true
})
/**
* Updates min/max of value axis.
* @ignore
*/
HeatLegend.prototype.updateMinMax = function (min, max) {
const valueAxis = this.valueAxis
if (!$type.isNumber(this.minValue)) {
valueAxis.min = min
valueAxis.invalidate()
}
if (!$type.isNumber(this.maxValue)) {
valueAxis.max = max
valueAxis.invalidate()
}
}
/**
* Processes JSON-based config before it is applied to the object.
*
* @ignore Exclude from docs
* @param config Config
*/
HeatLegend.prototype.processConfig = function (config) {
if (config) {
// Set up series
if ($type.hasValue(config.series) && $type.isString(config.series)) {
if ($type.isString(config.series)) {
if (this.map.hasKey(config.series)) {
config.series = this.map.getKey(config.series)
} else {
const seriesId_1 = config.series
var disposer_1 = this.map.events.on('insertKey', function (ev) {
if (ev.key == seriesId_1) {
this.series = ev.newValue
disposer_1.dispose()
}
}, this)
this._disposers.push(disposer_1)
delete config.series
}
}
}
}
_super.prototype.processConfig.call(this, config)
}
return HeatLegend
}(Container))
export { HeatLegend }
/**
* Register class in system, so that it can be instantiated using its name from
* anywhere.
*
* @ignore
*/
registry.registeredClasses.HeatLegend = HeatLegend
// # sourceMappingURL=HeatLegend.js.map

View File

@@ -190,6 +190,7 @@ import unitConvert, { getUnitType } from '@/utils/unit-convert'
import { chartTableDefaultPageSize, chartTableTopOptions, storageKey, chartPieTableTopOptions, unitTypes } from '@/utils/constants' import { chartTableDefaultPageSize, chartTableTopOptions, storageKey, chartPieTableTopOptions, unitTypes } from '@/utils/constants'
import { get } from '@/utils/http' import { get } from '@/utils/http'
import { replaceUrlPlaceholder, getCapitalGeo, getGeoData, lineToSpace } from '@/utils/tools' import { replaceUrlPlaceholder, getCapitalGeo, getGeoData, lineToSpace } from '@/utils/tools'
import { HeatLegend } from '@/components/amcharts/heatLegend'
export default { export default {
name: 'Chart', name: 'Chart',
@@ -352,12 +353,6 @@ export default {
const polygonSeries = chart.series.push(new am4Maps.MapPolygonSeries()) const polygonSeries = chart.series.push(new am4Maps.MapPolygonSeries())
polygonSeries.useGeodata = true polygonSeries.useGeodata = true
polygonSeries.exclude = ['AQ'] // 排除南极洲 polygonSeries.exclude = ['AQ'] // 排除南极洲
// 鼠标悬停提示
/* const polygonTemplate = polygonSeries.mapPolygons.template
polygonTemplate.tooltipText = '{name}'
polygonTemplate.fontSize = '12px'
const hs = polygonTemplate.states.create('hover')
hs.properties.fill = am4Core.color('#ccc') */
return { return {
chart, chart,
polygonSeries polygonSeries
@@ -443,13 +438,6 @@ export default {
}) })
imageSeries.data = pointData imageSeries.data = pointData
} else if (this.isMapBlock) { } else if (this.isMapBlock) {
polygonSeries.heatRules.push({
property: 'fill',
target: polygonSeries.mapPolygons.template,
min: am4Core.color('#EABA2B'),
max: am4Core.color('#D95D41')
})
const seriesData = data.map(r => { const seriesData = data.map(r => {
const value = r.establishLatency || r.httpResponseLatency || r.sslConLatency || r.sequenceGapLossPercent || r.pktRetransPercent || r.sessions const value = r.establishLatency || r.httpResponseLatency || r.sslConLatency || r.sequenceGapLossPercent || r.pktRetransPercent || r.sessions
return { return {
@@ -460,22 +448,29 @@ export default {
}) })
polygonSeries.data = [...seriesData] polygonSeries.data = [...seriesData]
const sorted = seriesData.sort((a, b) => b.value - a.value) const sorted = seriesData.sort((a, b) => b.value - a.value)
const allZero = this.$_.isEmpty(sorted) || Number(sorted[0].value) === 0 // 数据全为0的情况legend只显示1个颜色
const heatLegend = this.myChart.createChild(am4Maps.HeatLegend) polygonSeries.heatRules.push({
heatLegend.series = polygonSeries property: 'fill',
heatLegend.align = 'center' target: polygonSeries.mapPolygons.template,
heatLegend.minValue = 0 min: am4Core.color('#EABA2B'),
if (!this.$_.isEmpty(sorted)) { max: allZero ? am4Core.color('#EABA2B') : am4Core.color('#D95D41')
heatLegend.maxValue = Number(sorted[0].value) })
}
const heatLegend = this.myChart.createChild(HeatLegend)
heatLegend.markerContainer.height = 6 heatLegend.markerContainer.height = 6
heatLegend.width = am4Core.percent(25) heatLegend.series = polygonSeries
heatLegend.marginLeft = am4Core.percent(4) heatLegend.align = 'left'
heatLegend.markerCount = allZero ? 1 : 3
heatLegend.minValue = 0
heatLegend.fontSize = 12
heatLegend.maxValue = allZero ? 1 : Number(sorted[0].value)
heatLegend.width = allZero ? am4Core.percent(10) : am4Core.percent(25)
heatLegend.marginLeft = 15
heatLegend.valign = 'bottom' heatLegend.valign = 'bottom'
const polygonTemplate = polygonSeries.mapPolygons.template const polygonTemplate = polygonSeries.mapPolygons.template
polygonTemplate.tooltipText = '{name}{title}' polygonTemplate.tooltipText = '{name}{title}'
// polygonTemplate.numberFormatter = new am4Core.NumberFormatter().bigNumberPrefixes
polygonTemplate.nonScalingStroke = true polygonTemplate.nonScalingStroke = true
polygonTemplate.strokeWidth = 0.5 polygonTemplate.strokeWidth = 0.5
} }