首页 > 其他分享 >dom-to-image + canvas 实现拾色器(滴管取色)功能

dom-to-image + canvas 实现拾色器(滴管取色)功能

时间:2024-08-18 12:26:52浏览次数:9  
标签:canvas const colorCanvas style 取色 magnifierCtx display 滴管

虽然HTML原生的input可以实现拾色器功能,但是很多时候我们需要自己设置样式和交互方式,就需要自己手动写一个滴管取色的组件,目前比较通用的一个方案就是将dom转换成二进制图片数据,再由canvas读取色值来实现自定义的拾色器滴管功能。

运行截图:

完整demo代码:(感兴趣的可以直接复制完整demo代码本地运行)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>拾色器滴管取色</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            padding: 20px;
            margin: 0;
            position: relative;
        }
        .color-box {
            width: 50px;
            height: 50px;
            display: inline-block;
            margin: 5px;
            border: 1px solid #000;
        }
        #color-display {
            width: 100px;
            height: 50px;
            border: 1px solid #000;
            margin-top: 10px;
        }
        #color-canvas {
            position: absolute;
            display: none;
            cursor: crosshair;
        }
        #magnifier-canvas{
            position: absolute;
            width: 120px;
            height: 120px;
            display: none;
        }

    </style>
</head>
<body>
    <div id="container">
        <h1>Color Picker with Circular Magnifier</h1>

        <!-- 颜色方块 -->
        <div class="color-box" style="background-color: #FF5733;"></div>
        <div class="color-box" style="background-color: #33FF57;"></div>
        <div class="color-box" style="background-color: #3357FF;"></div>
        <div class="color-box" style="background-color: #FF33A6;"></div>
        <div class="color-box" style="background-color: #33FFF6;"></div>
        <div class="color-box" style="background-color: #FFBD33;"></div>

        <button id="capture-button">Capture and Pick Color</button>
        <div id="color-display"></div>
    </div>

    <canvas id="color-canvas"></canvas>
    <canvas id="magnifier-canvas" width="120" height="120"></canvas>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/dom-to-image/2.6.0/dom-to-image.min.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const captureButton = document.getElementById('capture-button');
            const colorDisplay = document.getElementById('color-display');
            const colorCanvas = document.getElementById('color-canvas');
            const magnifierCanvas = document.getElementById('magnifier-canvas');
            const container = document.getElementById('container');
            const body = document.body;
        
            let ctx, magnifierCtx;

            captureButton.addEventListener('click', async function() {
                try {
                    // 异步捕捉当前页面状态
                    const dataUrl = await domtoimage.toPng(body);
                    const img = new Image();
                    img.src = dataUrl;

                    img.onload = function() {
                        // 将 canvas 的大小和位置设置为覆盖整个页面
                        colorCanvas.width = window.innerWidth;
                        colorCanvas.height = window.innerHeight;
                        colorCanvas.style.left = '0';
                        colorCanvas.style.top = '0';
                        // 显示放大器
                        magnifierCanvas.style.display = 'block';

                        // 在 canvas 上绘制页面截图
                        ctx = colorCanvas.getContext('2d');
                        ctx.drawImage(img, 0, 0);

                        // 显示 canvas 并隐藏原始内容
                        colorCanvas.style.display = 'block';
                        // 恢复原始页面内容可见
                        container.style.visibility = 'hidden';

                        magnifierCtx = magnifierCanvas.getContext('2d');

                        // 监听鼠标移动事件
                        colorCanvas.addEventListener('mousemove', handleMouseMove);

                        // 监听鼠标点击事件进行颜色选择
                        colorCanvas.addEventListener('click', handleClick);
                    };
                } catch (error) {
                    console.error('Error capturing the page:', error);
                }
            });

            function handleMouseMove(event) {
                const x = event.clientX;
                const y = event.clientY;

                // 绘制圆形放大镜
                drawCircularMagnifier(x, y);

                // 放大镜在鼠标旁边显示
                magnifierCanvas.style.left = `${event.pageX + 10}px`;
                magnifierCanvas.style.top = `${event.pageY + 10}px`;
            }

            function handleClick(event) {
                const x = event.clientX;
                const y = event.clientY;

                // 获取点击位置的颜色数据
                const pixelData = ctx.getImageData(x, y, 1, 1).data;
                const r = pixelData[0];
                const g = pixelData[1];
                const b = pixelData[2];
                const a = pixelData[3] / 255;

                const rgbaColor = `rgba(${r}, ${g}, ${b}, ${a})`;
                colorDisplay.style.backgroundColor = rgbaColor;
                colorDisplay.textContent = rgbaColor;

                // 取色完成后隐藏 canvas 和放大镜
                colorCanvas.style.display = 'none';
                magnifierCanvas.style.display = 'none';
                magnifierCanvas.style.display = 'none';

                // 恢复原始页面内容可见
                container.style.visibility = 'visible';

                // 解除事件监听器
                colorCanvas.removeEventListener('mousemove', handleMouseMove);
                colorCanvas.removeEventListener('click', handleClick);
            }

            function drawCircularMagnifier(x, y) {
                const magnification = 3;
                const magnifierSize = 100;
                const radius = magnifierSize / 2;

                // 清空画布
                magnifierCtx.clearRect(0, 0, magnifierCanvas.width, magnifierCanvas.height);

                // 绘制圆形放大镜区域
                magnifierCtx.save();
                magnifierCtx.beginPath();
                magnifierCtx.arc(radius + 10, radius + 10, radius, 0, Math.PI * 2);
                magnifierCtx.closePath();
                magnifierCtx.clip();

                // 放大镜显示放大的页面内容
                magnifierCtx.drawImage(colorCanvas, x - magnifierSize / (2 * magnification), y - magnifierSize / (2 * magnification), magnifierSize / magnification, magnifierSize / magnification, 10, 10, magnifierSize, magnifierSize);
                
                magnifierCtx.restore();
                magnifierCtx.strokeStyle = '#000';
                magnifierCtx.lineWidth = 2;
                magnifierCtx.stroke();

                // 显示放大镜
                magnifierCanvas.style.display = 'block';
            }
        });
    </script>
