JavaScript吸管(鼠标光标下方像素的告诉颜色)


74

我正在寻找“吸管”工具,该工具为CMS提供JavaScript鼠标光标所位于的像素的十六进制值。

对于Firefox,有出色的ColorZilla扩展可以做到这一点。但是,它当然只是FF,我真的很想随同CMS一起提供该工具。

荷兰开发人员有一个非常聪明的主意,就是结合使用Ajax和PHPimagecolorat()来找出图像上的Pixel颜色。但这限制了我可以访问服务器端的图像的范围,而我真的梦想着有一个通用工具。

我将使用其中一种方法,但更希望使用跨浏览器,基于Javascript或Flash的方式,这种方式不需要服务器端摆弄,也不需要安装扩展程序。

我对ColorZilla可以做的任何IE特定解决方案也很感兴趣-我可以只支持IE和FF,尽管跨浏览器解决方案当然是理想的。


用Javascript是不可能的。我不确定Flash。
SLaks

从理论上讲,你也许可以为处理与鼠标光标下的最顶端的元素相关联的样式信息,并确定元素的颜色是什么应该是,如果它不是一个图像或帆布。实际上,这可能会使您发疯,处理边界,边距和浏览器怪癖。我认为以利亚的答案是唯一可行的答案。
Aaronaught

Answers:


80

JavaScript无法实现,因为它违反了跨域安全性。如果您知道图像由哪些像素组成,那将是非常糟糕的http://some-other-host/yourPassword.png。如果鼠标位于画布上或同一域的图像元素(或带有Access-Control-Allow-Origin: *标头的另一个域的图像元素)上,则只能告诉鼠标下方像素的颜色。对于画布,您可以这样做canvasElement.getContext('2d').getImageData(x, y, 1, 1).data。对于图像,您必须使用以下命令将它们绘制到画布上:

var canvas = document.createElement("canvas");
canvas.width = yourImageElement.width;
canvas.height = yourImageElement.height;
canvas.getContext('2d').drawImage(yourImageElement, 0, 0);

然后,只需使用为画布说明的先前方法即可。如果您必须能够转换为各种颜色值表示形式,请尝试我的color.js库。

另外,您永远也无法支持IE <9(假设IE9支持画布),并且使用Flash也无济于事,因为它也无法读取文档的像素数据。


5
关于安全性的有趣方面,并感谢Canvas的角度。但是,我只能忍受访问我域内的像素。
Pekka

谢谢以利亚。我有点难过,它仅限于Firefox,但这不是您的错,这绝对是最简单的解决方案。我可能会结合使用(较慢的)服务器端后备选项来满足IE的需求。接受您的答案。
Pekka 2010年

1
是什么使我无法嵌入yourPassword.png画布,然后在那里进行采样?(假设我知道网址)
拥抱

1
@ zzzzBov,@ hughes,您没有抓住要点:如果可以捕获屏幕上的任何像素,则可以在不同的浏览器窗口甚至PDF银行对帐单的不同窗口中查看值。没有人应该在处理敏感信息的页面上运行不受信任的JS,并且提供敏感文件应涉及适当的身份验证。您需要劫持用户的会话才能访问他们的password.png
丹·罗斯

2
@ danross,js没有跨沙箱访问权限来执行脚本(除非获得明确许可),因此没有理由将api限制为来自同一安全沙箱中框架的颜色值。
zzzzBov 2014年

18

使用称为“浏览器计时攻击”的技术,即使在iframe上,也可以(某种程度上)确定任何像素的颜色。

基本上,此技术测量的是在元素上渲染SVG滤镜的时间,而不是颜色本身(requestAnimationFrame()允许测量时间的准确性比颜色本身好得多)setTimeout())。根据当前像素的颜色,滤镜将花费更多或更少的时间。这使得可以确定像素是否与已知颜色相同的颜色,例如黑色或白色。

