javascript 如何在不使用 CSS 或 JS 的情况下使图像变暗以保持透明度?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25092391/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 03:55:43  来源:igfitidea点击:

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

javascripthtmlcssopacity

提问by Konstantin Pereiaslov

Normal approach to dimming an image suggested everywhere is to change it's opacity attribute and display something dark under it. However, my image has transparency and is on white background. So I want to keep the background under transparent parts of image white, only making darker the pixels that have color. Is this possible to do in CSS (preferably) or JS?

建议在任何地方使图像变暗的正常方法是更改​​它的不透明度属性并在其下方显示一些黑暗的东西。但是,我的图像具有透明度并且是白色背景。所以我想将背景保留在图像白色的透明部分下,只使有颜色的像素变暗。这可以在 CSS(最好)或 JS 中完成吗?

EDIT: Sample images http://imgur.com/a/Tat9f

编辑:示例图像http://imgur.com/a/Tat9f

Example image:

示例图像:

enter image description here

在此处输入图片说明

回答by Paulie_D

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

有一个相对较新的 CSS 属性filter可以实现您的目标。

The brightnessoption seems to be what you are after.

brightness选项似乎是您所追求的。

EDIT - Added interim support for FF via URL

编辑 - 通过 URL 添加了对 FF 的临时支持

JSFiddle Demo (with brightness and contrast options)

JSFiddle Demo(带有亮度和对比度选项)

CSS

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

过滤器上的 MDN

Support is non-IE see CanIUse.com

支持非 IE 见CanIUse.com

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

FF 支持(在撰写本文时)需要定义 SVG 过滤器

Brightness @ 50%

亮度@ 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%

对比度 @ 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>

回答by Mark Meyer

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.

如果你想使用 javascript 而不是 css,用 HTML 画布来做到这一点并不是特别困难。您只需将一个图像对象交给画布,然后获取上下文,这将允许您遍历和操作各个颜色通道。当然,它在没有 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.

这是一个简单的计算,使其变得容易,但正如您所见,将其更改为更高级的东西并不难。由于我们不接触 Alpha 通道,因此透明度保持不变。

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.)

这是一个小提琴:http: //jsfiddle.net/markm/kwsogrdt/
(浏览器至少在 safari 中抱怨交叉原点图像,这就是为什么倒数第二行在那里。)

回答by Gabriel

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.

你有没有想过不改变图像的不透明度,比如在图像顶部放置一个与图像大小相同的 div,不透明度为 0.3,背景颜色为黑色。

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

这可能不是您正在寻找的内容,尽管它值得深思。

Gab

瞎扯

回答by Konstantin Pereiaslov

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

另一种方法是mask在带有变暗的 div 上使用新的 CSS属性(目前仅由 webkit 完全支持)。

.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;
}