欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用css3和javascript开发web拾色器实例代码

程序员文章站 2022-04-05 12:17:26
本实例中的web拾色器功能使用css3实现页面效果,即在页面上显示的元素用css3样式来实现的。再使用js生成拾色器颜色数据,并控制各元素的鼠标事件。当事件作为反应时,获取到对应的数据并显示颜色值。拾...

本实例中的web拾色器功能使用css3实现页面效果,即在页面上显示的元素用css3样式来实现的。再使用js生成拾色器颜色数据,并控制各元素的鼠标事件。当事件作为反应时,获取到对应的数据并显示颜色值。

拾色器的html元素分为三个部分,分别是拾色区域、色系区域和颜色显示区域,如图所示:

使用css3和javascript开发web拾色器实例代码

web拾色器三个部分的html元素如下:

<div class="color_container">
  <div class="main_wrap"> <!--拾色区域-->
    <div class="main_drag" id="maindrag"></div>
    <div class="main_con" id="maincon">
      <div class="left_white_bg bg"></div>
      <div class="bottom_black_bg bg"></div>
    </div>
  </div>
  <div class="side_wrap"> <!--色系区域-->
    <div class="side_drag" id="sidedrag"></div>
    <div class="side_con" id="sidecon"></div>
  </div>
  <div class="show_color" id="findcolor"><!--显示区域-->
    <div class="color_full" id="colorfull"></div>
    <div class="color_text" id="colortext">
      r:<input type="text" readonly>
      g:<input type="text" readonly>
      b:<input type="text" readonly>
    </div>
  </div>
</div>

加上一些css样式实现图片上的布局效果:

