forked from github/dataease
feat(图表): 地图增加缩放按钮配配置项,适应浅色和深色模式。
This commit is contained in:
parent
5c7e0511aa
commit
3c67956186
@ -449,7 +449,9 @@ export default {
|
||||
latitude: '纬度',
|
||||
gradient: '渐变',
|
||||
layer_controller: '指标切换',
|
||||
suspension: '悬浮',
|
||||
show_zoom: '显示缩放按钮',
|
||||
button_color: '按钮颜色',
|
||||
button_background_color: '按钮背景色',
|
||||
chart_background: '组件背景',
|
||||
date_format: '请选择日期解析格式',
|
||||
solid_color: '纯色',
|
||||
|
@ -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
|
||||
}
|
||||
/**
|
||||
* 表头属性
|
||||
|
@ -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">
|
||||
|
@ -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-->
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
})
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user