staff_data/packages/mindmap/src/utils/Theme.ts

128 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import MersenneTwister from "./mersenneTwister"
import { ThemeConfig } from "../theme"
import { richTextSupportStyleList } from "../constants/constant"
import merge from 'deepmerge'
// 判断一个颜色是否是白色
export const isWhite = (color: string): boolean => {
color = String(color).replaceAll(/\s+/g, '')
return (
['#fff', '#ffffff', '#FFF', '#FFFFFF', 'rgb(255,255,255)'].includes(
color
) || /rgba\(255,255,255,[^)]+\)/.test(color)
)
}
// 判断一个颜色是否是透明
export const isTransparent = (color: string): boolean => {
color = String(color).replaceAll(/\s+/g, '')
return (
['', 'transparent'].includes(color) || /rgba\(\d+,\d+,\d+,0\)/.test(color)
)
}
// 从当前主题里获取一个非透明非白色的颜色
export const getVisibleColorFromTheme = (themeConfig: ThemeConfig): string | undefined => {
const { lineColor, root, second, node } = themeConfig
const list = [
lineColor,
root.fillColor,
root.color,
second.fillColor,
second.color,
node.fillColor,
node.color,
root.borderColor,
second.borderColor,
node.borderColor
]
for (let i = 0; i < list.length; i++) {
const color = list[i]
if (!isTransparent(color) && !isWhite(color)) {
return color
}
}
return undefined
}
// 根据内容生成颜色
export const generateColorByContent = (str: string): string => {
let hash = 0
for (let i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash)
}
// 这里使用伪随机数的原因是因为
// 1. 如果字符串的内容差不多根据hash生产的颜色就比较相近不好区分比如v1.1 v1.2,所以需要加入随机数来使得颜色能够区分开
// 2. 普通的随机数每次数值不一样,就会导致每次新增标签原来的标签颜色就会发生改变,所以加入了这个方法,使得内容不变随机数也不变
const rng = new MersenneTwister(hash)
const h = rng.genrand_int32() % 360
return 'hsla(' + h + ', 50%, 50%, 1)'
}
interface IconItem {
type: string
list: Array<{
name: string
icon: string
}>
}
export const mergerIconList = (list: IconItem[]): IconItem[] => {
return list.reduce((result: IconItem[], item) => {
const existingItem = result.find(x => x.type === item.type)
if (existingItem) {
item.list.forEach(newObj => {
const existingObj = existingItem.list.find(x => x.name === newObj.name)
if (existingObj) {
existingObj.icon = newObj.icon
} else {
existingItem.list.push(newObj)
}
})
} else {
result.push({ ...item })
}
return result
}, [])
}
// 合并主题配置
export const mergeTheme = <T extends object>(dest: T, source: T): T => {
return merge(dest, source, {
arrayMerge: (_destinationArray: any[], sourceArray: any[]) => sourceArray
})
}
interface NodeStyle {
merge: (prop: string) => string | number
}
interface Node {
style: NodeStyle
}
// 获取节点实例的文本样式数据
export const getNodeRichTextStyles = (node: Node): Record<string, string> => {
const res: Record<string, string> = {}
richTextSupportStyleList.forEach(prop => {
let value = node.style.merge(prop)
if (prop === 'fontSize') {
value = value + 'px'
}
res[prop] = String(value)
})
return res
}
export interface FontOptions {
italic?: boolean;
bold?: boolean;
fontSize: number;
fontFamily: string;
}
// 拼接font字符串
export const joinFontStr = ({ italic, bold, fontSize, fontFamily }: FontOptions): string => {
return `${italic ? 'italic ' : ''} ${bold ? 'bold ' : ''
} ${fontSize}px ${fontFamily} `
}