作者:彩虹棒棒糖
代码仓库:ColorTools
前言
作为前端攻城狮,日常工作中难免要写CSS,写CSS时,就一定会涉及到色彩的选择,这时,我们一般会在一些设计的网站上查找配色素材。这样的网站或者工具有很多,但是“不折腾就难受”的性子,利用业余时间,使用react开发了一个简易的色彩在线调试工具。
预览
体验地址:colortools
工具包含提供了常用的色板和渐变色调试工具。其中色板工具参考了utools的色彩小助手工具,渐变色参考了css渐变网站,在此表示感谢!
色板
渐变色
代码设计
项目结构:
其中,src目录下的index.js为入口文件,router.js为路由入口,独立出来,便于配置;pages为页面文件,components存放公共组件,configs存放一些配置信息;
路由 react-router
整个工具只有三个页面,1.首页,2.色板页,3.渐变色页。三个页面,使用右下角的按钮新型导航跳转;
import React from 'react';
import './index.css';
import {HashRouter as Router,Route,Switch} from 'react-router-dom';
import config from './configs/config';
import Home from './pages/home';
import ColorPlate from './pages/colorPlate';
import ColorGradient from './pages/colorGradient'
import NavButtonGroup from './components/NavButtonGroup';
const {navbuttons} = config;
const BasicRoute = () => (
<Router>
<div className="main-container">
<NavButtonGroup
navButtons={navbuttons.navButtons}
mainButton={navbuttons.main}
/>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/colorplate" component={ColorPlate} />
<Route exact path="/colorgradient" component={ColorGradient} />
</Switch>
</div>
</Router>
);
export default BasicRoute;
<NavButtonGroup />
组件是右下角的导航组件;因为组件较为简单,同时为了避免写重复的代码,将导航组件放在路由根部,在首页时,做一些处理,让其不显示就可以了;
色板
色板页面是/pages/colorplate页面组件;色板分为三个部分,
在下方的slider上选择颜色,会在预览区显示大块的颜色,颜色值区会显示颜色对应的rgb值和hex值,这两种都是前端常用的颜色格式;选择颜色的同时,会把颜色hex值复制到剪贴板;复制内容到剪贴板,使用了copy-to-clipboard;
import React , {useState} from 'react';
import {Tabs} from 'antd';
import ColorSlider from './ColorSlider';
import ColorValue from './ColorValue';
import ColorCard from './ColorCard';
import colorplateConfig from '../../configs/colorplate.config';
import {HexToRGB} from '../../utils/utils'
import './index.css';
const { TabPane } = Tabs;
export default props => {
const [color,setColor] = useState('#69c0ff');
const [rgb,setRGB] = useState(HexToRGB(color).format);
//颜色设置函数
const handleSetColor = color=>{
setColor(color);
let rgb = HexToRGB(color); //hex转RGB函数,由hex颜色获取rgb颜色
setRGB(rgb.format)
}
return (
<div className='colorplate-wrapper'>
<div className='color-showing' style={{backgroundColor:color}}></div>
<div className='colorplate'>
<div className='color-value'>
<ColorValue value={color} />
<ColorValue value={rgb} />
</div>
<div className='colorslider'>
<Tabs defaultActiveKey='ant' >
<TabPane tab='Ant' key='ant'>
{colorplateConfig.ant.map((item,index)=>(
<ColorSlider
key={index}
slider={item}
setColor={handleSetColor}
/>
))}
</TabPane>
<TabPane tab='ColorTale' key='colortale'>
<div className='colorcard-contianer'>
{colorplateConfig.colortable.map((item,index)=>(
<ColorCard
key={index}
colorTable={item}
setColor={handleSetColor} />
))}
</div>
</TabPane>
</Tabs>
</div>
</div>
</div>
)
}
这里将颜色块分装成组件<ColorSlider />,
暴露出颜色参数slider和颜色联动函数setColor;ColorCard />
与其类似,是对颜色进行了主题的分类;<ColorValue />
用于展示颜色值得组件,同样提供复制到剪贴板功能;
**PS:**这里其实可能有个小隐患,就是使用数组渲染数据时,使用的是索引作为key,由于组件只是作为展示,并不涉及修改组件的操作,所以使用所以作为key也没啥问题,具体react中为什么要使用key请看React之key详解;
渐变色工具
先上图:
渐变色工具,调整的属性是线性渐变linear-gradient(线性渐变实际中使用的较多);工具提供四个功能:增减颜色、调整渐变角度、调整颜色比例、重置和复制渐变颜色值;
加号按钮,可以增加颜色,默认为白色,最多可是增加5个颜色;第二个角度按钮可以调整颜色的角度,齿轮按钮可以调整各个颜色占得比例;
点击颜色的小圆圈,可以修改当前的颜色值,这里使用的react-color组件;
渐变色的传值为字符串,如:’linear-gradient(120deg,#a1c4fd 0%,#c2e9fb 100%)‘,这样的好处时,数据可以直接拿来渲染组件,不用经过处理,而在处理颜色时,就需要将字符串转为对象的形式,便于处理;
两个核心的函数:
//解析渐变色为对象
const exactGradientToObj = (gradient)=>{
let gradientArray = gradient.
replace('linear-gradient','').replace(/[(|)]/g,'').split(',');
//分离颜色数组,颜色包括颜色值和所占的百分比
let colors = gradientArray.filter((item,index)=>index).map(color=>{
color = color.split(' ');
return {color:color[0],percent:color[1]}
});
return {
angle:gradientArray[0], //角度是整体参数,单独列出
colors
}
};
//解析渐变色为字符串
const exactGradientToStr = gradientObj=>{
let colorsArray = gradientObj.colors.map(item=>`${item.color} ${item.percent}`);
return 'linear-gradient(' + [gradientObj.angle,...colorsArray].join(',') + ')';
}
解析为对象是为了后续的相关颜色操作的修改,同时,按钮所绑定的值都是对象上解析出来的,所以修改对象,按钮对应的值也会联动改变;反解对象为字符串,是为了颜色可以实时预览,因为预览的圆形的style绑定的是gradient字符串;所以这两个函数,在后续的颜色相关修改上,都会用到,这样就解决了实时预览和数据联动的问题了;例如,修改某一个渐变色(点击小圆圈修改):
//修改颜色
const changeColor = (color,index)=>{
let _color = '';
const {hex,rgb} = color;
if(rgb.a < 1){
_color = `rgba(${rgb.r},${rgb.g},${rgb.b},${rgb.a})`;
}
else {_color = hex;}
gradientObj.colors[index].color = _color;
handleChangeGradientObj(gradientObj);
setGradient(exactGradientToStr(gradientObj));
}
使用react-color时,是可以调整颜色的透明度的,就是rgba,所以要对此做出兼容,判断react-color的返回值中的rgb字段的透明度a是否小于1,小于1说明调整了透明度,而hex颜色是不能反映透明度信息的,所以这时颜色要用rgba;
因为最多可以添加5个颜色(其实是可以随意添加,只是自己有些懒的去算增加颜色比例的问题),对,就是5个,谁没事加那么多颜色完【任性!!】。所以就把各个颜色的比例固化下来:
const GRADIENT_RULE = {
2:['0%','100%'],
3:['0%','50%','100%'],
4:['0%','25%','50%','100%'],
5:['0%','13%','25%','50%','100%']
};
//设置颜色百分比
const setColorPercent = (colors)=>{
let percentArray = GRADIENT_RULE[colors.length];
if(!percentArray){
return false;
}
return colors.map((item,index)=>{
item.percent = percentArray[index];
return item;
})
}
增减颜色时,会根据颜色数组的长度查找配置表,匹配就会返回对应的比例数组;
小结
代码虽然并不复杂,我还刻意的使用hooks(只用了一点点😜),算是督促自己学习吧!
在此欢迎各位同学体验:colortools