less换肤功能实践

栏目: 编程工具 · 发布时间: 5年前

内容简介:在我司的后台管理组件库为了统一各产品的视觉和操作体验,我们建立了以扁平化和简洁为主旨的设计风格,使用块面来进行布局,用线条来表达各个控件,使功能庞杂的系统 既直观又条理清晰,让使用者一目了然。

在我司的后台管理组件库 pagurain 、rsuite中要求实现换肤功能,以下是我们对这一功能实践的记录及过程。

前提

为了统一各产品的视觉和操作体验,我们建立了 UI规范体系 ,方便创建项目也方便统一管理。

以扁平化和简洁为主旨的设计风格,使用块面来进行布局,用线条来表达各个控件,使功能庞杂的系统 既直观又条理清晰,让使用者一目了然。

主色及色阶

系统共用的组件颜色和变化形式是统一的,在此基础上,各系统又有自己的主色调。

每套系统都会有一个主色,并在主色的基础上,在同一色调中扩充成一组完整的可复用的色彩体系,丰富系统配色。

如下图所示,每组色彩是按一定的规律在明度和饱和度上选取得出的。

less换肤功能实践

初步实现

按照上面的实现,我们的多套皮肤就是先定义一个主色 @H500 ,然后使用 @H500 这个颜色计算出其他的颜色,就搞定了。每次在不同的主题就换一套颜色。当然最终还是要生成多套颜色的 css

下面就按照这个思路开始吧。首先,我们按照设计师的要求定义一组颜色,如下:

@H050:#e8f4ee;
@H100:#bbdfcb;
@H200:#8dcaa8;
@H300:#67b88b;
@H400:#41a66e;
@H500:#1b9451;
@H600:#188247;
@H700:#146f3d;
@H800:#115d33;
@H900:#0e4a29;

这组颜色的计算规则如下:

@H050:darken(@H500,90%);
@H100:darken(@H500,70%);
@H200:darken(@H500,50%);
@H300:darken(@H500,33.3%);
@H400:darken(@H500,16.6%);
@H500:#1b9451;
@H600:lighten(@H500,12.5%);
@H700:lighten(@H500,25%);
@H800:lighten(@H500,37.5%);
@H900:lighten(@H500,50%);

这猛一看挺简单啊,颜色的计算规则也有了, less 也有相应的函数,这不很简单么。直接一算就出来了。

结果呢:

先用个绿色( #1b9451 )试试

less换肤功能实践

换个蓝色( #b3d1ff )呢

less换肤功能实践

结果发现,如果颜色太深,那么 darken 后的颜色就是一堆黑色,如果颜色偏浅,那 lighten 后的颜色就是一堆白色。所以显然,使用 less 自带的颜色函数式不行的。那怎么办呢?

最简单的方法就是,现在外面算好了再复制进来,每次都复制10个颜色。计算颜色的方法,如下:

/*
 * Color utility functions
 * Source: http://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color-or-rgb-and-blend-colors
 * Github: https://github.com/mbitson/mcg
 */
function shadeColor(color, percent) {
    var f = parseInt(color.slice(1), 16),
        t = percent < 0 ? 0 : 255,
        p = percent < 0 ? percent * -1 : percent,
        R = f >> 16,
        G = f >> 8 & 0x00FF,
        B = f & 0x0000FF;
    return "#" + (0x1000000 + (Math.round((t - R) * p) + R) * 0x10000 + (Math.round((t - G) * p) + G) * 0x100 + (Math.round((t - B) * p) + B)).toString(16).slice(1);
}

为此我们还特意做了一个页面来方便使用, 页面链接

这样一来最起码的颜色就有了,我们只需先用这些变量生成一套基础的主题 base.less ,然后分别创建多个主题文件的 green.lessblue.less ,再分别覆盖这10个颜色变量,然后

@import "base"; //按照less 语法import less 可以省略文件ext

最终就可以得到多套 css 了。

改进

一次只传一个颜色

仅仅是那样,用肯定是没问题了,但是每次使用都要去生成配色的页面生成颜色,用着着实不爽。于是乎就想着能不能够有什么方法,自己去定义一个方法在less里直接调用。最终发现 grunt-contrib-less 这个插件有一个 customFunctions 方法,可以实现自定义方法,所以改进了一下。而且可以覆盖原有的变量,所以改进了一下,得到了如下代码

//生成主题
grunt.registerTask('theme', 'Generate theme', function () {
    Object.keys(themes).forEach((name) => {
        const color = themes[name];
        const taskName = `theme-${name}`;
        const outputName = `src/resources/css/themes-${name}.css`;
        grunt.config.merge({
            less: {
                [taskName]: {
                    options: {
                        customFunctions: {
                            pallet
                        },
                        modifyVars: {
                            'base-color': color
                        }
                    },
                    files: {
                        [outputName]: 'src/resources/less/theme/base.less'
                    }
                }
            }
        });
        grunt.task.run(`less:${taskName}`);
    });
});

源代码地址 ;

扔掉 grunt

但是这个时候问题又来了,因为这样做的话,就只能用 grunt 进行构建了, gulp 构建或者 webpack 打包肯定不行啊(没有pallet方法),那怎么办呢。一个 偶然发现 使用less中的转义语法 ~ 居然可以执行js。简直了。然后经过测试使用这种hack方法可以成功的定义function,就解决了一切问题.

.colorPaletteMixin {
    @functions: ~`(function () {
    /*
     * Color utility functions
     * Source: http://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color-or-rgb-and-blend-colors
     * Github: https://github.com/mbitson/mcg
     */
    var shadeColor = function (color, percent) {
        var f = parseInt(color.slice(1), 16),
            t = percent < 0 ? 0 : 255,
            p = percent < 0 ? percent * -1 : percent,
            R = f >> 16,
            G = f >> 8 & 0x00FF,
            B = f & 0x0000FF;
        return "#" + (0x1000000 + (Math.round((t - R) * p) + R) * 0x10000 + (Math.round((t - G) * p) + G) * 0x100 + (Math.round((t - B) * p) + B)).toString(16).slice(1);
    }

    /**
     * 计算系统颜色
     * @param color
     * @param percent (正值表示lighter,负值表示darken)
     */
    this.pallet = function (color, percent) {
        var colorConfig = {
            '50': 0.9,
            '100': 0.7,
            '200': 0.5,
            '300': 0.333,
            '400': 0.166,
            '500': 0,
            '600': -0.125,
            '700': -0.25,
            '800': -0.375,
            '900': -0.5
        };
        percent = colorConfig[percent] === undefined ? percent : colorConfig[percent] ;
        color = color.toLowerCase();
        return shadeColor(color, percent);
    }
})()`;
}
// It is hacky way to make this function will be compiled preferentially by less
.colorPaletteMixin();

小结

最后我只想说,写好文档太重要了,这里各种的坑,简直是踩也踩不完。说多了都是泪。安利一下我司的 react 组件库rsuite。l


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

PHP和MySQL Web开发(原书第4版)

PHP和MySQL Web开发(原书第4版)

Luke Welling、Laura Thomson / 武欣 / 机械工业出版社 / 2009 / 95.00元

本书将PHP开发与MySQL应用相结合,分别对PHP和MySQL做了深入浅出的分析,不仅介绍PHP和MySQL的一般概念,而且对PHP和MySQL的Web应用做了较全面的阐述,并包括几个经典且实用的例子。. 本书是第4版,经过了全面的更新、重写和扩展,包括PHP 5.3最新改进的特性(例如,更好的错误和异常处理),MySQL的存储过程和存储引擎,Ajax技术与Web 2.0以及Web应用需要......一起来看看 《PHP和MySQL Web开发(原书第4版)》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

html转js在线工具
html转js在线工具

html转js在线工具