提问人:Pekka 提问时间:12/20/2009 最后编辑:Zach SaucierPekka 更新时间:10/14/2022 访问量:68865
JavaScript 吸管(在鼠标光标下分辨像素的颜色)
JavaScript eyedropper (tell color of pixel under mouse cursor)
问:
我正在寻找一个“吸管”工具,它为我提供了鼠标光标所在像素的十六进制值,在 JavaScript 中用于 CMS。
对于Firefox,有一个出色的ColorZilla扩展可以做到这一点。但是,它当然只是 FF,我真的很想将该工具与 CMS 一起交付。
一位荷兰开发人员有一个非常聪明的想法,即结合使用 Ajax 和 PHP 来找出图像上的像素颜色。但这限制了我可以访问服务器端的图像的范围,我真的梦想着一个通用工具。imagecolorat()
我将使用其中一种方法,但更喜欢跨浏览器、Javascript 或基于 Flash 的方式,不需要服务器端摆弄,也不需要安装扩展。
我也对任何 IE 特定的解决方案感兴趣,这些解决方案可以做 ColorZilla 可以做的事情 - 我可以忍受只支持 IE 和 FF,尽管跨浏览器解决方案当然是理想的。
答:
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 支持 canvas),使用 Flash 也无济于事,因为它也无法读取文档的像素数据。
评论
yourPassword.png
password.png
我确实同意以利亚提供的非常详细的回答。此外,我想说的是,当涉及到图像时,你不需要画布。正如您自己所说,您可以从 php 中获取这些图像,并且可以在服务器上进行颜色查询。
我建议你用一个外部工具来处理这个问题 - 这使得它甚至独立于浏览器(但依赖于操作系统):编写一个小工具(例如在c#中),它为你执行颜色查询,使用快捷方式调用并将颜色提交到你的服务器。将该工具作为下载工具提供在您的 CMS 上。
我用于 CMS 的另一个方法是通过解析 CSS 来“窃取”颜色:用例是将现有网站的颜色作为调色板提供给我的应用程序:
- 我要求用户提供来自目标系统的 URL——主要是公司的主页
- 我解析了页面以查找所有内联样式和链接样式中的所有颜色定义
- (您可以轻松地将其扩展到所有引用的图像)
- 结果是一个漂亮的调色板,有所有公司的颜色可供选择
也许这也是您的 CMS 的解决方案?
评论
我不知道这是否可行,但是如果您的页面是静态的,您可以保存每个页面的图像屏幕截图(或者每个浏览器/屏幕分辨率都保存一个图像屏幕截图?),然后使用AJAX将光标坐标发送到服务器并使用PHP返回像素颜色。imagecolorat()
要截取屏幕截图,您可以使用 Selenium IDE,如此处所述。
希望它有所帮助。
补充前面的答案——
考虑此问题的一种方式是,您希望能够对 1px x x 1px 区域进行屏幕截图。捕获屏幕区域(例如,从基于 Web 的错误报告系统中)的一种相当常见的技术是使用签名的 Java 小程序和 java.awt.Robot 来捕获图片。如果对小程序进行签名,用户将看到一个“是否信任此应用”对话框(其中包含“始终信任此发布者中的应用”复选框),然后将能够使用该工具。
然后,您可以使用 LiveConnect 将结果传递给 JavaScript(文档很旧,但 Java 小程序仍然支持此功能),也可以将其发布到服务器。同样,您可以从 JavaScript 调入 Java 小程序。
评论
合并了 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>
评论
为了安全起见,您不能使用 Javascript 捕获屏幕像素(因此开发人员无法拍摄您的个人数据的快照),但您可以在 Flash 中执行此操作 - 您可以使用 flash.display.BitmapData 类在 Flash 容器中获取像素数据。
查看 http://www.sephiroth.it/tutorials/flashPHP/print_screen/ -- 我在基于 Flash 的 WYSYWIG 项目中使用它来将图像保存到 LAMP (PHP) 服务器。
使用 Flash 的问题在于它在 iOS 设备上不受原生支持,而 iOS 设备现在非常流行,值得开发。闪光灯正在沿着管子向下移动。
基于 canvas 的方法肯定是一个不错的方法,前提是您的所有访问者都拥有支持 canvas 标签和 JavaScript 的最新 Web 浏览器。
请参阅新的 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的),那么你可以从屏幕上的任何一点选择一种颜色。还不是跨浏览器的,但干净且基于标准。
评论
使用一种称为浏览器定时攻击的技术,可以(某种程度上)确定任何像素的颜色,即使在 iframe 上也是如此。
基本上,这种技术测量的是渲染 SVG 滤镜在元素上的时间,而不是颜色本身(允许以比 更好的精度测量时间)。根据当前的像素颜色,滤镜需要或多或少的时间来应用。这样就可以确定像素是否与已知颜色相同 - 例如黑色或白色。requestAnimationFrame()
setTimeout()
本白皮书(pdf)中的更多详细信息:https://www.contextis.com/media/downloads/Pixel_Perfect_Timing_Attacks_with_HTML5_Whitepaper.pdf
顺便说一句:是的,这是一个浏览器安全漏洞,但我不明白浏览器供应商如何修补它。
评论
没有内置的 DOM 方法可以在特定像素位置获取 DOM 元素(图像或 除外)的颜色。<canvas>
因此,为了做到这一点,我们必须使用 HTML2Canvas 或 DOM 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;
演示
评论
background-color
Chrome Canary 现在支持 EyeDropper API!
更新:在 Chrome 95+ 中受支持
https://www.chromestatus.com/feature/6304275594477568
我相信我们很快就会在所有流行的浏览器中期待它。
基本上,它会将用户的光标更改为放大镜,并让他选择页面上的任何像素(适用于图像、视频和 iframe)。
const eyeDropper = new EyeDropper()
async function useEyeDropper() {
try {
const selectedColor = await eyeDropper.open()
console.log(selectedColor) // { sRGBHex: '#008080' }
} catch (err) {
console.log('eye dropper cancelled')
}
}
someTriggerEl.addEventListener('click', () => {
useEyeDropper();
})
如果你不太了解 async/await:
const eyeDropper = new EyeDropper()
someTriggerEl.addEventListener('click', () => {
eyeDropper.open().then(selectedColor => {
console.log(selectedColor) // { sRGBHex: '#008080' }
}).catch(() => {
console.log('eye dropper cancelled')
})
})
我对这个功能非常兴奋
评论
我知道这是一个非常古老的帖子,但是谷歌浏览器出现了一个新的 API 调用功能,称为“eyeDropper”
这是从那个博客中摘录的
const eyeDropper = new EyeDropper();
try {
const selectedColor = await eyeDropper.open();
console.log(selectedColor);
// logs: { sRGBHex: '#ff0000' }
} catch (err) {
console.log("color selection cancelled");
}
//You can test for support of EyeDropper using the following snippet, if you’re browsing with a browser that supports the EyeDropper API a button will be rendered below the code snippet.
if ("EyeDropper" in window) {
// supported
}
https://pqina.nl/blog/use-the-javascript-eye-dropper-api-to-select-colors-on-the-web/
我想对 @BorrisTB 的回答(以及每个人的回答都指向 EyeDropper API 的可用性)添加两个重要的考虑因素。
- 我们在一个运行顺利的项目上实现了 Eyedropper API
在我的机器上,但给了我
生产服务器。事实证明它需要.这在 localhost 上是可能的,并且仅在 HTTPS 上是可能的。所以让
确保页面通过 HTTPS 加载,以便 API 可用。
EyeDropper is undefined
window.isSecureContext = true
- 目前,它仅在基于 chromium 的浏览器上可用,并且 也仅适用于台式机。Mozilla 和 Safari 不支持此功能 功能,并且出于安全原因没有计划支持它。 请参阅下表 https://developer.mozilla.org/en-US/docs/Web/API/EyeDropper_API#browser_compatibility
评论