.color_container {width:610px;background:#333;padding:10px;font-size:0;margin:30px auto;}
.color_container>div{display:inline-block;background:#fff;vertical-align:top;box-shadow:0px 0px 5px 0px #999;}
.color_container .main_con{width:550px;height:430px;}
.color_container .main_con .bg{position:absolute;top:0;right:0;bottom:0;left:0;}

.color_container .side_con{width:50px;height:430px;}
.color_container .main_wrap,.color_container .side_wrap{position:relative;}
.color_container .side_wrap{margin-left:10px;}
.color_container .main_drag,.color_container .side_drag{position:absolute;border:1px solid #fff;background:rgba(0,0,0,.3);cursor:pointer;}
.color_container .main_drag{width:12px;height:12px;border-radius:50%;z-index:3;left:-7px;top:-7px;}
.color_container .side_drag{height:6px;width:54px;border-radius:2px;left:-3px;top:-4px;}
.color_container .find_color{width:60px;height:60px;position:absolute;top:0;left:-70px;background:#fff;}
.color_container .show_color{display:block;margin:10px 0 0;height:auto;padding:10px;}
.color_container .color_full{display:inline-block;width:58px;height:58px;border:1px solid #ccc;}
.color_container .color_text{display:inline-block;margin-left:30px;height:60px;line-height:60px;text-align:center;font-size:14px;vertical-align:top;}
.color_container .color_text input{width:24px;margin:0 15px 0 5px;}

接下来使用css3的 linear-gradient 线性渐变来修改色系区域元素的背景颜色。色系规则是 红>黄>绿>青>蓝>紫>红,共经过了6次变化,每次变化比例是16%-17%之间,所以可以从上至下添加这七个渐变颜色,增加的css代码如下:

.color_container .side_con{background:linear-gradient(to bottom,red 0%,#ff0 17%,lime 33%,cyan 50%,blue 66%,#f0f 83%,red 100%)}

此时效果如图所示:

使用css3和javascript开发web拾色器实例代码

拾色区域一般默认颜色是红色系,所以先给拾色区域添加红色背景,代码如下:

.color_container .main_con{background:red;}

此时效果如图所示:

使用css3和javascript开发web拾色器实例代码

一般拾色器的拾色区域显示规则是,从上至下由明到暗;从左至右由浅到深。这种效果可以添加两个 linear-gradient 透明渐变实现,代码如下:

.color_container .main_con .left_white_bg{background:linear-gradient(to right,#fff 0%,transparent 100%)}
.color_container .main_con .bottom_black_bg{background:linear-gradient(to bottom,transparent 0%,#000 100%);}

此时已经实现最终静态效果如图所示:

使用css3和javascript开发web拾色器实例代码

此时web拾色器页面效果是有了,但还缺少交互,不能改变拾色区域背景及选择颜色,接下来通过js来实现交互效果。

因为鼠标在拖动吸管选择颜色是每个像素移动的,所以需要根据色系区域高度来计算颜色值并存储备用,代码如下所示:

//色系存储数据
var acolorseries = {
  r:[255],g:[0],b:[0]
}
//色系数据变化
var acolorvary = ['g','r','b','g','r','b'];
//色系元素
var eseries = document.getelementbyid('sidecon');
//每个色系颜色变化次数
var nserieslen = math.floor(eseries.offsetheight / 6);
//每次变化步长值
var nstep = math.floor(255 / nserieslen);
//步长值剩余值
var nstepremainder = 255 / nserieslen - nstep;
//循环存储色系rgb颜色值
for(let i=0;i<acolorvary.length;i++){
  let add = (i % 2);  //因为高度不能整除,需要使最终色系填满元素
  let nfull = 0; //计算剩余的步长值
  for(let j=0;j<nserieslen+add;j++){
    nfull += nstepremainder;
    let naddstep = nstep;
    if(nfull>1){  //剩余步长值超过1时,每次增加步长值加1
      naddstep = nstep + 1;
      nfull = nfull - 1;
    }
    //遍历色系数据对象添加颜色值
    for(let k in acolorseries){
      let nval = 0;
      let noldval = acolorseries[k][acolorseries[k].length-1];
      if(k==acolorvary[i]){
        if(add==0){ //判断颜色值改变方向是变大还是变小
          nval = noldval + naddstep;
        }else{
          nval = noldval - naddstep;
        }
        if(nval > 255){  //限制最大值255
          nval = 255;
        }else if(nval < 0){  //限制最小值为0
          nval = 0;
        }
      }else{
        nval = noldval;
      }
      acolorseries[k].push(nval);
    }
  }
}

在色系区域吸管上加上拖拽功能,代码如下所示:


复制代码代码如下://获取拾色区域var emaincon = document.getelementbyid('maincon');//获取色系吸管var esidedrag = document.getelementbyid('sidedrag');//获取吸管高度var nsidedragh = esidedrag.offsetheight;//获取吸管限制高度var nsideh = eseries.offsetheight - nsidedragh / 2; //在色系吸管上绑定鼠标按下事件esidedrag.addeventlistener('mousedown',function(event){ //初始化鼠标开始拖拽的点击位置 var ninity = event.clienty; //初始化色系吸管位置 var ninittop = this.offsettop; //色系吸管位置 var ny = null; //色系选择颜色 var color = null; document.onmousemove = event=>{ //鼠标移动时取消默认行为,避免选中其他元素或文字 event.preventdefault(); //根据鼠标设置色系吸管位置 ny = event.clienty - ninity + ninittop; //下面的条件限制色系吸管不能超出范围 if(ny >= nsideh-1){ ny = nsideh-1; } if(ny <= -nsidedragh/2){ ny = -nsidedragh/2; } //因为用的是箭头函数,所以this还是指向滑块,修改滑块位置 this.style.top = ny + 'px'; //修改拾色区背景颜色 let n = ny + nsidedragh / 2; color = {r:acolorseries.r[n],g:acolorseries.g[n],b:acolorseries.b[n]}; emaincon.style.background = `rgb(${color.r},${color.g},${color.b})`; } //鼠标释放事件 document.onmouseup = event=>{ document.onmouseup = null; document.onmousemove = null; }});

此时色系区域的吸管拖动时,拾色区域的背景颜色就会跟着变化,效果如图所示:

使用css3和javascript开发web拾色器实例代码

在色系区域再加上点击事件,点击时可以把吸管滑动到点击的位置,并修改拾色区域颜色,代码如下所示:

//色系元素绑定点击事件
eseries.addeventlistener('click',function(event){
  //获取点击位置
  let ny = event.offsety - nsidedragh/2;
  //增加过渡样式,使吸管有滑动效果
  esidedrag.style.transition = '.1s';
  //删除过渡样式
  settimeout(e=>{
    esidedrag.style.transition = 'inherit';
  },100)
  //改变色系吸管位置 
  esidedrag.style.top = ny + 'px';
  
  //修改拾色区背景颜色
  let n = ny + nsidedragh / 2;
  color = {r:acolorseries.r[n],g:acolorseries.g[n],b:acolorseries.b[n]};
  emaincon.style.background = `rgb(${color.r},${color.g},${color.b})`;
});

同样的,拾色区域也需要把颜色存储起来。因为每次选择色系时,拾色区域颜色都会修改,所以用一个函数实现此功能,代码如下所示:

//拾色区域颜色
var acolormainstore = [];
//获取拾色区域的宽度和高度
var nmainw = emaincon.offsetwidth;
var nmainh = emaincon.offsetheight;

function fncolorset(color){
  //重置拾色区域颜色数据
  acolormainstore  = [];

  //左侧可变颜色,默认为白色
  var oleftcolor = {r:255,g:255,b:255};
  //右侧可变颜色,因为color参数是字符串,所以要转换为数组
  var orightcolor = json.parse(json.stringify(color));
  //底部颜色固定黑色
  var obottomcolor = {r:0,g:0,b:0};
  //因为色块可变颜色从左上角开始,所以默认设置为白色
  var omaincolor = {r:255,g:255,b:255};
  //y轴步长值
  var oystep = {
    lstep: math.floor(256 / nmainh),  //左侧从上至下是从白色渐变到黑色,所以固定步长值计算
    lremainder: 256 / nmainh - math.floor(256 / nmainh),  //左侧步长剩余值
    ladd:0, //渐变过程添加值
  }
  //枚举添加右侧从下至下渐变步长值、剩余值及添加值
  for(let k in orightcolor){
    oystep[k+'step'] = math.floor((orightcolor[k]-obottomcolor[k]+1) / nmainh);
    oystep[k+'remainder'] = (orightcolor[k]-obottomcolor[k]+1) / nmainh - math.floor((orightcolor[k]-obottomcolor[k]+1) / nmainh);
    oystep[k+'add'] = 0;
  }

  //循环每一行色块
  for(let i=0;i<nmainh;i++){
    //因为每一列的颜色都是往下加深渐变,所以除第一行之外每行循环都需要修改左侧和右侧颜色
    if(i>0){
      oystep.ladd += oystep.lremainder;
      for(let k in oleftcolor){
        //修改左侧颜色
        if(oystep.ladd>1){
          oleftcolor[k] = oleftcolor[k] - (oystep.lstep + 1);
        }else{
          oleftcolor[k] = oleftcolor[k] - oystep.lstep;
        }
        //修改右侧颜色
        oystep[k+'add'] += oystep[k+'remainder'];
        if(oystep[k+'add']>1){
          orightcolor[k] = orightcolor[k] - (oystep[k+'step'] + 1);
          //修改添加值
          oystep[k+'add'] = oystep[k+'add'] - 1;
        }else{
          orightcolor[k] = orightcolor[k] - oystep[k+'step'];
        }
      }
      //修改添加值
      if(oystep.ladd>1){
        oystep.ladd = oystep.ladd - 1;
      }
    }
    
    //每一行的色块颜色单独存到一个新的数组中
    acolormainstore.push([]);
    //每一次循环色块都要重置为左侧颜色
    omaincolor = json.parse(json.stringify(oleftcolor));

    //x轴步长值
    let oxstep = {}
    for(let k in oleftcolor){
      oxstep[k+'step'] = math.floor((oleftcolor[k]-orightcolor[k]) / nmainw);
      oxstep[k+'remainder'] = (oleftcolor[k]-orightcolor[k]) / nmainw - math.floor((oleftcolor[k]-orightcolor[k]) / nmainw);
      oxstep[k+'add'] = 0;
    }
    
    //在每一行中循环每一列色块
    for(let j=0;j<nmainw;j++){
      if(j!=0&&j!=nmainw-1){ //第一个色块颜色和最后一个颜色不需要修改
        //从左至右渐变颜色
        for(let k in omaincolor){
          //逐步修改颜色
          oxstep[k+'add'] += oxstep[k+'remainder'];
          if(oxstep[k+'add']>1){
            omaincolor[k] = omaincolor[k] - (oxstep[k+'step'] + 1);
            oxstep[k+'add'] = oxstep[k+'add'] - 1;
          }else{
            omaincolor[k] = omaincolor[k] - oxstep[k+'step'];
          }
        }
      }
      if(j==nmainw-1){
        //最后的颜色设置为右侧颜色值
        omaincolor = json.parse(json.stringify(orightcolor));
      }
      
      //存储色块颜色
      acolormainstore[i].push(json.stringify(omaincolor));
    }
  }
}

//默认颜色为红色背景
fncolorset({r:255,g:0,b:0});

再给拾色区域的吸管加上拖拽功能,拾色区域加上点击事件,并修改显示区域的颜色及 rgb 的值,代码如下所示:

//获取显示颜色块
var ecolorfull = document.getelementbyid('colorfull');
var ecolortext = document.getelementbyid('colortext');
var acolorinput = ecolortext.getelementsbytagname('input');
function fncolorfull(color){
  //颜色参数是字符串,需要转换为数组
  var color = json.parse(color);
  // 修改显示颜色
  ecolorfull.style.background = 'rgb('+color.join(',')+')';
  //修改rgb颜色值
  for(let i=0;i<acolorinput.length;i++){
    acolorinput[i].value = color[i];
  }
}
//默认显示白色
fncolorfull('[255,255,255]');

//获取吸管元素
var emaindrag = document.getelementbyid('maindrag');
//amaincolorstore数组中颜色行下标
var nsx = 0;
//amaincolorstore数组中颜色列下标
var nsy = 0;
//获取吸管高度
var nmaindragh = emaindrag.offsetheight;
//获取吸管限制宽度
var nmainlimitw = nmainw - nmaindragh / 2;
//获取吸管限制高度
var nmainlimith = nmainh - nmaindragh / 2;
emaindrag.addeventlistener('mousedown',function(event){
  //初始化鼠标开始拖拽的点击位置
  var ninitx = event.clientx;
  var ninity = event.clienty;
  //初始化吸管位置
  var ninittop = this.offsettop;
  var ninitleft = this.offsetleft;
  //选中吸管后,在document上绑定鼠标移动事件
  document.onmousemove = event=>{
    //鼠标移动时取消默认行为,避免选中其他元素或文字
    event.preventdefault();
    //获取鼠标位置
    let nx = event.clientx - ninitx + ninitleft;
    let ny = event.clienty - ninity + ninittop;
    //以下的条件用于限制吸管不能移出拾色区域
    if(ny >= nmainlimith-1){
      ny = nmainlimith-1;
    }
    if(ny <= -nmaindragh/2){
      ny = -nmaindragh/2;
    }
    if(nx <= -nmaindragh/2){
      nx = -nmaindragh/2;
    }
    if(nx>=nmainlimitw-1){
      nx = nmainlimitw-1;
    }
    //因为用的是箭头函数,所以this还是指向吸管,修改吸管位置
    this.style.top = ny + 'px';
    this.style.left = nx + 'px';
    //颜色赋值,因为没办法选到最后一个颜色,所以加这个公式,这样中间有些颜色选不到
    nsx = nx + nmaindragh/2;
    nsy = ny + nmaindragh/2;
    //获取当前位置颜色
    let ocolor = json.parse(acolormainstore[nsy][nsx]);
    //填充显示颜色区域
    fncolorfull(json.stringify([ocolor.r,ocolor.g,ocolor.b]));
  }
  //松开鼠标后释放document上的事件
  document.onmouseup = event=>{
    document.onmouseup = null;
    document.onmousemove = null;
  } 
});
//拾色区域绑定点击事件
emaincon.addeventlistener('click',function(event){
  //获取点击位置
  let nx = event.offsetx - nmaindragh/2
  let ny = event.offsety - nmaindragh/2;
  //增加过渡样式,使吸管有滑动效果
  emaindrag.style.transition = '.1s';
  //删除过渡样式
  settimeout(e=>{
    emaindrag.style.transition = 'inherit';
  },100)
  //改变拾色吸管位置 
  emaindrag.style.top = ny + 'px';
  emaindrag.style.left = nx + 'px';
  //颜色赋值,因为没办法选到最后一个颜色,所以加这个公式,这样中间有些颜色选不到
  nsx = nx + nmaindragh/2;
  nsy = ny + nmaindragh/2;
  //获取当前位置颜色
  let ocolor = json.parse(acolormainstore[nsy][nsx]);
  //填充显示颜色区域
  fncolorfull(json.stringify([ocolor.r,ocolor.g,ocolor.b]));    
});

此时已经可以拖动拾色区域吸管并选择颜色。但此时还没有完全开发完成,因为之前在修改色系的事件中,只是修改了拾色区域的背景,并没有存储拾色区域的颜色,所以需要在色系元素的事件中添加如下代码:

//在色系吸管上绑定鼠标按下事件
esidedrag.addeventlistener('mousedown',function(event){
  /*...*/
  
  //鼠标释放事件
  document.onmouseup = event=>{
    document.onmouseup = null;
    document.onmousemove = null;
    //设置拾色区颜色
    color&&fncolorset(color);
    //获取当前位置颜色
    let ocolor = json.parse(acolormainstore[nsy][nsx]);
    //填充显示颜色区域
    fncolorfull(json.stringify([ocolor.r,ocolor.g,ocolor.b]));
  }
});
//色系元素绑定点击事件
eseries.addeventlistener('click',function(event){
  //*...*/

  //删除过渡样式
  settimeout(e=>{
    esidedrag.style.transition = 'inherit';
    //设置拾色区颜色
    color&&fncolorset(color);
    //获取当前位置颜色
    let ocolor = json.parse(acolormainstore[nsy][nsx]);
    //填充显示颜色区域
    fncolorfull(json.stringify([ocolor.r,ocolor.g,ocolor.b]));
  },100)
  
  /*...*/
});

一个流畅的web拾色器就完成了,我在代码中都尽可能加上了详细的注释,可以帮助更清晰的理解功能实现逻辑。

到此这篇关于使用css3和javascript开发web拾色器实例的文章就介绍到这了,更多相关css开发web拾色器内容请搜索以前的文章或继续浏览下面的相关文章,希望大家以后多多支持!

相关标签: css Web 拾色器