一步步教你实现跨游览器的颜色选择器

本文介绍了一种跨浏览器的颜色选择器实现方法,通过HTML、CSS和JavaScript构建一个动态颜色选择面板,支持鼠标悬停预览颜色及点击选取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

虽然网上这样的代码一大把的,但不是自己实现总是不明白其原理,而且许多都是基于这个框架那个框架。需要这么复杂吗?其实许多问题只要会分解,就简单了。HTML其实本来都是很简单的东西,微软提出了DHTML后,把静态变成动态,有些人才被那炫目的效果看傻了眼睛。定一定神,我们把它还原成静态不就行了吗?!就像动画一样,本来都是一帧帧的静止画面。javascript的颜色选择器也一样,其实最开始不就是一个表格吗?!只不过每一个格子的颜色不一样,至于动态效果,我们也可以一步分解成我们可以解决的部分。

打造整体框架


<!doctype html>
<html dir="ltr" lang="zh-CN"> 
    <head> 
        <meta charset="utf-8"/> 
        <meta http-equiv="X-UA-Compatible" content="IE=Edge"> 
        <title>跨游览器的颜色选择器</title>
        <script type="text/javascript">
            /* <![CDATA[ */

            /* ]]> */
        </script>
        <style>
            //
        </style>
    </head>
    <body>
    </body>
</html>

添加静态多彩表格

姑且是这样叫吧,当我们的脚本检测到我们的页面存在一个ID为"colorpicker"的DIV时,它就会在其里面建立一个两行六格的表格,然后格子里面再套表格,为6X6的规格,在遍历的同时也把格子的背景色也填了。unselectable属性为IE准备的,防止焦点丢失!

添加行为层代码(javascript)

 //用于生成颜色选择器的具体内容
