如何使用CSS(和JavaScript?)来创建模糊的"磨砂"背景?

Aar*_*ken 50 javascript css html5 webkit css3

我正在尝试使用HTML5,CSS3和JavaScript创建一个可以在webkit浏览器上运行的iOS 7风格磨砂外观.

从技术上讲,给出以下HTML:

<style>
  #partial-overlay {
    width: 100%;
    height: 20px;
    background: rgba(255, 255, 255, .2); /* TODO frost */
    position: fixed;
    top: 0;
    left: 0;
  }
</style>
<div id="main-view">
  <div style="width: 50px; height: 50px; background: #f00"></div>
  To my left is a red box<br>
  Now there is just text<br>
  Text that goes on for a few pixels <br>
  or even more
</div>
<div id="partial-overlay">
  Here is some content
</div>
Run Code Online (Sandbox Code Playgroud)

我想-webkit-filter: blur(5px)在水平的前20px处应用类似a的东西#main-view.

如果CSS被修改为#partial-overlay { width: 20px; height: 100%; ...}那么我需要-webkit-filter: blur(5px)垂直应用到前20px.

显而易见的解决方案是使用javascript来复制#main-view,设置overflow: hidden,然后根据需要更改宽度/高度,但这似乎很难概括为更复杂的页面/ CSS结构.

有没有更好的方法来实现这一点,最小的性能和最大的普遍性?

编辑:这是我想要实现的一个例子: 小样

apa*_*aul 20

感谢您的灵感......它引导我使用这个画布插件来实现这一目的

新增和改进:-webkit-和Firefox工作示例,现在重新调整大小/流畅.

JS

$(document).ready(function () {
    frost = function () {
        var w = $('#main-view').width();
        html2canvas(document.body, {
            onrendered: function (canvas) {
                document.body.appendChild(canvas);
                $('canvas').wrap('<div id="contain" />');
            },
            width: w,
            height: 30
        });
        $('canvas, #partial-overlay, #cover').hide();
        $('#cover').fadeIn('slow', function () {
            $('#partial-overlay').fadeIn('slow');
        });
    };

    $('body').append('<div id="cover"></div><svg id="svg-image-blur"><filter id="blur-effect-1"><feGaussianBlur stdDeviation="2"/></filter></svg>');

    $('#main-view').click(function () {
        frost();
        $('#partial-overlay').addClass('vis');
        $(window).resize(function () {
            $('canvas, #partial-overlay, #cover').hide();
        });

        function onResize() {
            if ($('#partial-overlay').hasClass('vis')) {
                frost();
            }
        }
        var timer;
        $(window).bind('resize', function () {
            timer && clearTimeout(timer);
            timer = setTimeout(onResize, 50);
        });

    });

    $('#partial-overlay').click(function () {
        $('#partial-overlay').removeClass('vis');
        $('canvas, #partial-overlay, #cover').hide();
    });
});
Run Code Online (Sandbox Code Playgroud)

CSS

#main-view {
    width:75%;
    height:50%;
    box-sizing: border-box;
    margin:8px;
}
#partial-overlay {
    display:none;
    width: 100%;
    height: 20px;
    position: absolute;
    top: 0;
    left: 0;
    z-index:99;
    background: rgba(255, 255, 255, 0.2);
    cursor:pointer;
}
canvas {
    position: absolute;
    top: 0;
    left: 0;
    -webkit-filter:blur(5px);
    filter: url(#blur-effect-1);
}
#cover {
    display:none;
    height:19px;
    width:100%;
    background:#fff;
    top:0;
    left:0;
    position:absolute;
}
#contain {
    height:20px;
    width:100%;
    overflow:hidden;
    position:absolute;
    top:0;
    left:0;
}
svg {
    height:0;
    width:0;
}
Run Code Online (Sandbox Code Playgroud)

HTML

<div id="main-view">
    <div style="width: 10%; height: 20%; background: #f00; float: left"></div>To my left is a red box
    <br>Now there is just text
    <br>Text that goes on for a few pixels
    <br>or even more</div>
<div id="partial-overlay">Here is some content</div>
Run Code Online (Sandbox Code Playgroud)

我把它放在一个点击功能,因为我认为这将是最有可能的用例.它在文档就绪时也能正常工作.

虽然画布表示不会像素完美,但我认为它在大多数情况下并不重要,因为它的模糊.

更新:根据要求,现在可以重新调整大小.我还将封面div移到JS中,并为Firefox添加了svg.调整大小需要在每个重新调整大小时重绘画布,因此我将其设置为在调整大小时隐藏画布,叠加等,然后在重新调整大小时将其替换.


Ger*_*art 14

基本上你可以有一个叠加占位符,你复制主要内容并同步两个div的滚动,而不是仅在叠加层上应用css模糊滤镜.

一个简单的JavaScript将做:

$(document).ready(function(){
  $('.overlay').append( $('.content').html() );
  $('.content').on('scroll', function(){
    $('.overlay').scrollTop($(this).scrollTop());
  });
});
Run Code Online (Sandbox Code Playgroud)

而对于CSS:

