Merge pull request #11129 from dataease/pr@dev-v2@chart-bubble-animate

feat(图表-气泡地图): 气泡添加水波纹动画配置
This commit is contained in:
jianneng-fit2cloud 2024-07-24 10:08:50 +08:00 committed by GitHub
commit 8c7515f5e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 304 additions and 3 deletions

View File

@ -22,6 +22,10 @@ declare interface ChartSenior {
* 区域称映射{区域id: {原始名称: 映射名称}}
*/
areaMapping: Record<string, Record<string, string>>
/**
* 气泡动效
*/
bubbleCfg: BubbleCfg
}
/**
@ -209,3 +213,25 @@ declare interface ScrollCfg {
*/
step: number
}
/**
* 气泡动效设置
*/
declare interface BubbleCfg {
/**
* 开启动效
*/
enable: boolean
/**
* 动效类型
*/
type: 'wave'
/**
* 水波速度
*/
speed: number
/**
* 水波环数
*/
rings: number
}

View File

@ -27,6 +27,7 @@ declare type EditorProperty =
| 'map-symbolic-selector'
| 'flow-map-line-selector'
| 'flow-map-point-selector'
| 'bubble-animate'
declare type EditorPropertyInner = {
[key in EditorProperty]?: string[]
}

View File

@ -19,6 +19,7 @@ import { ElIcon, ElMessage } from 'element-plus-secondary'
import { storeToRefs } from 'pinia'
import { BASE_VIEW_CONFIG } from '../util/chart'
import { cloneDeep, defaultsDeep } from 'lodash-es'
import BubbleAnimateCfg from '@/views/chart/components/editor/editor-senior/components/BubbleAnimateCfg.vue'
const dvMainStore = dvMainStoreWithOut()
const { nowPanelTrackInfo, nowPanelJumpInfo, dvInfo, componentData } = storeToRefs(dvMainStore)
@ -37,7 +38,8 @@ const emit = defineEmits([
'onAssistLineChange',
'onScrollCfgChange',
'onThresholdChange',
'onMapMappingChange'
'onMapMappingChange',
'onBubbleAnimateChange'
])
const props = defineProps({
@ -123,6 +125,11 @@ const onMapMappingChange = val => {
emit('onMapMappingChange', val)
}
const onBubbleAnimateChange = val => {
console.log(val)
emit('onBubbleAnimateChange', val)
}
const showProperties = (prop: EditorProperty) => {
return properties?.value?.includes(prop)
}
@ -359,6 +366,22 @@ const isDataEaseBi = computed(() => appStore.getIsDataEaseBi)
</span>
</div>
</collapse-switch-item>
<collapse-switch-item
:effect="themes"
title="气泡动效"
:change-model="chart.senior.bubbleCfg"
v-if="showProperties('bubble-animate')"
v-model="chart.senior.bubbleCfg.enable"
name="bubbleAnimate"
@modelChange="onBubbleAnimateChange"
>
<bubble-animate-cfg
:themes="themes"
:chart="props.chart"
:property-inner="propertyInnerAll['bubble-animate']"
@onBubbleAnimateChange="onBubbleAnimateChange"
/>
</collapse-switch-item>
</el-collapse>
</el-row>
</div>

View File

@ -0,0 +1,222 @@
<script lang="tsx" setup>
import { PropType, reactive, watch } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
const props = defineProps({
chart: {
type: Object,
required: true
},
themes: {
type: String as PropType<EditorTheme>,
default: 'dark'
},
propertyInner: {
type: Array<string>
}
})
const emit = defineEmits(['onBubbleAnimateChange'])
watch(
() => props.chart.senior.bubbleCfg,
() => {
init()
},
{ deep: true }
)
const state = reactive({
bubbleAnimateForm: {} as BubbleCfg,
isAutoBreakLine: false
})
const onBubbleAnimateChange = () => {
emit('onBubbleAnimateChange', state.bubbleAnimateForm)
}
const changeSpeedSize = v => {
const _v = parseInt(v)
if (_v >= 0 && _v <= 5) {
state.bubbleAnimateForm.speed = _v
} else if (_v < 0) {
state.bubbleAnimateForm.speed = 0
} else if (_v > 5) {
state.bubbleAnimateForm.speed = 5
}
onBubbleAnimateChange()
}
const changeRingsSize = v => {
const _v = parseInt(v)
if (_v >= 0 && _v <= 5) {
state.bubbleAnimateForm.rings = _v
} else if (_v < 0) {
state.bubbleAnimateForm.rings = 0
} else if (_v > 5) {
state.bubbleAnimateForm.rings = 5
}
onBubbleAnimateChange()
}
const init = () => {
const chart = JSON.parse(JSON.stringify(props.chart))
if (chart.senior) {
let senior = null
if (Object.prototype.toString.call(chart.senior) === '[object Object]') {
senior = JSON.parse(JSON.stringify(chart.senior))
} else {
senior = JSON.parse(chart.senior)
}
if (senior.bubbleCfg) {
state.bubbleAnimateForm = senior.bubbleCfg
}
}
}
init()
</script>
<template>
<div :style="{ width: '100%', display: 'block' }" @keydown.stop @keyup.stop>
<el-form
ref="scrollForm"
:model="state.bubbleAnimateForm"
:disabled="!state.bubbleAnimateForm.enable"
label-position="top"
>
<div class="bubble-animate-setting">
<label
class="bubble-animate-label"
style="line-height: 20px"
:class="{ dark: 'dark' === themes }"
>
动效类型
</label>
<el-row style="flex: 1" :gutter="8">
<el-col :span="13">
<el-form-item class="form-item" :class="'form-item-' + themes">
<el-radio-group
style="padding-left: 1px"
size="small"
:effect="themes"
v-model="state.bubbleAnimateForm.type"
@change="onBubbleAnimateChange()"
>
<el-radio :effect="themes" label="wave"> 水波 </el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</div>
<div class="bubble-animate-setting">
<label class="bubble-animate-label" :class="{ dark: 'dark' === themes }"> 动效速率 </label>
<el-row style="flex: 1" :gutter="8">
<el-col :span="13">
<el-form-item class="form-item bubble-animate-slider" :class="'form-item-' + themes">
<el-slider
:effect="themes"
:min="1"
:max="5"
v-model="state.bubbleAnimateForm.speed"
@change="onBubbleAnimateChange()"
/>
</el-form-item>
</el-col>
<el-col :span="11" style="padding-top: 2px">
<el-form-item class="form-item" :class="'form-item-' + themes">
<el-input
type="number"
:effect="themes"
v-model="state.bubbleAnimateForm.speed"
:min="1"
:max="5"
class="basic-input-number"
:controls="false"
@change="changeSpeedSize"
>
</el-input>
</el-form-item>
</el-col>
</el-row>
</div>
<div class="bubble-animate-setting">
<label class="bubble-animate-label" :class="{ dark: 'dark' === themes }"> 水波环数 </label>
<el-row style="flex: 1" :gutter="8">
<el-col :span="13">
<el-form-item class="form-item bubble-animate-slider" :class="'form-item-' + themes">
<el-slider
:effect="themes"
:min="1"
:max="5"
v-model="state.bubbleAnimateForm.rings"
@change="onBubbleAnimateChange()"
/>
</el-form-item>
</el-col>
<el-col :span="11" style="padding-top: 2px">
<el-form-item class="form-item" :class="'form-item-' + themes">
<el-input
type="number"
:effect="themes"
v-model="state.bubbleAnimateForm.rings"
:min="1"
:max="5"
class="basic-input-number"
:controls="false"
@change="changeRingsSize"
>
</el-input>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</div>
</template>
<style lang="less" scoped>
.basic-input-number {
:deep(input) {
-webkit-appearance: none;
-moz-appearance: textfield;
&::-webkit-inner-spin-button,
&::-webkit-outer-spin-button {
-webkit-appearance: none;
}
}
}
.bubble-animate-setting {
display: flex;
width: 100%;
.bubble-animate-slider {
padding: 0 8px;
:deep(.ed-slider__button-wrapper) {
--ed-slider-button-wrapper-size: 36px;
--ed-slider-button-size: 16px;
}
}
.bubble-animate-label {
padding-right: 8px;
font-size: 12px;
font-style: normal;
font-weight: 400;
height: 32px;
line-height: 32px;
display: inline-flex;
align-items: flex-start;
min-width: 56px;
&.dark {
color: #a6a6a6;
}
}
}
</style>

View File

@ -1056,6 +1056,11 @@ const onScrollCfgChange = val => {
renderChart(view.value)
}
const onBubbleAnimateChange = val => {
view.value.senior.bubbleCfg = val
renderChart(view.value)
}
const onTableColumnWidthChange = val => {
if (editMode.value !== 'edit') {
return
@ -2806,6 +2811,7 @@ const deleteChartFieldItem = id => {
@onScrollCfgChange="onScrollCfgChange"
@onThresholdChange="onThresholdChange"
@onMapMappingChange="onMapMappingChange"
@onBubbleAnimateChange="onBubbleAnimateChange"
/>
</template>
</el-scrollbar>

View File

@ -725,6 +725,13 @@ export const DEFAULT_SCROLL: ScrollCfg = {
step: 50
}
export const DEFAULT_BUBBLE_ANIMATE: BubbleCfg = {
enable: false,
speed: 1,
rings: 1,
type: 'wave'
}
export const DEFAULT_QUADRANT_STYLE: QuadrantAttr = {
lineStyle: {
stroke: '#aaa',
@ -1572,7 +1579,8 @@ export const BASE_VIEW_CONFIG = {
assistLineCfg: DEFAULT_ASSIST_LINE_CFG,
threshold: DEFAULT_THRESHOLD,
scrollCfg: DEFAULT_SCROLL,
areaMapping: {}
areaMapping: {},
bubbleCfg: DEFAULT_BUBBLE_ANIMATE
},
flowMapStartName: [],
flowMapEndName: []

View File

@ -28,7 +28,7 @@ const { t } = useI18n()
* 气泡地图
*/
export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
properties = MAP_EDITOR_PROPERTY
properties: EditorProperty[] = [...MAP_EDITOR_PROPERTY, 'bubble-animate']
propertyInner = MAP_EDITOR_PROPERTY_INNER
axis = MAP_AXIS_TYPE
axisConfig: AxisConfig = {
@ -147,6 +147,7 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
}
})
const { basicStyle } = parseJson(chart.customAttr)
const { bubbleCfg } = parseJson(chart.senior)
const { offsetHeight, offsetWidth } = document.getElementById(drawOption.container)
const options: DotLayerOptions = {
source: {
@ -173,6 +174,20 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
active: true
}
}
if (bubbleCfg && bubbleCfg.enable) {
return new DotLayer({
...options,
size: {
field: 'size',
value: [10, Math.min(offsetHeight, offsetWidth) / 10]
},
animate: {
enable: true,
speed: bubbleCfg.speed,
rings: bubbleCfg.rings
}
})
}
return new DotLayer(options)
}