fix(图表): 修复图表背景图模糊无效的问题

This commit is contained in:
jianneng-fit2cloud
2026-03-25 11:36:28 +08:00
parent 3d878af8f2
commit 3000ed63fb
3 changed files with 216 additions and 98 deletions

View File

@@ -13,6 +13,11 @@ import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { activeWatermarkCheckUser, removeActiveWatermark } from '@/components/watermark/watermark'
import { isMobile } from '@/utils/utils'
import { isDashboard, isMainCanvas } from '@/utils/canvasUtils'
import {
isBlurBgEnabled,
getBlurBgStyle,
getComponentBackgroundStyle
} from '@/utils/backgroundStyleUtils'
import { XpackComponent } from '@/components/plugin'
import { useAppStoreWithOut } from '@/store/modules/app'
import DePreviewPopDialog from '@/components/visualization/DePreviewPopDialog.vue'
@@ -222,43 +227,20 @@ const onMouseEnter = () => {
eventBus.emit('v-hover', config.value.id)
}
const blurBgEnable = computed(() => {
return isBlurBgEnabled(config.value.commonBackground)
})
const blurBgStyle = computed(() => {
return getBlurBgStyle(config.value.commonBackground, deepScale.value)
})
const componentBackgroundStyle = computed(() => {
if (config.value.commonBackground) {
const {
backdropFilterEnable,
backdropFilter,
backgroundColorSelect,
backgroundColor,
backgroundImageEnable,
backgroundType,
outerImage,
innerPadding,
borderRadius
} = config.value.commonBackground
let style = {
padding: innerPadding * deepScale.value + 'px',
borderRadius: borderRadius + 'px'
}
let colorRGBA = ''
if (backgroundColorSelect && backgroundColor) {
colorRGBA = backgroundColor
}
if (backgroundImageEnable) {
if (backgroundType === 'outerImage' && typeof outerImage === 'string') {
style['background'] = `url(${imgUrlTrans(outerImage)}) no-repeat ${colorRGBA}`
} else {
style['background-color'] = colorRGBA
}
} else {
style['background-color'] = colorRGBA
}
if (config.value.component !== 'UserView') {
style['overflow'] = 'hidden'
}
if (backdropFilterEnable) {
style['backdrop-filter'] = 'blur(' + backdropFilter + 'px)'
}
return style
return getComponentBackgroundStyle(config.value.commonBackground, {
scale: deepScale.value,
isUserView: config.value.component === 'UserView'
})
}
return {}
})
@@ -470,6 +452,7 @@ const updateFromMobile = (e, type) => {
:id="viewDemoInnerId"
:style="componentBackgroundStyle"
>
<div v-if="blurBgEnable" class="blur-bg" :style="blurBgStyle"></div>
<div
class="wrapper-inner-adaptor"
:style="slotStyle"
@@ -550,6 +533,12 @@ const updateFromMobile = (e, type) => {
}
}
.blur-bg {
width: 100%;
height: 100%;
background-size: 100% 100% !important;
}
.wrapper-edit-bar-active {
display: inherit !important;
}

View File

