6

一个灵活高度自定义的JavaScript颜色选择器

 3 years ago
source link: https://segmentfault.com/a/1190000039670041
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

ew-color-picker

这是一个用javascript编写的灵活的,高度自定义的颜色选择器。

这个颜色选择器适用于中小型项目,例如主题的切换。不同于组件库中的颜色选择器组件,它的配置自主化,根据用户的需求来自定义。

html5的原生颜色选择器样式不好看,而组件库的颜色选择器不够灵活多变,这样一来,就有了这个颜色选择器的诞生。

我们先来尝尝鲜,看看一个简单的示例:

  <!-引入颜色选择器的css样式-->
  <link rel="stylesheet" href="https://www.unpkg.com/ew-color-picker/dist/ew-color-picker.min.css">
  <!--引入插件JavaScript-->
  <script src="https://www.unpkg.com/ew-color-picker/dist/ew-color-picker.min.js"></script>

然后在页面中放一个元素:

  <div></div>

javascript中,我们只需要如下代码:

   const color = new ewColorPicker('div');

如此一来,一个简单的颜色选择器就出现在页面上了。可能大多数人不大喜欢实例化的方式,那么我们也提供了一个方法来创建它:

  const color = ewColorPicker.createColorPicker('div');

这样也可以创建一个颜色选择器实例。

tips:需要注意的就是,这些功能都是1.6.7版本加上的,所以请使用最新版本的js,实际上,以上展示的引入链接会自动帮我们引入最新版本的js,使用最新版本的js,确保我们在使用当中不会出现bug以及使用新功能,只要我在,这个插件就会自动更新,只要能想到的东西,都会加上去。

tips:还需要说明一点的是,为了遵循一个颜色选择器对应一个实例,所以,当传入的dom元素是多个的话,也会取第一个dom元素来实例化。例如传的是div元素,如果页面中有多个div元素,那实际上在颜色选择器内部获取到的div元素就是多个,但始终都会取第一个div元素来实例化。如果想要实例化多个颜色选择器,我们则可以像如下代码那样使用

   const elements = document.querySelectorAll('div');
   elements.forEach(item => new ewColorPicker(item));

我们也提供了一个方法getDefaultConfig来获取颜色选择器实例的默认配置对象。如下:

  ewColorPicker.getDefaultConfig();

tips:还需要注意的就是,传入的dom元素不能是'html','head','body','meta','title','link','style','script'这些特殊的元素,否则插件会在控制台给出一个错误提示。

tips:最新1.7.1版本允许添加到body元素中,当然还是不建议如此做,这个添加有些许bug。

这都是最简单的用法,可能这样不太直观,请看如下一个简单的示例:

demo1

看到这里,也许会有人疑问,这怎么就灵活多变,高度自定义呢?别着急,让我们继续。

自定义配置

我们来看一个配置对象,如下所示:

{
    hue: true,
    alpha: false,
    size: "normal",
    predefineColor: [],
    disabled: false,
    defaultColor: "",
    openPickerAni: "height",
    sure: emptyFun,
    clear: emptyFun,
    openPicker: emptyFun,
    isLog: true,
    changeColor: emptyFun,
    hasBox: true,
    isClickOutside: true,
    hasClear:true,
    hasSure:true,
    hasColorInput:true
}

我们先来分析第一个配置属性hue,或许我们看到一个完整的配置颜色选择器,应该是如下图所示:

1616080898(1).jpg

我们来着重分析一下每一块代表什么:

1.png

根据上图分析,我们也知道了hue的属性就是控制最右边的色阶柱的显隐,显然默认是显示的。

tips:如果是自定义配置,那么传入的元素在配置对象中就是el属性,例如,我们只需要一个颜色面板。那么我们可以编写如下代码:

  const color = new ewColorPicker({
      el:'div',
      hue:false
  })

如此一来,我们就会得到如下所示的颜色选择器:

2.png

正如图中所示,就一个红色的面板可供选择,这确实是一个不好的选择,不过没关系,我们提供了updateColor方法去手动改变颜色值。代码如下:

   //color为实例化的颜色选择器实例
   color.updateColor("#0ff");

当然,使用这个方法的前提是颜色选择器面板必须显示当中,并且传入的参数还要是一个正确格式的颜色,否则会在控制台给出错误提示,也不会生效。

请看如下一个示例:

demo