</body>
</html>

这样基本是可以做到定制化的取色器功能了,但是这样还是有一些问题,具体什么问题以及如何解决,可以参考:EyeDropper 实现拾色器(滴管取色)功能-CSDN博客

标签:canvas,const,colorCanvas,style,取色,magnifierCtx,display,滴管
From: https://blog.csdn.net/qq_35322029/article/details/141068800

相关文章

  • html5+CSS3 Canvas动画分享
    1.赛朋博客赛车动画 源码分享:<!DOCTYPEhtml><htmllang="en"><head>  <metacharset="UTF-8">  <title>赛车</title>  <style>    *{      margin:0;      padding:0;      bo......
  • 用html2canvas转当前网页为图片的流程
    1、从canvas中直接提取图片元数据//图片导出为png格式vartype='png';varimgData=canvas.toDataURL(type);上面的代码得到的数据格式为:data:image/png;base64,.....2、将mime-type改为image/octet-stream,强制让浏览器直接download**获取mimeType@param{Str......
  • HTML5新特性之Canvas
    <canvas>是⼀个HTML元素,我们可以将它简单理解为⼀个画板,通过Canvas提供的绘制api我们就可以绘制出各种图形。一、基础1、渲染上下文●getContext('2d')●getContext('webgl')<body><canvasid="canvas"width="800"height="800"style="back......
  • canvas实现手动绘制矩形
    开场白虽然在实际的开发中我们很少去绘制流程图就算需要,我们也会通过第3方插件去实现下面我们来简单实现流程图中很小的一部分手动绘制矩形绘制一个矩形的思路我们这里绘制矩形会使用到canvas.strokeRect(x,y,w,h)方法绘制一个描边矩形x:矩形起点的x轴坐标。y:矩形起......
  • uniapp中如何使用uni.canvasToTempFilePath方法上传Canvas内容为图片,并理解其工作原理
    1.主函数uni.canvasToTempFilePath({ canvasId:'canvasid', fileType:'png', quality:1,//图片质量 success(res){ uni.uploadFile({ url:that.baseUrl+'/file/upload',//后端接口地址 name:'file&......
  • 【Canvas与艺术】黑色三角循环标志
    【关键点】复数与三角函数【成图】【代码】<!DOCTYPEhtml><htmllang="utf-8"><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/><head><title>黑色三角循环标志</title><styletype=&......
  • 【canvas与艺术】交错联通结
    【成图】【代码】<!DOCTYPEhtml><htmllang="utf-8"><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/><head><title>联通结</title><styletype="text/css"&......
  • 鸿蒙OS开发使用Canvas组件绘制天气曲线图
    参考下文:鸿蒙征文|使用Canvas组件绘制天气曲线图_harmonyos_鸑鷟407-HarmonyOS开发者社区效果图:原理使用贝塞尔曲线首先可以了解一下贝塞尔曲线。如果看不懂也没关系,这里会直接讲绘制曲线的步骤。使用CanvasRenderingContext2D对象。首先使用beginPath方法确定起始点......
  • Canvas简历编辑器-图形绘制与状态管理(轻量级DOM)
    Canvas简历编辑器-图形绘制与状态管理(轻量级DOM)在前边我们聊了数据结构的设计和剪贴板的数据操作,那么这些操作都还是比较倾向于数据相关的操作,那么我们现在就来聊聊基本的图形绘制以及图形状态管理。在线编辑:https://windrunnermax.github.io/CanvasEditor开源地址:https......
  • 鸿蒙UI系统组件15——画布(Canvas)
    如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧!扫描下方名片,关注公众号,公众号更新更快,同时也有更多学习资料和技术讨论群。⭐️ 概 述      前一章我们学习了Shape绘制来绘制自定义形状,在实际的业务开发中,有可能我们需要绘制更复杂的图形,例如统计图中的饼图、......