zl程序教程

您现在的位置是:首页 >  Javascript

当前栏目

js 简单图片取色器

2023-02-26 10:21:42 时间

图片颜色识别的关键函数为:CanvasRenderingContext2D.getImageData(sx, sy, sw, sh), 详情参考:MDN getImageData

本文实现的效果图如下:
js 简单图片取色器
实现的功能点有:

(福利推荐:阿里云、腾讯云、华为云服务器最新限时优惠活动,云服务器1核2G仅88元/年、2核4G仅698元/3年,点击这里立即抢购>>>

1). 加载本地图片 2). 鼠标悬浮显示出相应的颜色 3). 按键盘快捷键复制代码 4). 额外小功能,图片支持拖曳加载 

接下来详细介绍每一步的实现:

  1. 加载本地图片

    // 绘制图片到 canvas function drawImage() {   if (canvasWidth != -1) {     ctx.clearRect(0, 0, canvasWidth, canvasHeight); // 清除 canvas 内容   }   // 获取图片宽高   imageWidth = image.width;   imageHeight = image.height;   // 计算 canvas 宽高(需要预留提示框的位置)   canvasWidth = imageWidth + toolTipWidth;   if (imageWidth > canvasWidth) {     canvasWidth = imageWidth;   }   canvasHeight = imageWidth + toolTipHeight;   if (imageHeight > canvasHeight) {     canvasHeight = imageHeight;   }   canvas.width = canvasWidth;   canvas.height = canvasHeight;   // 获取元素数据   rect = canvas.getBoundingClientRect();   ctx.drawImage(image, 0, 0); //  绘制图片   // 通过 getImageData 获取图片的所有像素颜色数组(从左往右,从上往下)   imageData = ctx.getImageData(0, 0, image.width, image.height).data;  // for (let i = 0, len = imageData.length; i < len; i = i + 4) {  //   let item = {   //     x: ((i / 4) % imageWidth) + 1,   //     y: Math.floor(i / 4 / imageWidth) + 1,   //   };   // } }  // 加载图像 function loadImage(url) {   image.src = url;   image.onload = function () {     drawImage(image);   }; }  // 上传文件 function uploadImage(img) {   // 判断是否有选中文件   if (!img) return;   // 检测是否是图片类型   if (img.type.indexOf('image') !== 0) {     alert('只能选择图片');     return;   }   // 定义文件读取对象,用于读取文件   var reader = new FileReader();   reader.readAsDataURL(img); // 读取图片内容为 url 格式   reader.onload = function () {     loadImage(reader.result); // 加载图片   }; }  // 定义选择图片 imgSelector.addEventListener('change', function (e) {   uploadImage(e.target.files[0]); // 选中的图片文件 });

    看似是一步,实际这一步里面包含了很多步:监听 input-file change 事件 –> 通过 FileReader 读取本地文件 –> 将读取到的本地文件(reader.result)放置到 Image –> 将 image 绘制到 canvas –> 读取 getImageData 图片颜色。

  2. 鼠标悬浮显示颜色信息

    // 将图片的 r, g, b 分别转换为 16进制的颜色 function colorItemHex(itemNumber) {   let hex = itemNumber.toString(16);   return (hex.length === 1 ? '0' + hex : hex).toUpperCase(); }  // 添加鼠标滑动事件 canvas.addEventListener('mousemove', function (evt) {   clearTimeout(t);   t = setTimeout(() => {     if (imageData != null) {       /*               getBoundingClient()中的[left, top] 获取元素距离视图左边和上边的距离               clientX 和 clientY 获取鼠标距离试图左边和上边的距离             */       let x = evt.clientX - rect.left;       let y = evt.clientY - rect.top;       ctx.clearRect(0, 0, canvasWidth, canvasHeight); // 清除 canvas 内容       // 重新绘制       ctx.drawImage(image, 0, 0);       // 根据坐标计算像素点位置,详情参考:desc.jpg       var i = ((y - 1) * imageWidth + x - 1) * 4;       if (x >= imageWidth || y >= imageHeight) {         return;       }       var tsPointX = x,         tsPointY = y; // 提示框的位置       if (x + toolTipWidth > canvasWidth) {         // 右边无法绘制出提示框, 左边绘制         tsPointX = x - toolTipWidth;       }       if (y + toolTipHeight > canvasHeight) {         // 下边无法绘制出提示框,上边绘制         tsPointY = y - toolTipHeight;       }       // 重新绘制新的提示框       ctx.fillStyle = 'rgba(255, 255, 255, 0.8)'; // 矩形填充颜色       ctx.fillRect(tsPointX, tsPointY, toolTipWidth, toolTipHeight); // 绘制矩形       ctx.strokeStyle = 'blue'; // 边框颜色       ctx.strokeRect(tsPointX, tsPointY, toolTipWidth, toolTipHeight); // 绘制矩形边框        // rgb 模式为颜色值的十进制数模式       let red = imageData[i];       let green = imageData[i + 1];       let blue = imageData[i + 2];       let alpha = imageData[i + 3];       let hex =         '#' +         colorItemHex(red) +         colorItemHex(green) +         colorItemHex(blue);       currHTML = hex;       // 设置文本样式       ctx.font = '16px sans-serif';       ctx.fillStyle = 'black';       if (alpha === 255) {         currRGB = `(${red}, ${green}, ${blue})`;         // 255 为完全不透明, 0 - 完全透明         ctx.fillText(           `RGB: ${currRGB}`,           tsPointX + 7,           tsPointY + 20 // 40 = 20 + 16(字体大小) + 5         );       } else {         // 颜色值的 alpha 是 0~255,而 css rgba() 函数的 alpha 为 0~1         let cssAlpha = Number((alpha / 255).toFixed(2));         currRGB = `(${red}, ${green}, ${blue}, ${cssAlpha})`;         ctx.fillText(           `RGBA: ${currRGB}`,           tsPointX + 7,           tsPointY + 20 // 40 = 20 + 16 * 2(字体大小) + 5         );       }       // hex 为颜色值的16进制模式       // 关于进制之间的手动转换可以参考:https://www.cnblogs.com/ysocean/p/7513061.html?userCode=wrvvs1rm       ctx.fillText('HTML: ' + hex, tsPointX + 7, tsPointY + 40);       ctx.fillText('按 C 复制 HTML 代码', tsPointX + 7, tsPointY + 60);       ctx.fillText('按 V 复制 RGB 代码', tsPointX + 7, tsPointY + 80);     }   }, 150); });  // 添加鼠标移出事件 canvas.addEventListener('mouseout', function () {   clearTimeout(t);   ctx.clearRect(0, 0, canvasWidth, canvasHeight); // 清除 canvas 内容   // 重新绘制   ctx.drawImage(image, 0, 0);   currHTML = currRGB = null; });

    这一步也是有很多步的:添加鼠标滑动事件 –> 根据鼠标坐标点获取在 ImageData 数组中的位置 –> 获取到图片 RGBA –> 通过 canvas 绘制提示框

    注意要点:

    1. 要在鼠标移出的时候,清除之前的提示框
    2. 如何根据坐标计算在图片颜色集中的位置,详细解释,会在下面放图说明
    3. 获取到的 RGBA 是十进制式的数据,如果需要 HTML 代码,则还需要转换为十六进制,进制间的相互转换
    4. 加入 setTimeout 避免滑动过快频繁触发

    js 简单图片取色器

  3. 按键盘快捷键复制代码

    // 复制内容到剪贴板 function copy(copyValue) {   var $tmpCopyNode = document.createElement('input');   $tmpCopyNode.type = 'text';   $tmpCopyNode.className = 'copy-node';   $tmpCopyNode.value = copyValue;   document.body.append($tmpCopyNode);   $tmpCopyNode.select();   document.execCommand('copy');   document.body.removeChild($tmpCopyNode); }  // 监听键盘事件 document.addEventListener('keydown', function (e) {   if (e.keyCode === 67) {     // 按下了 C 键,复制 HTML 代码     if (currHTML != null) {       copy(currHTML);     }   } else if (e.keyCode === 86) {     // 按下了 V 键,复制 RGB 代码     if (currRGB != null) {       copy(currRGB);     }   } });

    这里的难点就在于 复制 功能的实现,这里的复制是通过 input 实现的,所以需要让 input 透明并且不能显示在屏幕上,这个就需要 CSS 的配合:

    /* 一个用于复制内容的输入框的样式 */ .copy-node {   /* 将位置放到屏幕外 */   position: fixed;   top: -100px;   left: -100px;   /* 将背景和颜色设置为透明, 避免显现 */   border: none;   outline: none;   background-color: transparent;   color: transparent; }
  4. 拖曳加载图片

    /* 要实现拖曳上传的功能,以下2个事件必须监听 */ // 监听当被拖动元素在目的地元素内时触发, 取消浏览器的默认行为,要不然浏览器会默认打开新的标签页预览图片 $imgSelectorBtn.addEventListener('dragover', function (e) {   e.stopPropagation();   e.preventDefault(); }); // 当被拖动元素在目的地元素里放下时触发, 一般需要取消浏览器的默认行为 $imgSelectorBtn.addEventListener('drop', function (e) {   e.stopPropagation();   e.preventDefault();   uploadImage(e.dataTransfer.files[0]); // 上传文件 });