@@ -73,6 +73,8 @@
@click="selectCurComponent"
@mousedown="handleInnerMouseDownOnShape"
>
<!-- 背景模糊层 由于父层的backdrop-filter是作用于背后内容无法模糊自身背景图 -->
<div v-if="blurBgEnable" class="blur-bg" :style="blurBgStyle"></div>
<Icon v-if="shapeLock" name="dv-lock"><dvLock class="svg-icon iconfont icon-suo" /></Icon>
<div class="component-slot" :style="slotStyle">
<slot></slot>
@@ -159,9 +161,10 @@ import Board from '@/components/de-board/Board.vue'
import { activeWatermarkCheckUser, removeActiveWatermark } from '@/components/watermark/watermark'
import { useI18n } from '@/hooks/web/useI18n'
import {
CommonBackground,
ShorthandMode
} from '@/components/visualization/component-background/Types'
isBlurBgEnabled,
getBlurBgStyle,
getComponentBackgroundStyle
} from '@/utils/backgroundStyleUtils'
const { t } = useI18n()
const dvMainStore = dvMainStoreWithOut()
@@ -982,68 +985,23 @@ const padding3D = computed(() => {
}
})
// 是否启用背景模糊,有背景图且开启了模糊
const blurBgEnable = computed(() => {
return isBlurBgEnabled(element.value.commonBackground)
})
// 背景模糊层样式
const blurBgStyle = computed(() => {
return getBlurBgStyle(element.value.commonBackground, scale.value)
})
const componentBackgroundStyle = computed(() => {
if (element.value.commonBackground && element.value.component !== 'GroupArea') {
const {
backdropFilterEnable,
backdropFilter,
backgroundColorSelect,
backgroundColor,
backgroundImageEnable,
backgroundType,
outerImage,
innerPadding,
borderRadius
} = element.value.commonBackground
const commonBackground = element.value.commonBackground as CommonBackground
const innerPaddingTarget = ['Group'].includes(element.value.component) ? 0 : innerPadding
let innerPaddingStyle = innerPaddingTarget * scale.value + 'px'
const paddingMode = commonBackground.innerPadding?.mode
if (paddingMode === ShorthandMode.Uniform) {
innerPaddingStyle = `${commonBackground.innerPadding?.top * scale.value}px`
} else if (paddingMode === ShorthandMode.PerEdge) {
innerPaddingStyle = `${commonBackground.innerPadding?.top * scale.value}px ${
commonBackground.innerPadding?.right * scale.value
}px ${commonBackground.innerPadding?.bottom * scale.value}px ${
commonBackground.innerPadding?.left * scale.value
}px`
}
let borderRadiusStyle = borderRadius + 'px'
const borderRadiusMode = commonBackground.borderRadius?.mode
if (borderRadiusMode === ShorthandMode.Uniform) {
borderRadiusStyle = `${commonBackground.borderRadius?.topLeft * scale.value}px`
} else if (borderRadiusMode === ShorthandMode.PerEdge) {
borderRadiusStyle = `${commonBackground.borderRadius?.topLeft * scale.value}px ${
commonBackground.borderRadius?.topRight * scale.value
}px ${commonBackground.borderRadius?.bottomRight * scale.value}px ${
commonBackground.borderRadius?.bottomLeft * scale.value
}px`
}
let style = {
padding: innerPaddingStyle,
borderRadius: borderRadiusStyle
}
let colorRGBA = ''
if (backgroundColorSelect && backgroundColor) {
colorRGBA = backgroundColor
}
if (backgroundImageEnable) {
if (backgroundType === 'outerImage' && typeof outerImage === 'string') {
style['background'] = `url(${imgUrlTrans(outerImage)}) no-repeat ${colorRGBA}`
} else {
style['background-color'] = colorRGBA
}
} else {
style['background-color'] = colorRGBA
}
if (element.value.component !== 'UserView') {
style['overflow'] = 'hidden'
}
if (backdropFilterEnable) {
style['backdrop-filter'] = 'blur(' + backdropFilter + 'px)'
}
return style
return getComponentBackgroundStyle(element.value.commonBackground, {
scale: scale.value,
isUserView: element.value.component === 'UserView',
forceNoPadding: ['Group'].includes(element.value.component)
})
}
return {}
})
@@ -1277,6 +1235,12 @@ onMounted(() => {
background-size: 100% 100% !important;
}
.blur-bg {
width: 100%;
height: 100%;
background-size: 100% 100% !important;
}
.shape-selected {
outline: 1px solid var(--ed-color-primary, #3370ff);
}

View File

@@ -0,0 +1,165 @@
import { imgUrlTrans } from '@/utils/imgUtils'
import type {
CommonBackground,
CornerValues,
EdgeValues
} from '@/components/visualization/component-background/Types'
/**
* 判断是否启用背景图模糊
* @param commonBackground 组件背景配置
* @returns 是否启用背景图模糊
*/
export function isBlurBgEnabled(commonBackground: CommonBackground | undefined): boolean {
if (!commonBackground) {
return false
}
const { backdropFilterEnable, backgroundImageEnable, backgroundType, outerImage } =
commonBackground
return (
backdropFilterEnable === true &&
backgroundImageEnable === true &&
backgroundType === 'outerImage' &&
typeof outerImage === 'string'
)
}
/**
* 获取边距样式值
* @param edgeValues 边距配置
* @param scale 缩放比例
* @returns CSS 边距样式值
*/
export function getEdgeValuesStyle(edgeValues: EdgeValues | number | undefined, scale = 1): string {
if (edgeValues === undefined) {
return '0px'
}
if (typeof edgeValues === 'number') {
return `${edgeValues * scale}px`
}
const mode = edgeValues.mode
const top = (edgeValues.top ?? 0) * scale
const right = (edgeValues.right ?? 0) * scale
const bottom = (edgeValues.bottom ?? 0) * scale
const left = (edgeValues.left ?? 0) * scale
if (mode === 'uniform') {
return `${top}px`
} else if (mode === 'per_edge') {
return `${top}px ${right}px ${bottom}px ${left}px`
}
return `${top}px`
}
/**
* 获取圆角样式值
* @param cornerValues 圆角配置
* @param scale 缩放比例
* @returns CSS 圆角样式值
*/
export function getCornerValuesStyle(
cornerValues: CornerValues | number | undefined,
scale = 1
): string {
if (cornerValues === undefined) {
return '0px'
}
if (typeof cornerValues === 'number') {
return `${cornerValues * scale}px`
}
const mode = cornerValues.mode
const topLeft = (cornerValues.topLeft ?? 0) * scale
const topRight = (cornerValues.topRight ?? 0) * scale
const bottomLeft = (cornerValues.bottomLeft ?? 0) * scale
const bottomRight = (cornerValues.bottomRight ?? 0) * scale
if (mode === 'uniform') {
return `${topLeft}px`
} else if (mode === 'per_edge') {
return `${topLeft}px ${topRight}px ${bottomRight}px ${bottomLeft}px`
}
return `${topLeft}px`
}
/**
* 生成背景模糊层样式
* @param commonBackground 组件背景配置
* @param scale 缩放比例
* @returns CSS 样式对象
*/
export function getBlurBgStyle(
commonBackground: CommonBackground | undefined,
scale = 1
): Record<string, string> {
if (!isBlurBgEnabled(commonBackground)) {
return {}
}
const { outerImage, backdropFilter, borderRadius } = commonBackground
return {
position: 'absolute',
inset: '0',
background: `url(${imgUrlTrans(outerImage!)}) no-repeat center/cover`,
filter: `blur(${backdropFilter ?? 0}px)`,
borderRadius: getCornerValuesStyle(borderRadius, scale),
pointerEvents: 'none'
}
}
/**
* 生成组件背景样式
* @param commonBackground 组件背景配置
* @param options 配置选项
* @returns CSS 样式对象
*/
export function getComponentBackgroundStyle(
commonBackground: CommonBackground | undefined,
options: {
scale?: number
isUserView?: boolean
forceNoPadding?: boolean
} = {}
): Record<string, string> {
if (!commonBackground) {
return {}
}
const {
backdropFilterEnable,
backdropFilter,
backgroundColorSelect,
backgroundColor,
backgroundImageEnable,
backgroundType,
outerImage,
innerPadding,
borderRadius
} = commonBackground
const { scale = 1, isUserView = false, forceNoPadding = false } = options
const style: Record<string, string> = {
padding: forceNoPadding ? '0px' : getEdgeValuesStyle(innerPadding, scale),
borderRadius: getCornerValuesStyle(borderRadius, scale)
}
// 背景色
let colorRGBA = ''
if (backgroundColorSelect && backgroundColor) {
colorRGBA = backgroundColor
}
// 背景图
const blurEnabled = isBlurBgEnabled(commonBackground)
if (backgroundImageEnable) {
if (blurEnabled) {
style['background-color'] = colorRGBA
} else if (backgroundType === 'outerImage' && typeof outerImage === 'string') {
style['background'] = `url(${imgUrlTrans(outerImage)}) no-repeat ${colorRGBA}`
} else {
style['background-color'] = colorRGBA
}
} else {
style['background-color'] = colorRGBA
}
// 溢出处理
if (!isUserView) {
style['overflow'] = 'hidden'
}
if (backdropFilterEnable && !blurEnabled) {
style['backdrop-filter'] = `blur(${backdropFilter ?? 0}px)`
}
return style
}