开发者

Desaturate image when scrolling behind an element

I have an 'Is this possible on a canvas' question. Say I have a fixed div element on the page with it's background color set and make it opaque. Now when another element (an image) scrolls behind, it can be seen through the fixed div on top.

Now, I'd like to do this, except the full color image behind will desaturate (i.e. become opaque, greyscale) where the top div is covering it. I can't find any way this can be done with CSS3, nor does it seem possible to manipulate pixels with straight up javascript.

So I guess I'm wondering if the canvas element can detect standard overlapping DOM elements and redraw them on the surface. Or are there any other ways to tackle this? I don't want to make the whole page a canvas (for non html5 browsers), and flash is not an option.

Your thoughts are much apprecia开发者_如何学JAVAted.


This was interesting to me, so I implemented a solution.

See: http://jsfiddle.net/3eHmD/show/ (edit)

  • It will work in "all browsers".

  • It uses jQuery.

  • It uses pre-rendered images:

    Desaturate image when scrolling behind an element

    Desaturate image when scrolling behind an element

  • It doesn't have to use pre-rendered images. To avoid pre-rendering, I'd use Pixastic's desaturate (http://www.pixastic.com/lib/docs/actions/desaturate/).

JavaScript: (could be improved)

var $fixed = $('.fixed');
var $source = $('.content');

var $fixedCopy = $('<div class="fixedDimensions"></div>').appendTo('body').css('zIndex', 99);
var $contentCopy = $source.clone().appendTo($fixedCopy);


$contentCopy.find(':not(.magic)').css('visibility', 'hidden');
$contentCopy.find('.magic').each(function() {
    $(this).css('backgroundPosition', $(this).width() + 'px 0');
});

$(window).scroll(function(e) {
    $contentCopy.css('margin-top',-$(window).scrollTop());
}).scroll();

CSS:

html, body {
    margin: 0;
    padding: 0
}
body {
    background: #eee
}

.content {
    width: 300px;
    margin: 0 auto
}
#fixed {
    background: url(http://i.stack.imgur.com/GKWv7.png);
    color: red;
    font: 36px sans-serif;
    text-align: center
}
.fixedDimensions {
    height: 200px;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    overflow: hidden;
    z-index: 100;
}

HTML:

<div id="fixed" class="fixedDimensions">Hello</div>

<div id="container">
    <div class="content">
        <p><div class="magic" style="width:200px;height:300px;background:url(http://i.stack.imgur.com/b3LRY.jpg)"></div></p>
        <p>Lorem ipsum dolor...</p>
        <p><div class="magic" style="width:225px;height:300px;background:url(http://i.stack.imgur.com/6D8gh.jpg)"></div></p>
        <p>Aenean et diam dui..</p>
        ..
    </div>
</div>


Others have provided solutions that may or may not be better for what you want to do. In the interest of completeness, to answer your question of "is this possible on a Canvas?"

Yes, de-saturation can be done with a canvas. Here is how:

var imageData = ctx.getImageData(0,0,can.width, can.height);
var pixels = imageData.data;
var numPixels = pixels.length;

ctx.clearRect(0, 0, can.width, can.height);

for (var i = 0; i < numPixels; i++) {
    var average = (pixels[i*4] + pixels[i*4+1] + pixels[i*4+2]) /3;
    // set red green and blue pixels to the average value
    pixels[i*4] = average;
    pixels[i*4+1] = average;
    pixels[i*4+2] = average;
}
ctx.putImageData(imageData, 0, 0);

You average the color of the three existing colors to get the average brightness of color. Then you set all three colors to the same value to get gray at the average brightness. Make sense?

Example:

http://jsfiddle.net/DZmyB/4/


If you're willing to use jQuery, you might want to look at the jQuery Desaturate plugin. I realize it doesn't do everything you want (it's simply saturating or desaturating an image), but it could get you some of the way there.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