好,让我们接着来看第二个配置属性alpha,很显然这个属性是为了控制透明度柱子的显隐的,默认是不显示的。例如,我们可以这样修改:

   const color = new ewColorPicker({
      el:'div',
      hue:false,
      alpha:true
  })

以上代码就会得到如下图所示的一个颜色选择器:

3.png

可能很多同学注意到了从前面的一个示例中设置了这样一个hasBox属性,它的默认值是true,很显然这个值是控制色块的显隐的,如果该值为false,那么颜色面板默认就会显示。所以,我们提供了两个方法openPickerclosePicker来手动控制颜色面板的关闭,(PS:点击目标元素区域之外关闭稍后再说)。如下所示:

 //color为颜色选择器实例
 color.openPicker(openPickerAni);//参数为即height或opacity两种字符串值,等同后续的openPickerAni配置属性
 color.closePicker(openPickerAni);

我们来看如下一个手动控制颜色选择器关闭的示例:

demo

在以上示例中,可能有人注意到了isClickOutside这个属性,没错这个属性也是一个布尔值,默认为true,表示点击颜色面板之外的区域,就会关闭颜色面板。来看如下的示例:

<div id="demo"></div>
<button type="button" id="openClickOutsideBtn">开启|关闭目标区域元素点击事件</button>
button {
  float:right;
}
const color = new ewColorPicker({
  el:"#demo",
  isClickOutside:false
})
document.getElementById("openClickOutsideBtn").onclick = function(){
  color1.config.isClickOutside = !color1.config.isClickOutside;
  //为了避免出现意想不到的问题,在修改属性之后需要重置状态,并重新渲染一次颜色选择器
  //因为是通过配置对象的pickerFlag属性控制面板的显隐的,这是一个私有属性
  color1.config.pickerFlag = false;
  //实例上的render方法为原型对象上的,需要传入实例中的元素和修改过后的配置对象作为参数
  //实例上的rootElement属性保存着根元素
  color1.render(color1.rootElement,color1.config);
}

demo

让我们继续,我们可以看到size属性,他的值可以是字符串值,也可以是对象。字符串值主要为这四个normal,medium,small,mini中的其中一个,或者也可以自定义一个对象{ width:25;height:25 },默认值是normal。当然设置该值的前提是将hasBox属性设置为true,盒子元素都不显示,设置该值有什么用呢?后面的openPickerAni属性与openPicker方法也是同样的必须要将hasBox设置为true,这也是默认将该值设置为true的原因。让我们来看看如下一个示例:

    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    const colors = document.querySelectorAll('div');
    const colorConfigs = [
        {
            size:"normal"
        },
        {
            size:"medium"
        },
        {
            size:"small"
        },
        {
            size:"mini"
        },
        {
            size:{
                width:25,
                height:25
            }
        }
    ];
    colors.forEach((item,index) => {
        new ewColorPicker({
            el:item,
            ...colorConfigs[index]
        })
    })

可以看到运行效果如下图所示:

4.png

让我们接着看下一个属性predefineColor,顾名思义,这个属性是一个数组,代表预定义颜色,每一个数组项必须是一个合格的颜色值,否则是不会渲染到颜色选择器上的。来看如下一个示例:

  <div></div>
    const color = new ewColorPicker({
        el:"div",
        predefineColor:["#2396ef","#fff","rgba(134,11,12,1)","#666"],
        alpha:true
    })

然后我们可以看到如下图所示:

5.png

让我们接着看下一个属性,disabled,这个属性的作用就是禁止点击盒子块元素打开颜色面板,也就是说如果hasBoxfalse的话,请忽略这个属性。

tips:后续可能会考虑增加颜色面板的禁止点击事件等等。

这个很简单没什么好说的,所以就不举例了。让我们接着来看下一个属性defaultColor,即默认显示的颜色值。如果检测到的颜色值不符合格式,则会在控制台给出错误提示,比如看这样一个示例:

  <div></div>
    const color = new ewColorPicker({
        el:"div",
        predefineColor:["#2396ef","#fff","rgba(134,11,12,1)","#666"],
        alpha:true,
        defaultColor:"#123"
    })

如下图所示:

6.png

tips:或许这个检测颜色值是否合格的机制有些许问题,后续会优化。

让我们接着来看下一个属性openPickerAni,它就只有两个值,和前面手动开启或关闭颜色选择器方法的参数值一样,这里就不必赘述,当然想要该属性生效不能将hasBox设置为false

