JavaScript: Invertir color en todos los elementos de una página


Nota: Estoy manteniendo una versión actualizada del bookmarklet en mi pregunta que funciona bien y se basa en la respuesta de Jacob. Si está buscando un bookmarklet para usar, use ese. Vea la fantástica respuesta de leosok si solo desea algo increíble que funcione en Chrome.

Quiero poder invertir el color de todos los elementos de una página con un bookmarklet JavaScript. Sé que para invertir un color se resta cada uno de los valores hexadecimales RGB de 255 (xFF), pero más allá de eso no estoy seguro de cómo proceder.

¿Cómo puedo lograr esto?

Usar jQuery es aceptable, y solo necesita funcionar en Chrome, aunque si funcionara en Firefox eso sería una ventaja.

Esto excluye imágenes: los colores de fondo, texto y enlaces deben invertirse. Básicamente cualquier cosa que obtiene su color de CSS.

ACTUALIZACIÓN Aquí hay un bookmarklet actualizado que soluciona el problema del elemento anidado y funcionará en muchos sitios diferentes (incluido éste)

UPDATE2 Se ha añadido algo de soporte para la transparencia, el manejo de elementos que tienen rgba de color de fondo predeterminado(0, 0, 0, 0). Más sitios deberían estar trabajando ahora con el actualizado.

javascript: (function ($) {
    function load_script(src, callback) {
        var s = document.createElement('script');
        s.src = src;
        s.onload = callback;
        document.getElementsByTagName('head')[0].appendChild(s);
    }

    function invertElement() {
        var colorProperties = ['color', 'background-color'];
        var color = null;
        for (var prop in colorProperties) {
            prop = colorProperties[prop];
            if (!$(this).css(prop)) continue;
            if ($(this).data(prop) != $(this).css(prop)) continue;

            if (($(this).css(prop) === 'rgba(0, 0, 0, 0)') || ($(this).css(prop) === 'transparent')) {
                if ($(this).is('body')) {
                    $(this).css(prop, 'black');
                    continue;
                } else {
                    continue;
                }
            }
            color = new RGBColor($(this).css(prop));
            if (color.ok) {
                $(this).css(prop, 'rgb(' + (255 - color.r) + ',' + (255 - color.g) + ',' + (255 - color.b) + ')');
            }
            color = null;
        }
    }

    function setColorData() {
        var colorProperties = ['color', 'background-color'];
        for (var prop in colorProperties) {
            prop = colorProperties[prop];
            $(this).data(prop, $(this).css(prop));
        }
    }

    function invertColors() {
        $(document).live('DOMNodeInserted', function(e) {
            var $toInvert = $(e.target).find('*').andSelf();
            $toInvert.each(setColorData);
            $toInvert.each(invertElement);
        });
        $('*').each(setColorData);
        $('*').each(invertElement);
        $('iframe').each(function () {
            $(this).contents().find('*').each(setColorData);
            $(this).contents().find('*').each(invertElement);
        });
    }
    load_script('http://www.phpied.com/files/rgbcolor/rgbcolor.js', function () {
        if (!window.jQuery) load_script('https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js', invertColors);
        else invertColors();
    });

})(jQuery);

Ahora funciona con la mayoría de los sitios que he probado. Sin embargo, las imágenes de fondo pueden plantear un problema.

Author: Muhd, 2011-01-22

5 answers

Hola compañeros inversores!

Mi solución parece funcionar solo para chrome en este momento, pero invierte todo (incluyendo imágenes e iframes) como se ve aquí:

introduzca la descripción de la imagen aquí

Tampoco hace uso de bibliotecas externas y es muy sencillo: añadir un -webkit-filter: invert(100%) al selector html.

javascript: (
function () { 
// the css we are going to inject
var css = 'html {-webkit-filter: invert(100%);' +
    '-moz-filter: invert(100%);' + 
    '-o-filter: invert(100%);' + 
    '-ms-filter: invert(100%); }',

head = document.getElementsByTagName('head')[0],
style = document.createElement('style');

// a hack, so you can "invert back" clicking the bookmarklet again
if (!window.counter) { window.counter = 1;} else  { window.counter ++;
if (window.counter % 2 == 0) { var css ='html {-webkit-filter: invert(0%); -moz-filter:    invert(0%); -o-filter: invert(0%); -ms-filter: invert(0%); }'}
 };

style.type = 'text/css';
if (style.styleSheet){
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}

//injecting the css to the head
head.appendChild(style);
}());

Para mí, esto solo funciona en chrome. Pero allí funciona como un encanto.

Aquí está el violín: http://jsfiddle.net/nikita_turing/jVKw6/3 / Con el Bookmarklet incluir. Si alguien tiene una idea de cómo hacer que funcione para Firefox (SVG-Filters?) ¡adelante!

Saludos leosok

 32
Author: leosok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-26 14:45:54

Lo primero es lo primero, agarra la impresionante RGBColor clase aquí.

Aquí va:

Ejemplo de JsFiddle

//set up color properties to iterate through
var colorProperties = ['color', 'background-color'];