.overlay {
    overflow:hidden;
    -webkit-filter: blur(.25em);
    background:#fff;
}
Run Code Online (Sandbox Code Playgroud)

我为你准备了一个工作示例(仅限webkit):

http://jsfiddle.net/kmxD3/1/

玩得开心!:)

  • 这似乎是迄今为止我遇到过的最简单,最优雅的解决方案. (3认同)
  • @ Cort3z,这是由于模糊效果淡出(这使你可以看到下面的常规文本.为了更好地理解,请看这篇文章中的模糊示例中的图像:http://www.html5rocks.com/en/tutorials/filters/understanding-css /(注意右边的图像边缘渐变为白色).为了解释这一点并且边缘模糊,你必须使模糊的内容更大一些然后将其剪辑(或使其离开画布)以获得更清晰的边缘).我希望我更清楚......这个例子应该有一个更清晰的边缘:http://jsfiddle.net/kmxD3/105/ (2认同)

小智 11

有没有更好的方法来实现这一点,最小的性能和最大的普遍性?

答案是否定的.

原因是为了做你想做的事情你需要直接访问用于浏览器窗口的位图来提取或操纵你想要模糊的区域中的像素(我希望,浏览器中的"aero"看起来很漂亮整洁..)或过滤器,它适用于您应用它的后面的元素(或可以设置限制区域).

由于没有本机支持这样做(除了画布和扩展API,或者从html生成画布图像的库 - >相对慢),这需要在任何一种情况下使用技巧(图像,拆分div等)来完成.

如果你在画布上创建了你的页面中的所有内容,你可以做很多有趣的事情,但你也需要自己进行布局,更新,过滤等等,因此你会回来没有非优化,因为Javascript比本机慢(更不用说它会容易出错).

直到浏览器允许你将窗口的一部分作为画布抓取(从来没有?因为那将要求该页面上的所有内容都是同源的或具有设置特殊接受标头的内容),除了做技巧之外没有办法.

更新

作为一个演示,您可以使用html2canvas等,但必须使用妥协( - >慢性能) - 演示是粗略的,实验性的,需要调整才能正常工作 - 但仅限于演示:
http:// jsfiddle.net/AbdiasSoftware/RCaLR/

结果:

在此输入图像描述

抓取部分背景的通用功能:

getBlurredBG(x, y, width, height, id);
Run Code Online (Sandbox Code Playgroud)

使用html2canvas获取窗口的一部分:

function getBlurredBG(x, y, w, h, id) {

    html2canvas(document.body, {
        onrendered: function (canvas) {
            process(canvas, x, y, w, h, id);
        },
        width: (x + w),
        height: (y + h)
    });
}
Run Code Online (Sandbox Code Playgroud)

处理内容:

function process(canvas, x, y, w, h, id) {

    //create new canvas to enable clipping
    //As html2canvas returns a canvas from 0,0 to width and height
    //we need to clip it.
    var ocanvas = document.createElement('canvas');
    ocanvas.width = w;
    ocanvas.height = h;
    ocanvas.style.left = x + 'px';
    ocanvas.style.top = y + 'px';
    ocanvas.style.position = 'absolute';
    ocanvas.id = id;

    var ctx = ocanvas.getContext('2d');
    ctx.drawImage(canvas, x, y, w, h,
                          0, 0, w, h);

    stackBlurCanvasRGB(ocanvas, x, y, w, h, 28)
    lighten(ocanvas);

    ctx.fillStyle = 'rgba(255,255,255,0.5)';
    ctx.fillRect(x, y, w, h);

    ctx.fillStyle = '#999';
    ctx.font = '32px arial';
    ctx.fillText("Partial overlay content", 10, 60);

    document.body.appendChild(ocanvas);
}
Run Code Online (Sandbox Code Playgroud)


Dow*_*oat 10

最近,一个新的-webkit-backdrop-filter.Safari 9.0目前支持这一功能,Chrome支持旗帜.

演示:

#blurred {
  -webkit-backdrop-filter: blur(10px);
  width: 200px;
  height: 100px;
  position: fixed;
  top: 50px;
  left: 50px;
  border: 3px solid white;
}
Run Code Online (Sandbox Code Playgroud)
<img src="https://upload.wikimedia.org/wikipedia/commons/e/eb/Ash_Tree_-_geograph.org.uk_-_590710.jpg">

<div id="blurred"> Blurred </div>
Run Code Online (Sandbox Code Playgroud)

现在支持只有Safari.Chrome和Opera在旗帜下有这个.

注意:今天-webkit-backdrop-filter仍然没有很好的支持,所以如果你想获得这种效果,最好的方法是使用SVGfeGaussianBlur


Bjö*_*rth 6

仅 CSS 解决方案: backdrop-filter: blur(4px);


Dav*_*yen 2

不幸的是,没有好的方法可以做到这一点,因为您发现您将需要主 div 的副本:

<div class="wrapper">
   <div class="overlay"></div>
   <div id="main-copy"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

覆盖将推动包装宽度,而主副本将在背景中模糊。显然,如果主副本中的内容很复杂,就会出现性能问题。