本白皮书(pdf)中的更多详细信息:https : //www.contextis.com/media/downloads/Pixel_Perfect_Timing_Attacks_with_HTML5_Whitepaper.pdf

顺便说一句:是的,这是浏览器的安全漏洞,但是我看不到浏览器供应商如何修补它。


有趣的解决方法,但是由于跨源策略是否安全?
市长蒙蒂

这篇文章已经快7年了!有人知道今天仍然存在这个安全漏洞吗?
罗德里戈

我怀疑它是固定的,CORS是否不适用。
xendi

12

合并这里在StackOverflow和其他站点中找到的各种参考,我是使用javascript和JQuery这样做的:

<html>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script src="jquery.js"></script>
<script type="text/javascript">
    window.onload = function(){
        var canvas = document.getElementById('myCanvas');
        var context = canvas.getContext('2d');
        var img = new Image();
        img.src = 'photo_apple.jpg';
        context.drawImage(img, 0, 0);
    };

    function findPos(obj){
    var current_left = 0, current_top = 0;
    if (obj.offsetParent){
        do{
            current_left += obj.offsetLeft;
            current_top += obj.offsetTop;
        }while(obj = obj.offsetParent);
        return {x: current_left, y: current_top};
    }
    return undefined;
    }

    function rgbToHex(r, g, b){
    if (r > 255 || g > 255 || b > 255)
        throw "Invalid color component";
    return ((r << 16) | (g << 8) | b).toString(16);
    }

$('#myCanvas').click(function(e){
    var position = findPos(this);
    var x = e.pageX - position.x;
    var y = e.pageY - position.y;
    var coordinate = "x=" + x + ", y=" + y;
    var canvas = this.getContext('2d');
    var p = canvas.getImageData(x, y, 1, 1).data;
    var hex = "#" + ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);
    alert("HEX: " + hex);
});
</script>
<img src="photo_apple.jpg"/>
</body>
</html>

这是我的完整解决方案。在这里,我只使用了画布和一个图像,但是如果您需要<map>在图像上使用它,那也是可能的。我希望能有所帮助。


2
如何使用滴管允许从任何地方获得颜色?
SearchForKnowledge

7

我同意以利亚提供的非常详细的答案。另外,我想说的是图像时不需要画布。正如您自己说的那样,您可以从php中获得这些图像,并且可以在服务器上进行颜色查询。

我建议您使用外部工具来处理此问题-这甚至使其与浏览器无关(但取决于OS):编写一个小工具(例如在c#中)为您执行颜色查询,并通过快捷方式调用并提交服务器的颜色。在CMS上下载该工具。

我用于CMS的另一个方法是通过解析CSS来“窃取”颜色:用例是使现有网站的颜色作为调色板提供给我的应用程序:

  • 我要求用户提供目标系统的URL-主要是公司的主页
  • 我解析页面以找到所有内联样式和链接样式的所有颜色定义
  • (您可以轻松地将其扩展到所有参考图像)
  • 结果是一个不错的调色板,所有公司颜色可供选择

也许这也是您CMS的解决方案?


干杯拉尔夫。构建自定义调色板是一个很好的主意,但并不是我手头的任务,因为将会有很多没有定义颜色范围的新内容。客户端应用程序当然是最干净的方法,但是我需要一个在Windows和Mac OS上都可以使用的工具。再次(在Mac上是第一次)重新进入客户端编程是一个很好的理由,但是我现在有很多事情要做。我想我只使用图像方法。
Pekka 2010年

6

参见新的input [type = color] HTML5元素:http : //www.w3.org/TR/html-markup/input.color.html,http : //demo.hongkiat.com/html5-form-input-type /index2.html

现在,它至少可以在Chrome浏览器中运行(在Ubuntu中经过测试,也应该适用于Windows)。它启动操作系统提供的颜色选择对话框。如果此对话框中有一个吸管(用于Gnome),则可以从屏幕上的任意位置选择一种颜色。尚未跨浏览器,但整洁且基于标准。


真好 自然,它也可以在Firefox中工作,但是如果您不必弹出浏览器对话框就可以这样做,那就太好了。
NoBugs '16

2
不幸的是,Chrome浏览器最近更新了其表单控件设计,并且其新的拾色器没有吸管。
mattsven

5

我不知道这是否可行,但是如果您的页面是静态的,则可以保存其中每个页面的图像屏幕截图(或者可能是每个浏览器/屏幕分辨率一个图像的屏幕截图),然后使用AJAX将光标坐标发送到服务器并使用PHP返回像素颜色 imagecolorat()

要截取屏幕截图,您可以使用Selenium IDE此处所述的

希望能帮助到你。


3

要添加到先前的答案中-

解决此问题的一种方法是您希望能够对1px x 1px的区域进行屏幕捕获。捕获屏幕区域的一种相当普遍的技术(例如,从基于Web的错误报告系统中捕获)是使用签名的Java applet和java.awt.Robot捕获图像。如果您对小程序进行签名,您的用户将获得“您是否信任此应用程序”对话框(带有“始终信任此发布者的应用程序”复选框),然后将能够使用该工具。

然后,您可以使用LiveConnect将结果传递给JavaScript(文档很旧,但是Java applet仍然支持此功能),也可以将其发布到服务器上。同样,您可以从JavaScript调用Java小程序。


Java Applet角度很有趣。但是,我不擅长对Applet进行编码,因此我可能无法为自己的任务实现此功能,因此将采用上述的Canvas方法。但是,感谢您引起我的注意,以后我也许可以使用它。
Pekka 2010年

3

为了安全起见,您无法使用Javascript捕获屏幕像素(因此开发人员无法为您的个人数据拍摄快照),但是您可以在Flash中进行操作-您可以使用Flash在Flash容器中获取像素数据。 .BitmapData类。

请访问http://www.sephiroth.it/tutorials/flashPHP/print_screen/ -我已在基于Flash的WYSYWIG项目中使用它来将图像保存到LAMP(PHP)服务器。

使用Flash的问题在于iOS设备本身不支持它,iOS设备现在非常流行,值得开发。闪光灯正在沿着灯管下降。

如果您的所有访问者都拥有支持canvas标记和JavaScript的最新Web浏览器,那么基于画布的方法无疑将是一个很好的方法。


2

没有内置的DOM方法可以通用地获取<canvas>特定像素位置处DOM元素的颜色(图像或除外)。

因此,为了做到这一点,我们必须使用HTML2CanvasDOM Panda之类的东西来对我们的网站进行“截屏”,获取用户的点击位置,并获取该特定位置处“截屏”的像素颜色。

使用HTML2Canvas(版本0.5.0-beta3),您可以执行以下操作:

// Take "screenshot" using HTML2Canvas
var screenshotCanvas,
    screenshotCtx,
    timeBetweenRuns = 10,
    lastTime = Date.now();
function getScreenshot() {
    // Limit how soon this can be ran again
    var currTime = Date.now();
    if(currTime - lastTime > timeBetweenRuns) {
        html2canvas(document.body).then(function(canvas) {
            screenshotCanvas = canvas;
            screenshotCtx = screenshotCanvas.getContext('2d');
        });
        lastTime = currTime;
    }
}
setTimeout(function() { // Assure the initial capture is done
    getScreenshot();
}, 100);

// Get the user's click location
document.onclick = function(event) {
    var x = event.pageX,
        y = event.pageY;

    // Look what color the pixel at the screenshot is
    console.log(screenshotCtx.getImageData(x, y, 1, 1).data);
}


// Update the screenshot when the window changes size
window.onresize = getScreenshot;

演示版


这是实现上述解决方案的演示:jsfiddle.net/8850s/an9f24hp 单击某个位置以将background-colordiv的设置设置在左上角(甚至在div本身上)
GalaxyCat105
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.