var colorPickerHtml = function(){
    var  _hex = ['FF', 'CC', '99', '66', '33', '00'];
    var builder = [];
    // 呈现一个颜色格
    var _drawCell = function(builder, red, green, blue){
        builder.push('<td bgcolor="');
        builder.push('#' + red + green + blue);
        builder.push('" unselectable="on"></td>');
    };
    // 呈现一行颜色
    var _drawRow = function(builder, red, blue){
        builder.push('<tr>');
        for (var i = 0; i < 6; ++i) {
            _drawCell(builder, red, _hex[i], blue)
        }
        builder.push('</tr>');
    };
    // 呈现六个颜色区之一
    var _drawTable = function(builder, blue){
        builder.push('<table class="cell" unselectable="on">');
        for (var i = 0; i < 6; ++i) {
            _drawRow(builder, _hex[i], blue)
        }
        builder.push('</table>');
    };
    //开始创建
    builder.push('<table><tr>');
    for (var i = 0; i < 3; ++i) {
        builder.push('<td>');
        _drawTable(builder, _hex[i]);
        builder.push('</td>');
    }
    builder.push('</tr><tr>');
    for (var i = 3; i < 6; ++i) {
        builder.push('<td>');
        _drawTable(builder, _hex[i])
        builder.push('</td>');
    }
    builder.push('</tr></table>');
    builder.push('<table class="color_result">/n/
                   <tr>/n/
                     <td class="color_view"></td>/n/
                     <td class="color_code"></td>/n/
                   </tr>/n/
                 </table>');
    return builder.join('');
};
#================
#================

window.onload = function(){
    var colorpicker = document.getElementById("colorpicker");
    colorpicker.innerHTML = colorPickerHtml();
}
添加结构层代码(HTML)

<div id="colorpicker">
</div>
添加表现层代码(CSS)

div#colorpicker table{border-collapse:collapse;margin:0;padding:0;}
div#colorpicker .cell td{height:12px;width:12px;}
.color_result{width:216px;}
.color_view{width:110px;height:25px;}
.color_code{text-align:center;font-weight:700;color:#666;font-size:16px;background:#eee;}

至此,我们的颜色选择器就出来了!

添加动态效果

我们要来在选择器上移动时,表格下面的两个大格子会显示鼠标所在小格的颜色与其颜色值,点击表格则停止选择……一步来吧。先添加事件监听函数


var addEvent = (function () {  
    if (document.addEventListener) {  
        return function (el, type, fn) {  
            el.addEventListener(type, fn, false);  
        };  
    } else {  
        return function (el, type, fn) {  
            el.attachEvent('on' + type, function () {  
                return fn.call(el, window.event);  
            });  
        }  
    }  
})();
监听鼠标移动的函数

我们要确保鼠标所在的地方为我们选择器的小格子,因此需要分析事件源是否为td元素。


//事件源函数
var getTarget = function(event){ 
    event = event || window.event; 
    var obj = event.srcElement ? event.srcElement : event.target; 
    return obj 
}
//用它给颜色选择器绑定mouseover事件
var bindMouseover = function(obj){
    addEvent(obj,'mouseover',function(e){
        var td = getTarget (e);
        var nn = td.nodeName.toLowerCase();
        if(nn == 'td'){
            //执行相关事件………………
        }
    });
}

然后我们得找出那两个大表格就行了,它们上面各有一个类名color_view与color_code。问题是如何从DOM中取出它们,我们应该尽量避免遍历这种做法,新的时代带来新的事件,我们也应该开拓一下视野。IE8发布了的今天,新式游览器拥有了许多强悍的查找方案,如querySelector,用法酷似JQuery与Prototype的$()选择器,返回一个DOM对象,IE8,FF3.1,safari4等都支持。还有getElementsByClassName,我也实现了一个跨游览器的,能根据平台自主选择原生方案或Pure DOM方案,具体参见这里。因此继续添加行为层代码,Go Go Go!


var getElementsByClassName = function (searchClass, node,tag) {
  /***************略,参见下面的部分*****************/
}

var bindMouseover = function(obj){
    addEvent(obj,'mouseover',function(e){
        var td = getTarget(e),
        nn = td.nodeName.toLowerCase(),//IE会自动转换为大写
        colorView,
        colorCode;
        if(document.querySelector){
            colorView = obj.querySelector('td.color_view');
            colorCode = obj.querySelector('td.color_code');
        }else{
            colorView = getElementsByClassName('color_view',obj,'td')[0];
            colorCode = getElementsByClassName('color_code',obj,'td')[0];
        }
        if(nn == 'td'){
            colorView.style.backgroundColor = td.bgColor;
            colorCode.innerHTML = td.bgColor;
        }
    });
}
window.onload = function(){
    var colorpicker = document.getElementById("colorpicker");
    colorpicker.innerHTML = colorPickerHtml();
    bindMouseover(colorpicker);
}

至此,鼠标移动时的效果就完成了。需要说明一下,为什么我们构建格子时是用bgcolor而不用style="background-color:#fff",这是因为FF会把颜色值转为RGB格式,会导致与IE的16进制格式不一致,另,RGB所占空间太多,会撑开我们的格子。

接下来就是点击事件了吧,错!因为目前我们这样的布局或设置是违背我们的常识,一般而言,颜色选择器是在我们点击一个按钮才弹出来,然后我们选择了颜色,单击后颜色值就会自动填写在相应的文本域中。不可能是一开始就僵硬地出现在页面上,这样根本没有动态生成的需要。因此我们得修改我们的结构层。

修改结构层的body部分。


<body>
    <form action="" method="post">
        <input type="text" value="点击弹出颜色选择器" id="color"/>
    </form>
</body>

修改行为层代码,让文本框获得焦点时弹出颜色选择器


window.onload = function(){
    var textfield = document.getElementById('color');
    var picker = document.createElement('div');
    picker.setAttribute("id","colorpicker");
    picker.innerHTML = colorPickerHtml();
    var body = document.getElementsByTagName("body")[0];
    body.insertBefore(picker,null);
    picker.style.display = 'none';
    bindMouseover(picker);
    addEvent(textfield ,'focus',function(){
        textfield.style.position = 'relative';
        picker.style.position = 'absolute';
        picker.style.display = 'block';
        picker.style.left = textfield.offsetLeft + 'px';
        picker.style.top = (textfield.clientHeight + textfield.offsetTop)+ 'px';
    });
}

绑定单击事件


var bindClick = function(obj,id){
  addEvent(obj,'click',function(e){
        var td = getTarget(e),
        nn = td.nodeName.toLowerCase(),//IE会自动转换为大写
        textfield = document.getElementById(id);
        if(nn == 'td'){
            textfield.value = td.bgColor;
            obj.style.display = 'none';
        }
    });

}

修改onload事件


window.onload = function(){
    var textfield = document.getElementById('color');
    var picker = document.createElement('div');
    picker.setAttribute("id","colorpicker");
    picker.innerHTML = colorPickerHtml();
    var body = document.getElementsByTagName("body")[0];
    body.insertBefore(picker,null);
    picker.style.display = 'none';
    bindMouseover(picker);
    bindClick(picker,"color");
    addEvent(textfield ,'focus',function(){
        textfield.style.position = 'relative';
        picker.style.position = 'absolute';
        picker.style.display = 'block';
        picker.style.left = textfield.offsetLeft + 'px';
        picker.style.top = (textfield.clientHeight + textfield.offsetTop)+ 'px';
    });
}
司徒正美的颜色选择器

至此,我们的跨游览器颜色选择器就完成了,你也可以把javascript与CSS分离出来,这就更符合web标准了。当然你也可以利用我提供的addSheet函数把样式与脚本都统统打包到一个文件中,减少网页的请求数。最后我们打包用一个类,当作UI组件来使用!

colorpicker.js

            var Class = {
                create: function() {
                    return function() {
                        this.initialize.apply(this, arguments);
                    }
                }
            }
            var extend = function(destination, source) {
                for (var property in source) {
                    destination[property] = source[property];
                }
                return destination;
            }
            var ColorPicker =  Class.create();//我们的富文本编辑器类
            ColorPicker.prototype = {
                initialize:function(options){
                    this.setOptions(options);
                    this.drawPicker(this.options.textfield_id);
                },
                setOptions:function(options){
                    this.options = { //这里集中设置默认属性
                        id:'colorpicker'+ new Date().getTime(),
                        textfield_id:null//用于textarea的ID,也就是我们的必选项
                    }
                    extend(this.options, options || {});//这里是用来重写默认属性
                },
                ID:function(id){
                    return document.getElementById(id)
                },//getElementById的快捷方式
                CE:function(s){
                    return document.createElement(s)
                },//createElement的快捷方式
                hide:function(el){
                    el.style.display = 'none';
                },
                show:function(el){
                    el.style.display = 'block';
                },
                //用于生成颜色选择器的具体内容
                colorPickerHtml : function(){
                    var  _hex = ['FF', 'CC', '99', '66', '33', '00'];
                    var builder = [];
                    // 呈现一个颜色格
                    var _drawCell = function(builder, red, green, blue){
                        builder.push('<td bgcolor="');
                        builder.push('#' + red + green + blue);
                        builder.push('" unselectable="on"></td>');
                    };
                    // 呈现一行颜色
                    var _drawRow = function(builder, red, blue){
                        builder.push('<tr>');
                        for (var i = 0; i < 6; ++i) {
                            _drawCell(builder, red, _hex[i], blue)
                        }
                        builder.push('</tr>');
                    };
                    // 呈现六个颜色区之一
                    var _drawTable = function(builder, blue){
                        builder.push('<table class="cell" unselectable="on">');
                        for (var i = 0; i < 6; ++i) {
                            _drawRow(builder, _hex[i], blue)
                        }
                        builder.push('</table>');
                    };
                    //开始创建
                    builder.push('<table><tr>');
                    for (var i = 0; i < 3; ++i) {
                        builder.push('<td>');
                        _drawTable(builder, _hex[i]);
                        builder.push('</td>');
                    }
                    builder.push('</tr><tr>');
                    for (var i = 3; i < 6; ++i) {
                        builder.push('<td>');
                        _drawTable(builder, _hex[i])
                        builder.push('</td>');
                    }
                    builder.push('</tr></table>');
                    builder.push('<table id="color_result"><tr><td id="color_view"></td><td id="color_code"></td></tr></table>');
                    return builder.join('');
                },
                addEvent:function(el, type, fn ) {
                    if(!+"/v1") {
                        el['e'+type+fn]=fn;
                        el.attachEvent( 'on'+type, function() {
                            el['e'+type+fn]();
                        } );
                    }else{
                        el.addEventListener( type, fn, false );
                    }
                },
                drawPicker:function(id){
                    var $ = this,
                    textfield = $.ID(id),
                    colorPicker = $.CE("div");
                    colorPicker.className = "colorpicker";
                    colorPicker.innerHTML = $.colorPickerHtml();
                    textfield.parentNode.insertBefore(colorPicker,null);
                    $.hide(colorPicker);
                    $.addEvent(textfield,'focus',function(){
                        textfield.style.position = 'relative';
                        $.show(colorPicker);
                        var l = textfield.offsetLeft + 'px',
                        t = (textfield.clientHeight + textfield.offsetTop)+ 'px';
                        if(/msie|MSIE 6/.test(navigator.userAgent)){
                            var iframe = $.CE("<iframe id='picker_mask' style='left:"+l
                                +";width:220px;filter:mask();position:absolute;"+";top:"+t
                                +"height:180px;z-index:1;'></iframe>");//z-index不能为负数
                            textfield.insertAdjacentElement('afterEnd',iframe);
                        }
                        colorPicker.style.left =l ;
                        colorPicker.style.top = t ;
                    })
                    $.addEvent(colorPicker,'mouseover',function(){
                        var e = arguments[0] || window.event,
                        td = e.srcElement ? e.srcElement : e.target,
                        nn = td.nodeName.toLowerCase(),
                        colorView = $.ID('color_view'),
                        colorCode = $.ID('color_code');
                        if( 'td' == nn){
                            colorView.style.backgroundColor = td.bgColor;
                             !+"/v1"? (colorCode.innerText = td.bgColor):(colorCode.innerHTML = td.bgColor);
                        }
                    });
                    $.addEvent(colorPicker,'click',function(){
                        var e = arguments[0] || window.event,
                        td = e.srcElement ? e.srcElement : e.target,
                        nn = td.nodeName.toLowerCase();
                        if(nn == 'td'){
                            textfield.value = td.bgColor;
                            $.hide(colorPicker);
                            var iframe =  $.ID("picker_mask");
                            iframe && iframe.parentNode.removeChild(iframe);
                        }
                    });

                    addSheet('/
          div.colorpicker {display:none;position:absolute;width:216px;border:2px solid #c3c9cf;background:#f8f8f8;}/
          div.colorpicker table{border-collapse:collapse;margin:0;padding:0;width:100%;}/
          div.colorpicker  table td {padding:0!important;}/
          div.colorpicker .cell td{height:12px;width:12px;}/
          #color_result{width:216px;}/
          #color_view{width:110px;height:25px;}');
                }
            }
            window.onload = function(){
                new ColorPicker({textfield_id:"color"});
            }

最后, 我们得注意一个地方: !+"/v1"? (colorCode.innerText = td.bgColor):(colorCode.innerHTML = td.bgColor);,也就是绑定鼠标在颜色选择器的格子上移动时的事件代码。在IE中,tabel及其td、th的innerHTML是个只读属性,这点非常奇特与恶心,这时我们给它赋值时会报错,我们可以用innerText代替!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值