方法的实际效果是,输入一个base color,通过输入参数1~5得到比base颜色浅一些的5种颜色,参数7-10可获得比base color深一些的颜色。
根据输入参数,执行方法:
if (index <= 6) {
return tinycolor.mix(
'#ffffff',
color,
currentEasing * 100 / primaryEasing
).toHexString();
}
return tinycolor.mix(
getShadeColor(color),
color,
(1 - (currentEasing - primaryEasing) / (1 - primaryEasing)) * 100
).toHexString();
这个过程可以理解为根据传入的最后一个参数,中和白色和base color。为了让输出的结果随着参数的变化,显得的更平滑,方法中引入了贝叶斯曲线。
其中p1和p2为两个基点,p0和p1的连线,以及p2和p3的连线是和曲线相切的,ant-design中采用的基点是:
BezierEasing(0.26, 0.09, 0.37, 0.18);
当传入不同的P1.x时,方法BezierEasing
可输出曲线上对应的P1.y值。
上面方法中的
currentEasing * 100 / primaryEasing
其中currentEasing = BezierEasing(index * 0.1);//这里index为文章开始说道的参数,及@purple-1: color(~`colorPalette("@{purple-6}", 1)`);中的1
其中primaryEasing = BezierEasing(0.6);
这样就构造了tinycolor.mix方法中的amount参数
再细看tinycolor.mix时如何输出一个中间色的:
tinycolor.mix = function(color1, color2, amount) {
amount = (amount === 0) ? 0 : (amount || 50);
var rgb1 = tinycolor(color1).toRgb();
var rgb2 = tinycolor(color2).toRgb();
var p = amount / 100;
var rgba = {
r: ((rgb2.r - rgb1.r) * p) + rgb1.r,
g: ((rgb2.g - rgb1.g) * p) + rgb1.g,
b: ((rgb2.b - rgb1.b) * p) + rgb1.b,
a: ((rgb2.a - rgb1.a) * p) + rgb1.a
};
return tinycolor(rgba);
};
- color1在index小于6的时候为白色#ffffff, index大于6的时候为getShadeColor返回的一个颜色(稍后再说),不是黑色
- color2为base color
- base color的rgba四个数值,分别根据传入的amout的参数,做上述运算,得到新的rgba
- 最后将新得到的rgba进行归零运算(相当于四舍五入,去掉多余的小数点位数)
再看获取深色时,构造出来的getShadeColor:
var getShadeColor = function(c) {
var shadeColor = tinycolor(c);
// warm and cold color will darken in different radio, and rotate in different degree
// warmer color
if (shadeColor.toRgb().r > shadeColor.toRgb().b) {
return shadeColor.darken(shadeColor.toHsl().l * warmDark * 100).spin(warmRotate).toHexString();
}
// colder color
return shadeColor.darken(shadeColor.toHsl().l * coldDark * 100).spin(coldRotate).toHexString();
}
我也没太明白,一个复杂的运算,将颜色先映射到HSL空间,最后将亮度空间按照变深的方向旋转一定角度,得到一个比原色深一些的颜色。将原色和这个深色带入tinycolor.mix方法中得到一个中间色。
基本思路就是这样。。