UNPKG

@cataract6545/tmui

Version:

tm-vuetify是一个新势力由主题驱动的UI组件库,相比其它优势大,组件全,设计趋势紧跟未来。具有主题生成,主题实时切换,暗黑实时切换,lottie动画,图表等新颖功能,tmui TMUI

534 lines (488 loc) 17.1 kB
/** * 主题工具 * @author tmzdy tmui3.0 * @description 主题样式生成工具 * @copyright tmzdy|tmui|https://tmui.design */ import { colortool } from './colortool'; import { ssrRef } from '@dcloudio/uni-app' import { cssStyleConfig, cssstyle, colorThemeType, cssDirection, linearDirection, linearDeep, linearDirectionType } from '../lib/interface'; //导入用户自定义的主题色值。 // import { theme } from '../../../theme/index'; let localTheme = {}; // #ifdef APP try { localTheme = JSON.parse(uni.getStorageSync("$tmTheme")) } catch (e) { //TODO handle the exception } // #endif let theme = uni?.$tm?.config?.theme ? { ...uni.$tm.config.theme } : localTheme; var colors: Array<colorThemeType> = []; var colorObj: any = { red: '#FE1C00', pink: '#CA145D', purple: '#A61BC3', 'deep-purple': '#6A0E81', indigo: '#652DF4', blue: '#0163FF', 'light-blue': '#0889FF', cyan: '#11CDE8', teal: '#00998a', green: '#5DBD1F', 'light-green': '#83D54A', lime: '#D4ED00', yellow: '#FFC400', amber: '#FFFB01', orange: '#FEA600', 'deep-orange': '#FE5C00', brown: '#795548', 'blue-grey': '#607D8B', grey: '#9E9E9E', black: '#000000', white: '#FFFFFF', primary: '#0163FF', 'grey-5': '#fafafa', 'grey-4': '#f5f5f5', 'grey-3': '#eeeeee', 'grey-2': '#e0e0e0', 'grey-1': '#bdbdbd', 'grey-darken-1': '#757575', 'grey-darken-2': '#616161', 'grey-darken-3': '#404044', 'grey-darken-4': '#202022', 'grey-darken-5': '#111112', 'grey-darken-6': '#0A0A0B', ...theme }; for (const key in colorObj) { if (Object.prototype.hasOwnProperty.call(colorObj, key)) { const element: string = String(colorObj[key]); if (isCssColor(element)) { let rgba = colortool.cssToRgba(element); colors.push({ name: key, value: element, hsva: colortool.rgbaToHsva(colortool.cssToRgba(element)), rgba: colortool.cssToRgba(element), hsla: colortool.rgbaToHsla(rgba), csscolor: `rgba(${rgba.r},${rgba.g},${rgba.b},${rgba.a})` }); } } } function isCssColor(color: string) { const reg1 = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; const reg2 = /^(rgb|RGB|rgba|RGBA)/; return reg1.test(color) || reg2.test(color); } function getColor(colorName: string) { let isHand: number = colors.findIndex(function (el, index) { return el.name == colorName; }); if (isHand == -1) { colorName = "primary"; isHand = colors.findIndex(function (el, index) { return el.name == colorName; }); console.warn('主题中不存在相关名称的主题。'); } return colors[isHand]; } class themeColors { colors: Array<colorThemeType> = []; constructor(c: Array<colorThemeType> = colors) { this.colors = c; } public hasColors(colorName: string = "") { let isHand: Array<colorThemeType> = this.colors.filter(function (el, index) { return el.name == colorName; }); return isHand.length > 0; } public add(colorName: string = "", value: string = "") { let isHand: Array<colorThemeType> = this.colors.filter(function (el, index) { return el.name == colorName; }); if (isHand.length > 0) { // console.error('已存在相关颜色名称!!!'); return this.colors; } if (!value) { console.error('颜色值必填!!!'); return this.colors; } let rgba = colortool.cssToRgba(value); let color: colorThemeType = { csscolor: "", hsva: { h: 0, s: 0, v: 0, a: 0 }, hsla: { h: 0, s: 0, l: 0, a: 0 }, rgba: { r: 0, g: 0, b: 0, a: 0 }, name: colorName, value: value }; color.csscolor = colortool.rgbaToCss(rgba); color.hsva = colortool.rgbaToHsva(rgba); color.rgba = rgba; color.hsla = colortool.rgbaToHsla(rgba); this.colors.push(color); return this.colors; } public del(colorName: string) { let isHand: number = this.colors.findIndex(function (el, index) { return el.name == colorName; }); if (isHand == -1) { console.error('删除失败,主题中不存在相关名称的主题。'); return; } this.colors.splice(isHand, 1); } public getColor(colorName: string): colorThemeType { let isHand: number = this.colors.findIndex(function (el, index) { return el.name == colorName; }); if (isHand == -1) { colorName = "primary"; isHand = this.colors.findIndex(function (el, index) { return el.name == colorName; }); console.error('主题中不存在相关名称的主题。'); } return this.colors[isHand]; } /** * 计算主题 * @author tmui3.0|tmzdy * @param config 样式的细化 * @returns cssstyle 返回一个计算好的主题系。 */ public getTheme(config: cssStyleConfig = { colorname: 'primary', dark: false }): cssstyle { if (!config['colorname']) { console.error('颜色名称必填'); config.colorname = 'primary'; } let index = this.colors.findIndex(el => el.name == config.colorname); if (index == -1) { console.error('主题不存在,默认为primary'); config.colorname = 'primary'; } //当前颜色对象。 let nowColor = { ...this.colors[index] }; config.borderWidth = isNaN(parseInt(String(config['borderWidth']))) ? 0 : config['borderWidth'] ?? 0; config.borderStyle = config['borderStyle'] ? config['borderStyle'] : 'solid'; config.borderColor = config['borderColor'] || ''; config.borderDirection = config['borderDirection'] || cssDirection.all; config.linearDirection = config['linearDirection'] || linearDirection.none; config.linearDeep = config['linearDeep'] || linearDeep.light; config.shadow = isNaN(parseInt(String(config['shadow']))) ? 6 : config['shadow']; config.round = isNaN(parseInt(String(config['round']))) ? 4 : config['round']; config.opaticy = isNaN(parseInt(String(config['opaticy']))) ? 1 : config['opaticy']; config.outlined = typeof config['outlined'] == 'boolean' ? config['outlined'] : false; config.text = typeof config['text'] == 'boolean' ? config['text'] : false; config.blur = typeof config['blur'] == 'boolean' ? config['blur'] : false; // 确定一个颜色值是明亮的还是深色的, //以方便确定文本颜色是亮还是深来区别,否则颜色看不清. function isDarkColorFun(r: number, g: number, b: number) { const yiq = (r * 2126 + g * 7152 + b * 722) / 10000; return yiq < 180; } /**是否是黑色 */ let isBlack = false; /**是否是白色 */ let isWhite = false; /**黑或者白 */ let isBlackAndWhite = false; /**是否是灰色 */ let isGrey = false /**该颜色在人眼中属于深,还是浅,以适配文本色 */ let isDarkColor = false; isDarkColor = isDarkColorFun(nowColor.rgba.r, nowColor.rgba.g, nowColor.rgba.b) //黑 if (nowColor.hsla.h == 0 && nowColor.hsla.s == 0 && nowColor.hsla.l == 0) { isBlack = true; } //白 if (nowColor.hsla.h == 0 && nowColor.hsla.s == 0 && nowColor.hsla.l == 100) { isWhite = true; } //灰 if (nowColor.hsla.h == 0 && nowColor.hsla.s == 0 && nowColor.hsla.l < 100) { isGrey = true; } //黑或者白 if (nowColor.hsla.h == 0 && nowColor.hsla.s == 0) { isBlackAndWhite = true; } let css: cssstyle = {}; css.color = nowColor.value; css.config = { ...config }; css.isBlackAndWhite = isBlackAndWhite; css.gradientColor = [] css.colorname = config.colorname; let borderhsl = { ...nowColor.hsla }; let borderDir = "all"; css.borderCss = {}; //背景颜色。 let bghsl = { ...nowColor.hsla }; /**非黑非白,h,s不变,只要降10%的亮度即可。 */ if (config.dark && !isBlackAndWhite) { bghsl.l = 40; } if (config.blur) { bghsl.a = 0.85 } css.backgroundColor = colortool.rgbaToCss(colortool.hslaToRgba({ ...bghsl })); if (isBlackAndWhite && config.dark) { css.backgroundColor = colortool.rgbaToCss(colortool.hslaToRgba({ ...bghsl, h: 240, s: 3, l: 8 })); css.border = colortool.rgbaToCss(colortool.hslaToRgba({ ...borderhsl, h: 240, s: 3, l: 12 })); } if (isWhite && !config.dark) { css.border = colortool.rgbaToCss(colortool.hslaToRgba({ ...borderhsl, l: 90 })); } if (isBlack && !config.dark) { css.border = colortool.rgbaToCss(colortool.hslaToRgba({ ...borderhsl, l: 12 })); } css.backgroundColorCss = { 'background-color': css.backgroundColor } //文字颜色。 let txcolor = { ...nowColor.hsla }; //当亮度小于(含)50需要降低文本颜色的亮度,即加深。,否则加亮,即变浅色。 if (config.dark) { txcolor.l = 95; } else { if (isDarkColor) { txcolor.l = 95; } else { if (isGrey) { txcolor.l = 10; } else { txcolor.l = 20; } } } //外边框轮廓时 //outlined if (config.outlined) { txcolor.l = nowColor.hsla.l; if (config.dark) { txcolor.l = 55; } else { if (nowColor.hsla.h != 0 && nowColor.hsla.s != 0 && !isDarkColorFun(nowColor.rgba.r, nowColor.rgba.g, nowColor.rgba.b)) { txcolor.l = 20; } } if ((isBlack || isWhite) && config.dark) { txcolor.l = 100 } config.borderWidth = config['borderWidth'] || 2; let n_hsl = { h: nowColor.hsla.h, s: nowColor.hsla.s, l: 0, a: 0 }; let o_bgcss = colortool.rgbaToCss(colortool.hslaToRgba(n_hsl)); css.backgroundColor = o_bgcss; css.backgroundColorCss = { 'background-color': o_bgcss } css.textColor = colortool.rgbaToCss(colortool.hslaToRgba(txcolor)); } //text if (config.text) { txcolor.l = nowColor.hsla.l; if (isGrey) { txcolor.l = 15; } else { // txcolor.l = 55; if (nowColor.hsla.h != 0 && nowColor.hsla.s != 0 && !isDarkColorFun(nowColor.rgba.r, nowColor.rgba.g, nowColor.rgba.b)) { txcolor.l = 20; } } if (config.dark) { txcolor.l = 60; if (!isBlackAndWhite) { txcolor.s = 100; } } if (isBlack) { txcolor.l = 90 } if (isWhite) { txcolor.l = 15 } if (nowColor.hsla.h == 0 && nowColor.hsla.s == 0 && config.dark) { txcolor.l = 90; } css.textColor = colortool.rgbaToCss(colortool.hslaToRgba(txcolor)); css.border = css.textColor; let o_now_bgColor = nowColor.csscolor; let n_hsl = { h: nowColor.hsla.h, s: nowColor.hsla.s, l: 96, a: nowColor.hsla.a }; if (config.dark) { if (nowColor.hsla.h != 0 && nowColor.hsla.s != 0) { n_hsl.l = 12; n_hsl.s = 35; } else { n_hsl.l = 12; n_hsl.s = 0; } } if (config.blur) { n_hsl.a = 0.85 } o_now_bgColor = colortool.rgbaToCss(colortool.hslaToRgba(n_hsl)); css.backgroundColor = o_now_bgColor; css.backgroundColorCss = { 'background-color': o_now_bgColor } } //shadow if (config.shadow) { let n_hsl = { h: nowColor.hsla.h, s: 100, l: 50, a: 0.2 }; if (nowColor.hsla.h == 0 && nowColor.hsla.s == 0) { //黑白要反转。 n_hsl = { h: 0, s: 0, l: 20, a: 0.07 }; } let o_bgcss = colortool.rgbaToCss(colortool.hslaToRgba(n_hsl)); css.shadowColor = { boxShadow: `0rpx ${config.shadow * 2.5}rpx ${config.shadow * 6}rpx ${o_bgcss}` } } //处理渐变色 if (config.linearDirection) { let liner_color_1 = { h: 0, s: 0, l: 0, a: nowColor.hsla.a }; let liner_color_2 = { h: 0, s: 0, l: 0, a: nowColor.hsla.a }; let dir_str = linearDirection[config.linearDirection]; // 增减控制参数。 let addling = 0; if (nowColor.hsla.h < 180 && nowColor.hsla.h > 0) { addling = 20 } else { addling = -37 } //先计算渐变的亮色系。 // 先算白或者黑 // 如果是白 if (nowColor.hsla.h == 0 && nowColor.hsla.s == 0 && nowColor.hsla.l == 100) { //白。 if (config.linearDeep == 'light') { liner_color_1.l = 80; liner_color_2.l = 20; } else { liner_color_1.l = 50; liner_color_2.l = 40; } } else if (nowColor.hsla.h == 0 && nowColor.hsla.s == 0 && nowColor.hsla.l == 0) { //黑。 if (config.linearDeep == 'light') { liner_color_1.l = 40; liner_color_2.l = 10; } else { liner_color_1.l = 30; liner_color_2.l = 0; } } else { liner_color_2.h = nowColor.hsla.h; liner_color_2.s = nowColor.hsla.s; liner_color_1.h = nowColor.hsla.h; liner_color_1.s = nowColor.hsla.s; if (config.linearDeep == 'light') { liner_color_1.h = liner_color_1.h;//色相需要往前偏移加强色系 liner_color_1.s = 90;//饱和度需要加强 liner_color_1.l = 70; liner_color_2.l = 44; } else if (config.linearDeep == 'dark') { liner_color_2.s = 90; liner_color_2.l = 26; liner_color_1.s = 90; liner_color_1.l = 50; } else if (config.linearDeep == 'accent') { liner_color_1.h -= 0;//色相需要往前偏移加强色系 liner_color_1.s = 90;//饱和度需要加强 liner_color_1.l = 54; liner_color_2.h -= addling;//偏移30度的色相搭配色进行渐变 liner_color_2.s = 90;//饱和度需要加强 liner_color_2.l = 54; } } if (config.dark) { liner_color_1.l = 40 liner_color_2.l = 40 txcolor.l = 90; } // 背景颜色取中间。 let color_t_1 = colortool.rgbaToCss(colortool.hslaToRgba(liner_color_1)); let color_t_2 = colortool.rgbaToCss(colortool.hslaToRgba(liner_color_2)); if (!config.text && !config.outlined) { css.backgroundColorCss = { 'background-image': `linear-gradient(${dir_str},${color_t_1},${color_t_2})` } let newBgcolor = { h: (liner_color_1.h + liner_color_2.h) / 2, s: (liner_color_1.s + liner_color_2.s) / 2, l: (liner_color_1.l + liner_color_2.l) / 2, a: (liner_color_1.a + liner_color_2.a) / 2 } let newBgcolorRgb = colortool.hslaToRgba(newBgcolor) if (!config.dark) { if (!isDarkColorFun(newBgcolorRgb.r, newBgcolorRgb.g, newBgcolorRgb.b) && nowColor.hsla.h != 0 && nowColor.hsla.s != 0) { txcolor.l = 20; } } css.backgroundColor = colortool.rgbaToCss(colortool.hslaToRgba(newBgcolor)); css.gradientColor = [color_t_1, color_t_2] css.linearDirectionStr = dir_str; } } if (config.dark == true) { // css.cardcolor = '#0A0A0B'; //项目 // css.inputcolor = '#111112';//输入框,表单等 // css.bodycolor = 'rgba(5,5,5, 1.0)';//背景 // css.disablecolor = 'rgba(30, 30, 30, 1.0)';//禁用的项目或者表单 // css.textDisableColor = 'rgba(100, 100, 100, 1.0)';//文本禁用色. css = { ...css, ...uni.$tm.config?.themeConfig?.dark ?? {} } } css.textColor = colortool.rgbaToCss(colortool.hslaToRgba(txcolor)); if (config.dark) { if (nowColor.hsla.h == 0 && nowColor.hsla.s == 0) { css.border = colortool.rgbaToCss(colortool.hslaToRgba({ ...nowColor.hsla, l: 12 })); } else { css.border = colortool.rgbaToCss(colortool.hslaToRgba({ ...nowColor.hsla, l: bghsl.l + 10 })); } } else { if (nowColor.hsla.h == 0 && nowColor.hsla.s == 0) { css.border = colortool.rgbaToCss(colortool.hslaToRgba({ ...nowColor.hsla, l: 90 })); } else { // text时,使用浅色线条,outlined时与颜色相同 if ((config.text && config.outlined)) { css.border = colortool.rgbaToCss(colortool.hslaToRgba({ ...nowColor.hsla, l: 90 })); } else if (!config.text && config.outlined) { css.border = colortool.rgbaToCss(colortool.hslaToRgba({ ...txcolor })); } else if (!config.text && !config.outlined && config.borderWidth > 0) { css.border = colortool.rgbaToCss(colortool.hslaToRgba({ ...nowColor.hsla, l: bghsl.l - 3 })); } } css.border = config.borderColor || css.border } //设置边线样式。 let bcss = `${config.borderWidth}rpx ${config.borderStyle} ${css.border}`; if (config.borderDirection == 'all') { css.borderCss[`border`] = bcss; } else if (config.borderDirection == 'x' || config.borderDirection == "leftright") { css.borderCss[`border-left`] = bcss; css.borderCss[`border-right`] = bcss; } else if (config.borderDirection == 'y' || config.borderDirection == "topbottom") { css.borderCss[`border-top`] = bcss; css.borderCss[`border-bottom`] = bcss; } else if (config.borderDirection == 'bottomleft') { css.borderCss[`border-left`] = bcss; css.borderCss[`border-bottom`] = bcss; } else if (config.borderDirection == 'bottomright') { css.borderCss[`border-right`] = bcss; css.borderCss[`border-bottom`] = bcss; } else if (config.borderDirection == 'topleft') { css.borderCss[`border-left`] = bcss; css.borderCss[`border-top`] = bcss; } else if (config.borderDirection == 'topright') { css.borderCss[`border-right`] = bcss; css.borderCss[`border-top`] = bcss; } else { let str = '-' + config.borderDirection; css.borderCss[`border${str}`] = bcss; } return css; } } export default { isCssColor, themeColors, getColor };