feat(图表): 地图增加缩放按钮配配置项,适应浅色和深色模式。

This commit is contained in:
wisonic-s 2024-04-17 12:24:47 +08:00
parent 5c7e0511aa
commit 3c67956186
10 changed files with 167 additions and 72 deletions

View File

@ -449,7 +449,9 @@ export default {
latitude: '纬度',
gradient: '渐变',
layer_controller: '指标切换',
suspension: '悬浮',
show_zoom: '显示缩放按钮',
button_color: '按钮颜色',
button_background_color: '按钮背景色',
chart_background: '组件背景',
date_format: '请选择日期解析格式',
solid_color: '纯色',

View File

@ -161,9 +161,10 @@ declare interface ChartBasicStyle {
*/
areaBorderColor: string
/**
* @deprecated
* 悬浮工具栏
*/
suspension: boolean
suspension?: boolean
/**
* 地图底色
*/
@ -192,6 +193,18 @@ declare interface ChartBasicStyle {
* 环形图/玫瑰图外径占比
*/
radius: number
/**
* 是否显示地图缩放按钮
*/
showZoom: boolean
/**
* 地图缩放按钮颜色
*/
zoomButtonColor: string
/**
* 地图缩放按钮背景颜色
*/
zoomBackground: string
}
/**
* 表头属性

View File

@ -1,6 +1,5 @@
<script lang="ts" setup>
import { computed, nextTick, onMounted, PropType, reactive, ref, watch } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import { getGeoJsonFile, parseJson } from '../../../js/util'
import { forEach, debounce } from 'lodash-es'
import { EmptyBackground } from '@/components/empty-background'
@ -118,14 +117,6 @@ const updateAreaData = debounce(() => {
const onMapMappingChange = () => {
emit('onMapMappingChange', state.mappingForm)
}
const mergeCellMethod = ({ columnIndex }) => {
if (columnIndex === 1) {
return [1, 2]
}
if (columnIndex === 2) {
return [0, 0]
}
}
onMounted(() => {
init()
})
@ -141,7 +132,6 @@ onMounted(() => {
:cell-class-name="'area-map-table-cell-' + themes"
:row-class-name="'area-map-table-row-' + themes"
:data="areaData"
:span-method="mergeCellMethod"
>
<el-table-column label="图形" prop="originName" width="80" show-overflow-tooltip />
<el-table-column width="144">

View File

@ -49,6 +49,7 @@ const changeBasicStyle = (prop?: string, requestData = false) => {
}
const init = () => {
const basicStyle = cloneDeep(props.chart.customAttr.basicStyle)
configCompat(basicStyle)
state.basicStyleForm = defaultsDeep(basicStyle, cloneDeep(DEFAULT_BASIC_STYLE)) as ChartBasicStyle
if (!state.customColor) {
state.customColor = state.basicStyleForm.colors[0]
@ -56,6 +57,12 @@ const init = () => {
}
initTableColumnWidth()
}
const configCompat = (basicStyle: ChartBasicStyle) => {
//
if (basicStyle.suspension === false && basicStyle.showZoom === undefined) {
basicStyle.showZoom = false
}
}
const COLUMN_WIDTH_TYPE = ['table-info', 'table-normal']
const initTableColumnWidth = () => {
if (!COLUMN_WIDTH_TYPE.includes(props.chart.type)) {
@ -230,21 +237,51 @@ onMounted(() => {
</el-form-item>
</el-col>
</el-row>
<el-form-item
class="form-item"
:class="'form-item-' + themes"
v-if="showProperty('suspension')"
>
<el-form-item class="form-item" :class="'form-item-' + themes" v-if="showProperty('zoom')">
<el-checkbox
size="small"
:effect="themes"
v-model="state.basicStyleForm.suspension"
v-model="state.basicStyleForm.showZoom"
:predefine="predefineColors"
@change="changeBasicStyle('suspension')"
@change="changeBasicStyle('zoomShow')"
>
{{ t('chart.suspension') }}
{{ t('chart.show_zoom') }}
</el-checkbox>
</el-form-item>
<div v-if="showProperty('zoom') && state.basicStyleForm.showZoom">
<el-form-item
class="form-item"
:class="'form-item-' + themes"
:label="t('chart.button_color')"
>
<el-color-picker
is-custom
class="color-picker-style"
v-model="state.basicStyleForm.zoomButtonColor"
:persistent="false"
:effect="themes"
:trigger-width="108"
:predefine="predefineColors"
@change="changeBasicStyle('zoomButtonColor')"
/>
</el-form-item>
<el-form-item
class="form-item"
:class="'form-item-' + themes"
:label="t('chart.button_background_color')"
>
<el-color-picker
is-custom
class="color-picker-style"
v-model="state.basicStyleForm.zoomBackground"
:persistent="false"
:effect="themes"
:trigger-width="108"
:predefine="predefineColors"
@change="changeBasicStyle('zoomBackground')"
/>
</el-form-item>
</div>
<!--map end-->

View File

@ -24,7 +24,9 @@ export const DEFAULT_COLOR_CASE: DeepPartial<ChartAttr> = {
areaBorderColor: '#303133',
gaugeStyle: 'default',
tableBorderColor: '#E6E7E4',
tableScrollBarColor: 'rgba(0, 0, 0, 0.15)'
tableScrollBarColor: 'rgba(0, 0, 0, 0.15)',
zoomButtonColor: '#aaa',
zoomBackground: '#fff'
},
misc: {
mapLineGradient: false,
@ -65,7 +67,9 @@ export const DEFAULT_COLOR_CASE_LIGHT: DeepPartial<ChartAttr> = {
areaBorderColor: '#303133',
gaugeStyle: 'default',
tableBorderColor: '#E6E7E4',
tableScrollBarColor: 'rgba(0, 0, 0, 0.15)'
tableScrollBarColor: 'rgba(0, 0, 0, 0.15)',
zoomButtonColor: '#aaa',
zoomBackground: '#fff'
},
misc: {
mapLineGradient: false,
@ -106,7 +110,9 @@ export const DEFAULT_COLOR_CASE_DARK: DeepPartial<ChartAttr> = {
areaBorderColor: '#EBEEF5',
gaugeStyle: 'default',
tableBorderColor: '#CCCCCC',
tableScrollBarColor: 'rgba(255, 255, 255, 0.5)'
tableScrollBarColor: 'rgba(255, 255, 255, 0.5)',
zoomButtonColor: '#aaa',
zoomBackground: '#fff'
},
misc: {
mapLineGradient: false,
@ -244,9 +250,6 @@ export const DEFAULT_MISC: ChartMiscAttr = {
mapLineSourceColor: '#146C94',
mapLineTargetColor: '#576CBC'
}
export const DEFAULT_SUSPENSION = {
show: true
}
export const DEFAULT_MARK = {
fieldId: '',
@ -1364,14 +1367,16 @@ export const DEFAULT_BASIC_STYLE: ChartBasicStyle = {
radarShape: 'polygon',
mapStyle: 'normal',
areaBorderColor: '#EBEEF5',
suspension: true,
areaBaseColor: '#ffffff',
mapSymbolOpacity: 0.7,
mapSymbolStrokeWidth: 2,
mapSymbol: 'circle',
mapSymbolSize: 20,
radius: 80,
innerRadius: 60
innerRadius: 60,
showZoom: true,
zoomButtonColor: '#aaa',
zoomBackground: '#fff'
}
export const BASE_VIEW_CONFIG = {

View File

@ -98,7 +98,7 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
options = this.setupOptions(chart, options, drawOption, geoJson)
const view = new Choropleth(container, options)
const dotLayer = this.getDotLayer(chart, geoJson, drawOption)
this.configZoomButton(view)
this.configZoomButton(chart, view)
view.once('loaded', () => {
view.addLayer(dotLayer)
view.on('fillAreaLayer:click', (ev: MapMouseEvent) => {
@ -178,13 +178,6 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
const curAreaNameMapping = senior.areaMapping?.[areaId]
handleGeoJson(geoJson, curAreaNameMapping)
options.color = hexColorToRGBA(basicStyle.areaBaseColor, basicStyle.alpha)
const suspension = basicStyle.suspension
if (!suspension) {
options = {
...options,
zoom: false
}
}
if (!chart.data?.data?.length || !geoJson?.features?.length) {
options.label && (options.label.field = 'name')
return options
@ -221,8 +214,7 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
this.configLabel,
this.configStyle,
this.configTooltip,
this.configBasicStyle,
this.configLegend
this.configBasicStyle
)(chart, options, extra)
}
}

View File

@ -12,7 +12,7 @@ export const MAP_EDITOR_PROPERTY: EditorProperty[] = [
export const MAP_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
'background-overall-component': ['all'],
'basic-style-selector': ['colors', 'alpha', 'areaBorderColor', 'suspension'],
'basic-style-selector': ['colors', 'alpha', 'areaBorderColor', 'zoom'],
'title-selector': [
'title',
'fontSize',

View File

@ -22,8 +22,11 @@ const { t } = useI18n()
* 地图
*/
export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
properties = MAP_EDITOR_PROPERTY
propertyInner = MAP_EDITOR_PROPERTY_INNER
properties: EditorProperty[] = [...MAP_EDITOR_PROPERTY, 'legend-selector']
propertyInner: EditorPropertyInner = {
...MAP_EDITOR_PROPERTY_INNER,
'legend-selector': ['icon', 'fontSize', 'color']
}
axis = MAP_AXIS_TYPE
axisConfig: AxisConfig = {
xAxis: {
@ -90,15 +93,12 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
active: { stroke: 'green', lineWidth: 1 }
},
tooltip: {},
legend: {
position: 'bottomleft'
},
// 禁用线上地图数据
customFetchGeoData: () => null
}
options = this.setupOptions(chart, options, drawOption, geoJson)
const view = new Choropleth(container, options)
this.configZoomButton(view)
this.configZoomButton(chart, view)
view.once('loaded', () => {
view.on('fillAreaLayer:click', (ev: MapMouseEvent) => {
const data = ev.feature.properties
@ -135,14 +135,6 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
unknown: basicStyle.areaBaseColor
}
}
const suspension = basicStyle.suspension
if (!suspension) {
options = {
...options,
legend: false,
zoom: false
}
}
if (!chart.data?.data?.length || !geoJson?.features?.length) {
options.label && (options.label.field = 'name')
return options

View File

@ -900,9 +900,32 @@ export function getTooltipSeriesTotalMap(data: any[]): Record<string, number> {
})
return result
}
export function configL7Legend(): LegendOptions {
const LEGEND_SHAPE_STYLE_MAP = {
circle: {
borderRadius: '50%'
},
square: {},
triangle: {
borderLeft: '5px solid transparent',
borderRight: '5px solid transparent',
borderBottom: '10px solid var(--bgColor)',
background: 'unset'
},
diamond: {
transform: 'rotate(45deg)'
}
}
export function configL7Legend(chart: Chart): LegendOptions | false {
const { basicStyle } = parseJson(chart.customAttr)
if (basicStyle.suspension === false && basicStyle.showZoom === undefined) {
return false
}
const { legend } = parseJson(chart.customStyle)
if (!legend.show) {
return false
}
return {
position: 'bottomleft',
customContent: (_: string, items: CategoryLegendListItem[]) => {
const showItems = items?.length > 30 ? items.slice(0, 30) : items
if (showItems?.length) {
@ -925,11 +948,22 @@ export function configL7Legend(): LegendOptions {
const domStr = substitute(ITEM_TPL, substituteObj)
const itemDom = createDom(domStr)
// legend 形状用的
itemDom.style.setProperty('--bgColor', item.color)
listDom.appendChild(itemDom)
})
return listDom
}
return ''
},
domStyles: {
'l7plot-legend__category-value': {
fontSize: legend.fontSize + 'px',
color: legend.color
},
'l7plot-legend__category-marker': {
...LEGEND_SHAPE_STYLE_MAP[legend.icon]
}
}
}
}
@ -944,12 +978,18 @@ class CustomZoom extends Zoom {
this.zoomIn
)
const resetBtnIconText = createL7Icon('l7-icon-round')
this['createButton'](resetBtnIconText, 'Reset', 'l7-button-control', container, () => {
this.mapsService.setZoomAndCenter(
this.controlOption['initZoom'],
this.controlOption['center']
)
})
this['zoomResetButton'] = this['createButton'](
resetBtnIconText,
'Reset',
'l7-button-control',
container,
() => {
this.mapsService.setZoomAndCenter(
this.controlOption['initZoom'],
this.controlOption['center']
)
}
)
if (this.controlOption.showZoom) {
this['zoomNumDiv'] = this['createButton'](
'0',
@ -965,19 +1005,44 @@ class CustomZoom extends Zoom {
container,
this.zoomOut
)
const { buttonColor, buttonBackground } = this.controlOption as any
if (buttonColor) {
const elements = [
this.controlOption.zoomInText,
this.controlOption.zoomOutText,
resetBtnIconText
] as HTMLElement[]
setStyle(elements, 'fill', buttonColor)
}
const elements = [this['zoomResetButton'], this['zoomInButton'], this['zoomOutButton']]
if (buttonBackground) {
setStyle(elements, 'background', buttonBackground)
}
setStyle(elements, 'border-bottom', 'none')
this['updateDisabled']()
}
}
export function configL7Zoom(plot: L7Plot<PlotOptions>) {
const options = plot.options
if (options.zoom === false) {
export function configL7Zoom(chart: Chart, plot: L7Plot<PlotOptions>) {
const { basicStyle } = parseJson(chart.customAttr)
if (
(basicStyle.suspension === false && basicStyle.showZoom === undefined) ||
basicStyle.showZoom === false
) {
return
}
plot.once('loaded', () => {
const zoomOptions = {
initZoom: plot.scene.getZoom(),
center: plot.scene.getCenter()
center: plot.scene.getCenter(),
buttonColor: basicStyle.zoomButtonColor,
buttonBackground: basicStyle.zoomBackground
} as any
plot.scene.addControl(new CustomZoom(zoomOptions))
})
}
function setStyle(elements: HTMLElement[], styleProp: string, value) {
elements.forEach(e => {
e.style[styleProp] = value
})
}

View File

@ -15,7 +15,6 @@ import {
ChartLibraryType
} from '@/views/chart/components/js/panel/types'
import { cloneDeep, defaultsDeep } from 'lodash-es'
import { ChoroplethOptions } from '@antv/l7plot/dist/esm/plots/choropleth'
import { parseJson } from '@/views/chart/components/js/util'
export interface L7PlotDrawOptions<P> extends AntVDrawOptions<P> {
@ -47,12 +46,12 @@ export abstract class L7PlotChartView<
defaultsDeep(options.tooltip, tooltip)
return options
}
protected configLegend(_: Chart, options: ChoroplethOptions) {
const legend = configL7Legend()
defaultsDeep(options.legend, legend)
protected configLegend(chart: Chart, options: O): O {
const legend = configL7Legend(chart)
defaultsDeep(options, { legend })
return options
}
protected configEmptyDataStrategy(chart: Chart, options: ChoroplethOptions): ChoroplethOptions {
protected configEmptyDataStrategy(chart: Chart, options: O): O {
const { functionCfg } = parseJson(chart.senior)
const emptyDataStrategy = functionCfg.emptyDataStrategy
if (!emptyDataStrategy || emptyDataStrategy === 'breakLine') {
@ -75,8 +74,8 @@ export abstract class L7PlotChartView<
return options
}
protected configZoomButton(plot: P) {
configL7Zoom(plot)
protected configZoomButton(chart: Chart, plot: P) {
configL7Zoom(chart, plot)
}
protected constructor(name: string, defaultData?: any[]) {
super(ChartLibraryType.L7_PLOT, name)