同样的openPicker也是针对hasBoxtrue而生效的,它是点击色块元素的回调,它有两个回调的参数。即elcontext,也就是元素本身和元素本身的实例对象。

  const color = new ewColorPicker({
     el:"div",
     openPicker:(el,context) => {
        //可以通过context.config.pickerFlag来判断是打开还是关闭
     }
  })

同理clearsure就是清空按钮和确定按钮的回调,要让这两个回调生效,就不能将hasClearhasSure设置为false,因为这两个配置属性分别是空值清空和确定的显隐的。其中hasClear的回调参数为defaultColor,该值为空就为空,以及元素本身实例对象context。而sure的回调参数则是color值和元素本身实例对象。请看如下写法:

   const color = new ewColorPicker({
     el:"div",
     clear:(defaultColor,context) => {
        console.log(defaultColor,context);
     },
     sure:(color,context) => {
       console.log(color,context);
     }
   })

除了这两个回调之外,我们还额外增加了一个回调即changeColor函数,顾名思义,这个函数的作用就是当颜色值改变时触发,比如点击色阶柱改变色彩,点击透明度柱改变透明度等等。请看如下代码:

   const color = new ewColorPicker({
     el:"div",
     changeColor:(color) => {
         //颜色值只要改变时就触发,回调参数为改变后的颜色值
     }
   })

还有一个isLog属性,这个属性的默认值是true,表示会在控制台打印一些信息,请忽略这个属性,啊哈哈,后续考虑将它的默认值设置为false

最后一个就是hasColorInput属性,表示是否显示输入框,这在自定义输入框(比如和element ui的输入框绑定在一起)和颜色选择器绑定中十分有效,如果想要使用它,就不推荐设置为false

我们来看一个示例如下:

  <div></div>
    const color = new ewColorPicker({
        el:"div",
        hasColorInput:false,
        hasSure:false,
        hasBox:false,
        hasClear:false,
        alpha:true
    })

效果如下图所示:

7.png

目前最新版本为1.6.8,后续还会考虑加更多的功能,只要你有需求,跟我提,我觉得合理就会加,如果觉得本颜色选择器可以帮助到你,还望给个star,源码

更多描述可以参见文档官网和码云站点文档官网

tips:如果github访问太慢,可以访问码云站点的官网。

最后,后续有空的话,我会考虑写文章来分析这个颜色选择器的实现原理。

  • 1.8.5 取消el属性和不传dom元素的验证,如果不传任何参数,则默认将颜色选择器添加到body中(但会生成一个容器元素来包含)。
  • 1.8.3 ~ 1.8.4 修复了一些问题,优化了一些代码
  • 1.8.2 修复了水平方向透明度改变问题,并调整了一下布局和优化了一些代码。
  • 1.8.1 修复了一些问题,并添加了hueDirectionalphaDirection属性。
  • 1.8.0 修复了添加到body中的问题,以及修改了将disabled设置为true的问题。
  • 1.7.9 修复了隐藏色块的问题。
  • 1.7.8 修复了将input隐藏的问题,优化了代码,将openPickerAni配置属性名更改为pickerAnimation
  • 1.7.7 修复了预定义颜色的一些问题,优化了一些代码。
  • 1.7.6 修复了一些问题,开放了内部工具方法,可通过ewColorPicker.util访问到所有工具方法,并修改了颜色值的验证,支持英文颜色单词的传入,例如设置预定义颜色以及默认颜色。
  • 1.7.5 修复了透明度默认赋值问题,将原openPicker点击色块打开或关闭的回调更名为openOrClosePicker,优化了代码。
  • 1.7.4:修复了颜色模式切换透明度不改变问题,新增了changeBoxByChangeColor配置属性,该属性表示是否在打开颜色面板,颜色值触发的时候,色块的背景色更改,如果不点击确定按钮,关闭颜色面板后会恢复到默认颜色,预定义颜色数组predefineColor新增了可以传数组项为对象或字符串,对象定义为{ color:"#123",disabled:true }(color为合格的颜色值,disabled为true或者false,表示是否禁用该预定义点击更换颜色)
  • 1.7.3:优化了颜色值算法,新增了boxDisabledopenChangeColorMode配置属性。
  • 1.7.2:新增了允许将颜色选择器添加到body中,但会生成一个容器元素来包含,将disabled配置属性更改成了全部禁止点击。
  • 1.3.3 ~ 1.7.1:添加了颜色选择器的基本功能。

打个广告,我在思否上线的课程玩转typescript1玩转typescript2适用于有一定基础的前端,还望大家多多支持,谢谢。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK