How to dim an image keeping transparency untouched with CSS or JS?

主宰稳场 提交于 2019-12-03 12:33:32

There is a relatively new CSS property filter which might achieve what you are after.

The brightness option seems to be what you are after.

EDIT - Added interim support for FF via URL

JSFiddle Demo (with brightness and contrast options)

CSS

img {
width:250px;
}
#one:hover {
    -webkit-filter:brightness(50%);
    -moz-filter:brightness(50%);
    filter: url(#brightness); /* required for FF */
    filter:brightness(50%);
}
#two:hover {
    -webkit-filter:contrast(50%);    
    -moz-filter:contrast(50%);
     filter: url(#contrast);
    filter:contrast(50%);
}

MDN on Filter

Support is non-IE see CanIUse.com

FF support (at the time of writing) requires definition of an SVG filter

Brightness @ 50%

<svg height="0" xmlns="http://www.w3.org/2000/svg">

    <filter id="brightness">
        <feComponentTransfer>
            <feFuncR type="linear" slope=".5" />
            <feFuncG type="linear" slope=".5" />
            <feFuncB type="linear" slope=".5" />
        </feComponentTransfer>
    </filter>

</svg>

Contrast @ 200%

<svg height="0" xmlns="http://www.w3.org/2000/svg">
    <filter id="contrast">
        <feComponentTransfer>
            <feFuncR type="linear" slope="2" intercept="-(0.5 * 2) + 0.5" />
            <feFuncG type="linear" slope="2" intercept="-(0.5 * 2) + 0.5" />
            <feFuncB type="linear" slope="2" intercept="-(0.5 * 2) + 0.5" />
        </feComponentTransfer>
    </filter>
</svg>

If you want to use javascript instead of css, it's not especially difficult to do this with the HTML canvas. You simply hand the canvas an image object and then grab the context which will allow you to loop through and manipulate the individual color channels. Of course it breaks completely with no JS.

function darkenImage(imageObj, percentage) {
    var canvas = document.getElementById('aCanvas');
    var context = canvas.getContext('2d');
    var x =0;
    var y =0;

    context.drawImage(imageObj, x, y);

    var imageData = context.getImageData(x, y, imageObj.width, imageObj.height);
    var data = imageData.data;

    for(var i = 0; i < data.length; i += 4) {
       // red
       data[i] = percentage * data[i];
       // green
       data[i + 1] = percentage * data[i + 1];
       // blue
       data[i + 2] =  percentage * data[i + 2] ;
    }

    // overwrite original image
    context.putImageData(imageData, x, y);
  }
var anImage = new Image();
anImage.onload = function() {
    darkenImage(this, .5);
  };
anImage.crossOrigin = 'http://api.imgur.com/crossdomain.xml'
anImage.src = 'http://i.imgur.com/GnMumrk.png';

This is a naive calculation to make it easy, but as you can see it wouldn't be hard to alter it to something a little fancier. Since we don't touch the alpha channel, the transparency remains untouched.

Here's a fiddle: http://jsfiddle.net/markm/kwsogrdt/
(the browser complains about the cross origin image at least in safari which is why the second to last line is there.)

Have you thought of instead of changing the opacity of the image, say putting a div on top of the image with the same size as the image, opacity of 0.3 and a background color of black.

This may not be what you are looking for though its food for thought.

Gab

Another way to do this would be by using new CSS mask property (currently fully supported only by webkit) on the div with the darkening.

.dim {
  display: none;
  /*Also position it above the image*/
 }

.dim:hover {
 background-color: black;
 opacity: 0.5;
 -webkit-mask: url(image.png) top left / cover;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!