Пипетка JavaScript (указать цвет пикселя под курсором мыши) - PullRequest
66 голосов
/ 20 декабря 2009

Я ищу инструмент " eyedropper ", который дает мне шестнадцатеричное значение пикселя, под которым находится курсор мыши, в JavaScript для CMS.

Для Firefox есть отличное расширение ColorZilla , которое делает именно это. Тем не менее, это, конечно, только FF, и я бы очень хотел поставить инструмент вместе с CMS.

У голландского разработчика была очень умная идея использования комбинации Ajax и PHP imagecolorat() для определения цвета пикселей на изображении. Но это ограничивает диапазон изображений, к которым я могу получить доступ на стороне сервера , и я действительно мечтаю об универсальном инструменте.

Я буду работать с одним из этих подходов, но я бы предпочел кросс-браузерный, Javascript или Flash-способ, который не требует никаких действий на стороне сервера и установки расширений.

Меня также интересуют любые конкретные решения IE, которые делают то, что может сделать ColorZilla - я мог бы жить только с поддержкой IE и FF, хотя кросс-браузерное решение было бы, конечно, идеальным.

Ответы [ 9 ]

71 голосов
/ 20 декабря 2009

С 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 не поможет, так как он также не может считывать пиксельные данные документа.

14 голосов
/ 30 января 2014

Используя технику, названную Атака по времени браузера , можно (как бы) определить цвет любого пикселя, даже для фреймов.

По сути, этот метод измеряет время визуализации фильтра SVG для элемента, а не для самого цвета (requestAnimationFrame() позволяет измерять время с гораздо большей точностью, чем setTimeout()). В зависимости от текущего цвета пикселя, применение фильтра занимает больше или меньше времени. Это позволяет определить, является ли пиксель того же цвета, что и известный цвет, например черный или белый.

Подробнее в этом документе (pdf): http://www.contextis.com/documents/2/Browser_Timing_Attacks.pdf

Кстати: да, это дыра в безопасности браузера, но я не понимаю, как производители браузеров могут ее исправить.

11 голосов
/ 10 января 2012

Объединяя различные ссылки, найденные здесь в 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> поверх изображения, это тоже возможно. Я надеюсь, что помог.

7 голосов
/ 03 января 2010

Я согласен с очень подробным ответом, который дал Илия. Кроме того, я бы сказал, что вам не нужен холст, когда дело доходит до изображений. Как вы сами заявили, у вас есть эти изображения, доступные из php, и вы можете выполнять цветовой запрос на сервере.

Я бы предложил решить эту проблему с помощью внешнего инструмента - это делает его даже независимым от браузера (но зависящим от ОС): напишите небольшой инструмент (например, в C #), который выполняет цветовой запрос для вас, вызывается с помощью ярлык и отправляет цвет на ваш сервер. Сделайте инструмент доступным для скачивания на своей CMS.

Другой подход, который я использовал для CMS, заключался в том, чтобы «красть» цвета путем анализа CSS: сценарий использования состоял в том, чтобы сделать цвета уже существующего веб-сайта доступными в качестве цветовой палитры для моего приложения:

  • Я попросил пользователя указать URL-адрес целевой системы - в основном, домашней страницы компании
  • Я проанализировал страницу, чтобы найти все определения цветов во всех встроенных и связанных стилях
  • (вы можете легко распространить это на все ссылочные изображения)
  • В результате получилась приятная цветовая палитра со всеми цветами сопората на выбор

Может быть, это также решение для вашей CMS?

4 голосов
/ 03 марта 2013

См новый элемент ввода [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), тогда можно выбрать цвет из любой точки на экране . Пока не кросс-браузер, но чистый и основанный на стандартах.

4 голосов
/ 05 января 2010

Я не знаю, возможно ли это, но если ваши страницы статичны, вы можете сохранить снимок экрана каждого из них (или, может быть, один для каждого браузера / разрешения экрана?), А затем использовать AJAX для отправки курсора координаты на сервер и вернуть цвет пикселя с помощью PHP imagecolorat().

Чтобы сделать снимки экрана, вы можете использовать Selenium IDE , как описано здесь .

Надеюсь, это поможет.

3 голосов
/ 20 марта 2012

В качестве меры безопасности вы не можете захватывать пиксели экрана с помощью Javascript (поэтому разработчики не могут делать снимки ваших личных данных), но вы МОЖЕТЕ делать это во Flash - вы можете получать данные пикселей в контейнере Flash, используя flash.display.BitmapData class.

Извлечение http://www.sephiroth.it/tutorials/flashPHP/print_screen/ - я использовал его в проектах WYSYWIG на основе Flash для сохранения изображений на сервер LAMP (PHP).

Проблема с использованием Flash заключается в том, что он изначально не поддерживается на устройствах iOS, которые сейчас чрезвычайно популярны и для которых стоит разработать. Вспышка движется вниз по трубам.

Метод на основе холста, безусловно, будет хорошим, если у всех ваших посетителей есть современные веб-браузеры, которые поддерживают тег canvas и JavaScript.

3 голосов
/ 07 января 2010

Добавить к предыдущим ответам -

Одним из способов решения этой проблемы является то, что вы хотите иметь возможность делать снимки экрана размером 1 на 1 пиксель. Довольно распространенный метод захвата областей экрана (например, из веб-систем отчетов об ошибках) заключается в использовании подписанного Java-апплета и java.awt.Robot для захвата изображения. Если вы подпишите апплет, ваши пользователи получат диалоговое окно «Доверяете ли вы этому приложению» (с флажком «всегда доверять приложениям от этого издателя»), а затем смогут использовать этот инструмент.

Затем вы можете передать результат в JavaScript с помощью LiveConnect (документы старые, но Java-апплеты все еще поддерживают это), или вы можете опубликовать его на своем сервере. Точно так же вы можете вызывать апплет Java из JavaScript.

2 голосов
/ 14 марта 2017

Не существует встроенного метода DOM для общего получения цвета элемента DOM (кроме изображений или <canvas>) в определенном месте пикселя.

Таким образом, чтобы сделать это, мы должны использовать что-то вроде HTML2Canvas или DOM Panda , чтобы сделать «скриншот» нашего веб-сайта, получить местоположение клика пользователя и получить цвет пикселя "скриншота" в этом конкретном месте.

Используя HTML2Canvas (версия 0.5.0-бета3), вы можете сделать что-то вроде этого:

// 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;

Демо

...