下面补上两段代码:

  1. 按钮的 CSS 代码
/* 定义文件选择按钮 */ .img-selector {   display: none; } .file {   position: absolute;   width: 100%;   font-size: 90px; } .img-selector-btn {   color: #ffffff;   background: #06980e;   text-align: center;   cursor: pointer;   border: 1px solid #cccccc;   padding: 7px 10px;   display: inline-block;   box-sizing: border-box; } .img-selector-btn:hover {   background: #04bc0d; }
  1. 所有的 HTML 标签
<canvas id="canvas"></canvas> <div>   <input     type="file"     class="img-selector"     id="imgSelector"     accept="image/*"   />   <label     id="imgSelectorBtn"     class="img-selector-btn"     for="imgSelector"     title="JPG,GIF,PNG"   >     选择图片   </label> </div>
  1. 所有声明的变量及说明:
var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); var posColors = []; // 保存所有位置的像素信息 var rect = null; // canvas 元素矩阵数据 var t = -1; // 定时器,避免频繁触发鼠标悬浮事件 var imageData = null; // 图片像素点颜色数组 var imageWidth = -1,   imageHeight; // 图片宽度,高度 var canvasWidth = -1,   canvasHeight = -1; // canvas 宽度和高度 var toolTipWidth = 175,   toolTipHeight = 90; // tooltip 提示框的宽度和高度 var currRGB = null,   currHTML = null; var $copyNode = document.getElementById('copyNode'); // 用于复制操作的编辑框 var $imgSelectorBtn = document.getElementById('imgSelectorBtn'); // 图片选择按钮 var image = new Image(); // 构造图片

关于 canvas 的内容可参考菜鸟教程相关专题:HTML5 Canvas、学习 HTML5 Canvas 这一篇文章就够了

js 简单图片取色器


本站部分内容转载自网络,版权属于原作者所有,如有异议请联系QQ153890879修改或删除,谢谢!
转载请注明原文链接:js 简单图片取色器

你还在原价购买阿里云、腾讯云、华为云、天翼云产品?那就亏大啦!现在申请成为四大品牌云厂商VIP用户,可以3折优惠价购买云服务器等云产品,并且可享四大云服务商产品终身VIP优惠价,还等什么?赶紧点击下面对应链接免费申请VIP客户吧:

1、点击这里立即申请成为腾讯云VIP客户

2、点击这里立即注册成为天翼云VIP客户

3、点击这里立即申请成为华为云VIP客户

4、点击这里立享阿里云产品终身VIP优惠价

喜欢 (0)
[[email protected]]
分享 (0)