色码转换器再进化

前言

今天来优化 Day24 做的色码挑战器,主要增加的功能如下:

  • 新增转换成RGBA
  • 点选色码可以直接复制

因为要多显示一个色码表示法,将排版做了些微调整,改成下图的样子

剪贴簿功能

这次学习的主要一个重点是复制功能,在浏览器中主要有三个方法可以实作复制功能,之後的实作会先采用第一种方法

1. Document.execCommand

  • 透过document.execCommand('copy') 执行复制
  • 以下是选取一个p元素的方式
const get = (text) => document.querySelector(text);
const p = get('p');

p.addEventListener('click', function() {
  //  产生 range 物件
  const range = document.createRange();
  // 选取p节点作为range物件的内容
  range.selectNode(p);
  // 产生 selection 物件
  const selection = window.getSelection();
  // 清除选取范围
  selection.removeAllRanges();
  // 将选取到内容放入selection物件中
  selection.addRange(range);
  // 执行复制
  document.execCommand('copy');
  // 清除
  selection.removeAllRanges();
})

2. Clipboard API

  • 回传 Promise 物件,为非同步操作
  • 所有操作需要使用navigator.clipboard
  • 需要使用者授权

3. Clipboard Event

  • 尚在实验中的功能
  • 可以监听使用者使用剪贴簿的行为,再改变剪贴簿的资料

认识有哪些方法可以对浏览器中的元素进行复制後,就开始来练习吧~

实作流程

HTML


<!-- 显示颜色的区域 -->
<section class="display">
  <!--总共有三个与下面同样结构的div -->
  <div class="hex">
    <div class="colorpad"></div>
    <p class="colorCode">#808080</p>
  </div>
  <!--略 -->
</section>

<!-- 可以滑动slider的区域 -->
<section class="slider"> 
  <!--总共有四个与下面同样结构的div:代表R/G/B/A的slider-->
  <div class="alpha-group">
    <span>A</span>
    <input type="range" min="0" max="1" step="0.01" value="0.5" class="alpha">
    <span class="range">0.5</span>
  </div>
  <!--略 -->
</section>
  • 这里比较需要注意的是 input 属性 step 在预设状况下是 1,需要改为 0.01

JS实作流程

由於要增加 RGBA 的显示,我将原本的displayValue函式拆解成两个函式:

  • displayDigit : 负责 slider 中 R/G/B/A 个别数值显示
  • displayColorCode: 负责不同色码的显示

这里会拆出来也是在更改的过程中,发现当我在添加 RGBA 的显示时,即便不是拖曳透明度的 slider,数值也会跟着做变化,见识到不必要的耦合现象!!!/images/emoticon/emoticon17.gif

其他的逻辑部分和 Day24 的实作没有太大的区别,所以以下直接看程序码

// 转换数值
function rgbToHex(R,G,B) {
  const hexDigit = [R, G, B].map( item => {
    return Number(item).toString(16).padStart(2, '0')
  }).join('');
  
  return '#'+ hexDigit;
}

// 显示 slider 个别数值
function displayDigits(e) {
  const currentValue = e.target.value;
  const alphaValue = currentValue;
  e.target.nextElementSibling.innerHTML = currentValue;
}


// 显示颜色的不同表示法
function displayColorCode() {
  const hexValue = (rgbToHex(red.value, green.value, blue.value)).toUpperCase();
  
  const hexIndicator = get('.hex').children[1];
  const rgbIndicator = get('.rgb').children[1];
  const rgbaIndicator = get('.rgba').children[1];
  
  hexIndicator.innerHTML = hexValue;
  rgbIndicator.innerHTML = `RGB(${red.value},${green.value},${blue.value})`;
  rgbaIndicator.innerHTML = `RGBA(${red.value},${green.value},${blue.value},${alpha.value})`;
}


//改变圆形图的颜色
function changeColor() {
  const hexColorPad = get('.hex').children[0];
  const rgbColorPad = get('.rgb').children[0];
  const rgbaColorPad = get('.rgba').children[0];
   
  hexColorPad.style.backgroundColor = `rgb(${red.value},${green.value},${blue.value})`;  
  rgbColorPad.style.backgroundColor = `rgb(${red.value},${green.value},${blue.value})`;
  rgbaColorPad.style.backgroundColor = `rgba(${red.value},${green.value},${blue.value}, ${alpha.value})`;
}

//对 slider绑定事件监听器
rangeSliders.forEach(rangeSlider => {
  //监听并改变RGB个别代码
  rangeSlider.addEventListener('mousemove', displayDigits);
  //监听并改变所有色码表示法
  rangeSlider.addEventListener('mousemove', displayColorCode);
  //监听并改变背景颜色
  rangeSlider.addEventListener('mousemove', changeColor);
})


新增功能的部分

  • 复制使用者点选的色码:copy函式
  • 按钮改变颜色和字样提醒使用者已复制色码:changeDisplay函式
  • 将这两个函式当作触发按钮点击事件的 callback function
//做复制的功能
const buttons = getAll('.colorCode');

function copy() {
  const range = document.createRange();
  range.selectNode(this);
  const selection = window.getSelection();
  selection.removeAllRanges();
  selection.addRange(range); 
  document.execCommand('copy');
  selection.removeAllRanges();
}

// 改变颜色和文字内容
function changeDisplay(e){
  e.target.style.backgroundColor = `rgb(247,157,128)`;
  e.target.innerHTML = `复制好色码罗~`;
  
  reset(e);
}

// 两秒後会回复到先前的状态
function reset(e){
  setTimeout(()=> {
    e.target.style.backgroundColor = `rgb(78,199,207)`;
    displayColorCode();
  }, 2000)
}

//对按钮绑定事件监听
buttons.forEach(button => {
  button.addEventListener('click', copy);
  button.addEventListener('click', changeDisplay);
});

完成~~~codepen连结/images/emoticon/emoticon42.gif

结语

一开始只是为了回应馒头大大的一句话,想不到因而学习到浏览器的复制功该如何实作,也在增加功能的过程中再次体会到拆函式的重要性,不好好将函式拆好的下场就是改了 A 动了B,不断有出其不意的惊喜(令人崩溃的那种XD

透过观察线上的色码转换器所包含的功能,想想这些功能是怎麽实作出来的,再逐步找相应语法尝试的过程真的很有趣~

谢谢神队友的修改建议和提问~~

参考资料:

RGBA and Hex Color Converter
剪贴簿复制操作
那些被忽略但很好用的 Web API / Clipboard


<<:  建立你想要的文化(4)- 推动

>>:  Final Day

Day26-用jQuery写得出ToDoList吗_1_新增list没什麽问题

这应该是这次参赛的最後作品了 来挑战用jQuery做一个ToDoList 首先先写简单的架构 一个i...

【第30天】最终回

玉山竞赛心得 从朋友口中得知玉山银行和趋势科技举办了中文手写字辨识的比赛,於是我们召集资策会夥伴们组...

Day21:【TypeScript 学起来】Generics 泛型

是说在社群到处都在爆雷的《鱿鱼游戏》,我进度第一集,好想弃赛来追剧(我就废 然後谢谢没看鱿鱼游戏,...

鬼故事 - 不是,你偷这些干嘛

鬼故事 - 不是,你偷这些干嘛 Credit: System32Comics 灵感来源:UCCU H...

[17] 建立统一放资料的地方

建立一个放资料的地方,统一读取和写入这样比较方便 dataCenter.js const GetIn...