react学习笔记——react构建在线调色工具

2,465 阅读6分钟

cirolee.github.io_colorTools_.png

作者:彩虹棒棒糖

代码仓库:ColorTools

前言

作为前端攻城狮,日常工作中难免要写CSS,写CSS时,就一定会涉及到色彩的选择,这时,我们一般会在一些设计的网站上查找配色素材。这样的网站或者工具有很多,但是“不折腾就难受”的性子,利用业余时间,使用react开发了一个简易的色彩在线调试工具。

预览

体验地址:colortools

工具包含提供了常用的色板和渐变色调试工具。其中色板工具参考了utools的色彩小助手工具,渐变色参考了css渐变网站,在此表示感谢!

色板

colorgradient.png

渐变色

colorplate.png

代码设计

项目结构:

mulu.png

其中,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页面组件;色板分为三个部分,

seban-1.png

在下方的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详解

渐变色工具

先上图:

colorplate.png

渐变色工具,调整的属性是线性渐变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