de/frontend/src/components/canvas/utils/style.js

429 lines
12 KiB
JavaScript

import { sin, cos } from '@/components/canvas/utils/translate'
import store from '@/store'
import Vue from 'vue'
export const LIGHT_THEME_COLOR_MAIN = '#000000'
export const LIGHT_THEME_COLOR_SLAVE1 = '#CCCCCC'
export const LIGHT_THEME_PANEL_BACKGROUND = '#F1F3F5'
export const LIGHT_THEME_COMPONENT_BACKGROUND = '#FFFFFF'
export const DARK_THEME_COLOR_MAIN = '#FFFFFF'
export const DARK_THEME_COLOR_SLAVE1 = '#CCCCCC'
export const DARK_THEME_PANEL_BACKGROUND = '#030B2E'
export const DARK_THEME_COMPONENT_BACKGROUND = '#131E42'
export const DARK_THEME_COMPONENT_BACKGROUND_BACK = '#5a5c62'
export function getStyle(style, filter = []) {
const needUnit = [
'fontSize',
'width',
'height',
'top',
'left',
'borderWidth',
'letterSpacing',
'borderRadius',
'margin',
'padding'
]
const result = {}
Object.keys(style).forEach(key => {
if (!filter.includes(key)) {
if (key !== 'rotate') {
result[key] = style[key]
if (key) {
if (key === 'backgroundColor') {
result[key] = colorRgb(style[key], style.opacity)
}
if (key === 'fontSize' && result[key] < 12) {
result[key] = 12
}
if (needUnit.includes(key)) {
result[key] += 'px'
}
}
} else {
result.transform = key + '(' + style[key] + 'deg)'
}
}
})
if (result.backgroundColor && (result.opacity || result.opacity === 0)) {
delete result.opacity
}
return result
}
// 获取一个组件旋转 rotate 后的样式
export function getComponentRotatedStyle(style) {
style = { ...style }
if (style.rotate !== 0) {
const newWidth = style.width * cos(style.rotate) + style.height * sin(style.rotate)
const diffX = (style.width - newWidth) / 2 // 旋转后范围变小是正值,变大是负值
style.left += diffX
style.right = style.left + newWidth
const newHeight = style.height * cos(style.rotate) + style.width * sin(style.rotate)
const diffY = (newHeight - style.height) / 2 // 始终是正
style.top -= diffY
style.bottom = style.top + newHeight
style.width = newWidth
style.height = newHeight
} else {
style.bottom = style.top + style.height
style.right = style.left + style.width
}
return style
}
export function colorRgb(color, opacity) {
var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
var sColor = color
if (sColor && reg.test(sColor)) {
sColor = sColor.toLowerCase()
if (sColor.length === 4) {
var sColorNew = '#'
for (var i = 1; i < 4; i += 1) {
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
}
sColor = sColorNew
}
// 处理六位的颜色值
const sColorChange = []
for (let i = 1; i < 7; i += 2) {
sColorChange.push(parseInt('0x' + sColor.slice(i, i + 2)))
}
if (opacity || opacity === 0) {
return 'rgba(' + sColorChange.join(',') + ',' + opacity + ')'
} else {
return 'rgba(' + sColorChange.join(',') + ')'
}
} else {
return sColor
}
}
export const customAttrTrans = {
'size': [
'barWidth',
'lineWidth',
'lineSymbolSize',
'funnelWidth', // 漏斗图 最大宽度
'tableTitleFontSize',
'tableItemFontSize',
'tableTitleHeight',
'tableItemHeight',
'dimensionFontSize',
'quotaFontSize',
'spaceSplit', // 间隔
'scatterSymbolSize', // 气泡大小,散点图
'radarSize'// 雷达占比
],
'label': [
'fontSize'
],
'tooltip': {
'textStyle': ['fontSize']
}
}
export const customStyleTrans = {
'text': ['fontSize'],
'legend': {
'textStyle': ['fontSize']
},
'xAxis': {
'nameTextStyle': ['fontSize'],
'axisLabel': ['fontSize'],
'splitLine': {
'lineStyle': ['width']
}
},
'yAxis': {
'nameTextStyle': ['fontSize'],
'axisLabel': ['fontSize'],
'splitLine': {
'lineStyle': ['width']
}
},
'yAxisExt': {
'nameTextStyle': ['fontSize'],
'axisLabel': ['fontSize'],
'splitLine': {
'lineStyle': ['width']
}
},
'split': {
'name': ['fontSize'],
'axisLine': {
'lineStyle': ['width']
},
'axisTick': {
'lineStyle': ['width']
},
'axisLabel': ['margin', 'fontSize'],
'splitLine': {
'lineStyle': ['width']
}
}
}
export const THEME_STYLE_TRANS_MAIN_BACK = {
'legend': {
'textStyle': ['color']
},
'xAxis': {
'nameTextStyle': ['color'],
'axisLabel': ['color'],
'splitLine': {
'lineStyle': ['color']
}
},
'yAxis': {
'nameTextStyle': ['color'],
'axisLabel': ['color'],
'splitLine': {
'lineStyle': ['color']
}
},
'yAxisExt': {
'nameTextStyle': ['color'],
'axisLabel': ['color'],
'splitLine': {
'lineStyle': ['color']
}
},
'split': {
'name': ['color'],
'axisLine': {
'lineStyle': ['color']
},
'axisTick': {
'lineStyle': ['color']
},
'axisLabel': ['color'],
'splitLine': {
'lineStyle': ['color']
}
}
}
export const THEME_STYLE_TRANS_MAIN = {
'legend': {
'textStyle': ['color']
},
'xAxis': {
'nameTextStyle': ['color'],
'axisLabel': ['color']
},
'yAxis': {
'nameTextStyle': ['color'],
'axisLabel': ['color']
},
'yAxisExt': {
'nameTextStyle': ['color'],
'axisLabel': ['color']
},
'split': {
'name': ['color'],
'axisTick': {
'lineStyle': ['color']
},
'axisLabel': ['color']
}
}
export const THEME_STYLE_TRANS_SLAVE1 = {
'xAxis': {
'splitLine': {
'lineStyle': ['color']
}
},
'yAxis': {
'splitLine': {
'lineStyle': ['color']
}
},
'yAxisExt': {
'splitLine': {
'lineStyle': ['color']
}
},
'split': {
'splitLine': {
'lineStyle': ['color']
},
'axisLine': {
'lineStyle': ['color']
}
}
}
export const THEME_ATTR_TRANS_MAIN = {
'label': ['color'],
'tooltip': {
'textStyle': ['color']
}
}
export const THEME_ATTR_TRANS_MAIN_SYMBOL = {
'label': ['color']
}
export const THEME_ATTR_TRANS_SLAVE1_BACKGROUND = {
'tooltip': ['backgroundColor']
}
// 移动端特殊属性
export const mobileSpecialProps = {
'lineWidth': 3, // 线宽固定值
'lineSymbolSize': 5// 折点固定值
}
export function getScaleValue(propValue, scale) {
const propValueTemp = Math.round(propValue * scale)
return propValueTemp > 1 ? propValueTemp : 1
}
export function recursionTransObj(template, infoObj, scale, terminal) {
for (const templateKey in template) {
// 如果是数组 进行赋值计算
if (template[templateKey] instanceof Array) {
template[templateKey].forEach(templateProp => {
if (infoObj[templateKey] && infoObj[templateKey][templateProp]) {
// 移动端特殊属性值设置
if (terminal === 'mobile' && mobileSpecialProps[templateProp] !== undefined) {
infoObj[templateKey][templateProp] = mobileSpecialProps[templateProp]
} else {
infoObj[templateKey][templateProp] = getScaleValue(infoObj[templateKey][templateProp], scale)
}
}
})
} else {
// 如果是对象 继续进行递归
if (infoObj[templateKey]) {
recursionTransObj(template[templateKey], infoObj[templateKey], scale, terminal)
}
}
}
}
export function recursionThemTransObj(template, infoObj, color) {
for (const templateKey in template) {
// 如果是数组 进行赋值计算
if (template[templateKey] instanceof Array) {
template[templateKey].forEach(templateProp => {
if (infoObj[templateKey]) {
Vue.set(infoObj[templateKey], templateProp, color)
}
})
} else {
// 如果是对象 继续进行递归
if (infoObj[templateKey]) {
recursionThemTransObj(template[templateKey], infoObj[templateKey], color)
}
}
}
}
export function componentScalePublic(chartInfo, heightScale, widthScale) {
const scale = Math.min(heightScale, widthScale)
// attr 缩放转换
recursionTransObj(this.customAttrTrans, chartInfo.customAttr, scale)
// style 缩放转换
recursionTransObj(this.customStyleTrans, chartInfo.customStyle, scale)
return chartInfo
}
export function adaptCurTheme(customStyle, customAttr, chartType) {
const canvasStyle = store.state.canvasStyleData
const themeColor = canvasStyle.panel.themeColor
if (themeColor === 'light') {
recursionThemTransObj(THEME_STYLE_TRANS_MAIN, customStyle, LIGHT_THEME_COLOR_MAIN)
recursionThemTransObj(THEME_STYLE_TRANS_SLAVE1, customStyle, LIGHT_THEME_COLOR_SLAVE1)
recursionThemTransObj(THEME_ATTR_TRANS_MAIN, customAttr, LIGHT_THEME_COLOR_MAIN)
recursionThemTransObj(THEME_ATTR_TRANS_SLAVE1_BACKGROUND, customAttr, LIGHT_THEME_COMPONENT_BACKGROUND)
if (chartType === 'symbol-map') {
// 符号地图特殊处理
Vue.set(customStyle['baseMapStyle'], 'baseMapTheme', 'light')
}
} else {
recursionThemTransObj(THEME_STYLE_TRANS_MAIN, customStyle, DARK_THEME_COLOR_MAIN)
recursionThemTransObj(THEME_STYLE_TRANS_SLAVE1, customStyle, DARK_THEME_COLOR_SLAVE1)
if (chartType === 'symbol-map') {
// 符号地图特殊处理
Vue.set(customStyle['baseMapStyle'], 'baseMapTheme', 'dark')
recursionThemTransObj(THEME_ATTR_TRANS_MAIN_SYMBOL, customAttr, '#000000')
} else {
recursionThemTransObj(THEME_ATTR_TRANS_MAIN, customAttr, DARK_THEME_COLOR_MAIN)
recursionThemTransObj(THEME_ATTR_TRANS_SLAVE1_BACKGROUND, customAttr, DARK_THEME_COMPONENT_BACKGROUND_BACK)
}
}
customAttr['color'] = { ...canvasStyle.chartInfo.chartColor }
customStyle['text'] = { ...canvasStyle.chartInfo.chartTitle, title: customStyle['text']['title'], show: customStyle['text']['show'], remarkShow: customStyle['text']['remarkShow'], remark: customStyle['text']['remark'] }
if (customStyle.background) {
delete customStyle.background
}
}
export function adaptCurThemeCommonStyle(component) {
const commonStyle = store.state.canvasStyleData.chartInfo.chartCommonStyle
for (const key in commonStyle) {
component.commonBackground[key] = commonStyle[key]
}
if (isFilterComponent(component.component)) {
const filterStyle = store.state.canvasStyleData.chartInfo.filterStyle
for (const styleKey in filterStyle) {
Vue.set(component.style, styleKey, filterStyle[styleKey])
}
} else if (isTabComponent(component.component)) {
const tabStyle = store.state.canvasStyleData.chartInfo.tabStyle
for (const styleKey in tabStyle) {
if (typeof tabStyle[styleKey] === 'string') {
Vue.set(component.style, styleKey, tabStyle[styleKey])
} else {
Vue.set(component.style, styleKey, null)
}
}
} else {
if (component.style.color) {
if (store.state.canvasStyleData.panel.themeColor === 'light') {
component.style.color = LIGHT_THEME_COLOR_MAIN
} else {
component.style.color = DARK_THEME_COLOR_MAIN
}
}
}
return component
}
export function adaptCurThemeCommonStyleAll() {
const componentData = store.state.componentData
componentData.forEach((item) => {
adaptCurThemeCommonStyle(item)
if (item.style.backgroundColor) {
delete item.style.backgroundColor
}
})
}
export function adaptCurThemeFilterStyleAll(styleKey) {
const componentData = store.state.componentData
const filterStyle = store.state.canvasStyleData.chartInfo.filterStyle
componentData.forEach((item) => {
if (isFilterComponent(item.component)) {
Vue.set(item.style, styleKey, filterStyle[styleKey])
}
})
}
export function isFilterComponent(component) {
return ['de-select', 'de-select-grid', 'de-date', 'de-input-search', 'de-number-range', 'de-select-tree'].includes(component)
}
export function isTabComponent(component) {
return ['de-tabs'].includes(component)
}