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 = (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 => { const res: Record = {} 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} ` }