forked from github/dataease
Merge pull request #11129 from dataease/pr@dev-v2@chart-bubble-animate
feat(图表-气泡地图): 气泡添加水波纹动画配置
This commit is contained in:
commit
8c7515f5e0
@ -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
|
||||
}
|
||||
|
@ -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[]
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
@ -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>
|
||||
|
@ -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: []
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user