//iterate through every element in reverse order...
$("*").get().reverse().each(function() {
    var color = null;

    for (var prop in colorProperties) {
        prop = colorProperties[prop];

        //if we can't find this property or it's null, continue
        if (!$(this).css(prop)) continue; 

        //create RGBColor object
        color = new RGBColor($(this).css(prop));

        if (color.ok) { 
            //good to go, let's build up this RGB baby!
            //subtract each color component from 255
            $(this).css(prop, 'rgb(' + (255 - color.r) + ', ' + (255 - color.g) + ', ' + (255 - color.b) + ')');
        }
        color = null; //some cleanup
    }
});

Captura de pantalla:

texto alt

EDITAR : Aquí hay un bookmarklet que ahora puede copiar y pegar en su navegador ( http://jsfiddle.net/F7HqS/1/)

javascript:function load_script(src,callback){var s=document.createElement('script');s.src=src;s.onload=callback;document.getElementsByTagName('head')[0].appendChild(s);}function invertColors(){var colorProperties=['color','background-color'];$('*').each(function(){var color=null;for(var prop in colorProperties){prop=colorProperties[prop];if(!$(this).css(prop))continue;color=new RGBColor($(this).css(prop));if(color.ok){$(this).css(prop,'rgb('+(255-color.r)+','+(255-color.g)+','+(255-color.b)+')');}color=null;}});}load_script('http://www.phpied.com/files/rgbcolor/rgbcolor.js',function(){if(!window.jQuery)load_script('https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js',invertColors);else invertColors();});
 70
Author: Jacob Relkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-03 18:18:52

He limpiado los comentarios de una de las respuestas (por leosok) de arriba, por lo que funcionará como un bookmarklet en chrome. Tenga en cuenta que esta solución es más eficiente que el punto más alto actual aquí, además de que funciona incluso si el html cambia después de ejecutar el script.

javascript:(function () { 
    var css = 'html {-webkit-filter: invert(100%);' + '-moz-filter: invert(100%);' + '-o-filter: invert(100%);' + '-ms-filter: invert(100%); }';
    var head = document.getElementsByTagName('head')[0];
    var style = document.createElement('style');
    if (!window.counter) { 
        window.counter = 1;
    } else { 
        window.counter++;
        if (window.counter % 2 == 0) { 
            var css = 'html {-webkit-filter: invert(0%); -moz-filter: invert(0%); -o-filter: invert(0%); -ms-filter: invert(0%); }'
        } 
    }
    style.type = 'text/css';
    if (style.styleSheet) {
        style.styleSheet.cssText = css;
    } else {
        style.appendChild(document.createTextNode(css));
    }
    head.appendChild(style);
}());

Una línea para bookmarklet. crear un marcador, a continuación, editar la url a este: javascript:(function () { var css = 'html {-webkit-filter: invert(100%);' + '-moz-filter: invert(100%);' + '-o-filter: invert(100%);' + '-ms-filter: invert(100%); }'; var head = document.getElementsByTagName('head')[0]; var style = document.createElement('style'); if (!window.counter) { window.counter = 1; } else { window.counter++; if (window.counter % 2 == 0) { var css = 'html {-webkit-filter: invert(0%); -moz-filter: invert(0%); -o-filter: invert(0%); -ms-filter: invert(0%); }' } } style.type = 'text/css'; if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } head.appendChild(style); }());

 3
Author: erb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-05 16:45:08

La respuesta aceptada es totalmente correcta, con un defecto menor. Cada vez que cambia la inversión, agrega OTRA etiqueta de estilo a la cabeza. Haga esto en su lugar

  // the css we are going to inject
  let css = 'html {-webkit-filter: invert(100%);' +
    '-moz-filter: invert(100%);' +
    '-o-filter: invert(100%);' +
    '-ms-filter: invert(100%); }';

  let head = $('head')[0];
  let invertStyle = $('#invert')[0];

  if (invertStyle) {
    head.removeChild(invertStyle);
  } else {
    let style = document.createElement('style');

    style.type = 'text/css';
    style.id = 'invert';
    if (style.styleSheet){
      style.styleSheet.cssText = css;
    } else {
      style.appendChild(document.createTextNode(css));
    }

    //injecting the css to the head
    head.appendChild(style);
  }

De esa manera, simplemente elimina la etiqueta si quieres deshacer la inversión. Funciona muy bien!

 2
Author: astryk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-18 23:12:25

Pensé que sería divertido intentar invertir imágenes. No tardó mucho en encontrar una biblioteca Javascript adecuada para la edición de imágenes: http://www.pixastic.com/lib /

Probablemente no pueda cargar toda esa biblioteca en un bookmarklet, pero si lo aloja usted mismo puede agregar algo como esto al final del bookmarklet (después de invertColors):

load_script('http://www.example.com/pixastic.invert.js', function () {$('img').each(function() {try{$(this).pixastic("invert");} catch(e) {}})})

Creo que vale la pena señalar que si su objetivo es tomar una página con un fondo blanco y hacerla negra (o vice versa), algo más simple podría estar en orden.

Acabo de probar el bookmarklet de Jacob y lo comparé con una versión más ingenua que encontré en los foros de soporte de Google: http://www.google.com/support/forum/p/Chrome/thread?tid=26affebdd0da12d9&hl=en

La inversión de Jacob parece funcionar con menos frecuencia y toma un poco más de tiempo en páginas grandes. Creo que terminaré usando la versión ingenua con más frecuencia.

 1
Author: i_grok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-28 01:20:35