【问题标题】:Blur canvas that is full width of window without transparent edge?模糊没有透明边缘的窗口全宽的画布?
【发布时间】:2017-04-14 08:53:06
【问题描述】:

我在尝试使用画布和 CSS 模糊过滤器实现的效果时遇到了一些问题。

基本上我需要一个 100% 的窗口高度和宽度的画布,可以擦除它以显示位于下方的元素。我正在使用模糊,因此形状/绘图看起来很模糊(这是必需的)。

我的问题是,尽管画布尺寸过大,但拐角处仍有透明边缘,显示下方的元素(即具有蓝色背景的主体)。我尝试了多个负边距/溢出黑客,但似乎无法绕过它?

我需要这个画布是屏幕的整个宽度,模糊,并且根本不裁剪,但也许这就是 CSS 过滤器的呈现方式,只有可见的内容?

(function() {
     
     // make canvas larger than window 
     var largeWidth = window.innerWidth * 3;
     var largeHeight = window.innerHeight * 3;
     function createCanvas(parent, width, height) {
      var canvas = {};
      canvas.node = document.createElement('canvas');
      canvas.context = canvas.node.getContext('2d');
      canvas.node.width = largeWidth;
      canvas.node.height = largeHeight;
      parent.appendChild(canvas.node);
      return canvas;
     }

    function init(container, width, height, fillColor) {
     var canvas = createCanvas(container, 3000, 3000);
     var ctx = canvas.context;
     ctx.fillCircle = function(x, y, radius, fillColor) {
      this.fillStyle = fillColor;
      this.beginPath();
      this.moveTo(x, y);
      this.arc(x, y, radius, 0, Math.PI * 2, false);
      this.fill();
     };
     ctx.clearTo = function(fillColor) {
      ctx.fillStyle = fillColor;
      ctx.fillRect(0, 0, width, height);
     };
     ctx.clearTo(fillColor || "#ddd");
     canvas.node.onmousemove = function(e) {
      var x = e.pageX - this.offsetLeft;
      var y = e.pageY - this.offsetTop;
      var radius = 100; // or whatever
      var fillColor = '#ff0000';
      ctx.globalCompositeOperation = 'destination-out';
      ctx.fillCircle(x, y, radius, fillColor);
     };
     canvas.node.onmousedown = function(e) {
      canvas.isDrawing = true;
     };
    }

    var container = document.getElementById('canvas');
    init(container, largeWidth, largeHeight, '#fff');

    })();
/* CSS: */

body {
  background: blue;
}

#canvas {
  z-index: 1;
  top: 0;
  left: 0;
  position: fixed;
  filter: blur(10px);
  -webkit-filter: blur(10px);
}
<div id = "canvas"></div>

请看我的fiddle

谢谢

【问题讨论】:

  • 需要去掉div的过滤器吗?
  • @KarthikSivakumar 我需要滤镜,以获得模糊效果

标签: javascript jquery html css canvas


【解决方案1】:

解决方案 1 - 又名“今日就绪”

不要模糊你的画布,但要模糊你放在里面的东西;例如:

// After filling circle
context.shadowColor = color;
context.shadowBlur = 16;
context.stroke();

这是fiddle

解决方案 2 - 又名“明天……也许”

Webkit 正在开发此类功能。但是我不确定它是否会按照您对画布的预期工作,也许它会将整个画布视为“模糊蒙版”,因此如果画布内的内容被擦除,它将在事件下方模糊。这是功能:

backdrop-filter: blur(10px);

这里有一些doc

ps:

  1. 我不确定是否有必要像您一样包装画布 .. 只需创建一个并直接编辑其属性!
  2. 哎哟!如果你将元素尺寸放大 3 倍但不设置偏移量,它只会在右侧和底部溢出

【讨论】:

    【解决方案2】:

    您可以从画布中删除过滤器并使用gradient brush 来实现相同的效果。

    (function() {
         
         // make canvas larger than window 
         var largeWidth = window.innerWidth * 3;
         var largeHeight = window.innerHeight * 3;
         function createCanvas(parent, width, height) {
          var canvas = {};
          canvas.node = document.createElement('canvas');
          canvas.context = canvas.node.getContext('2d');
          canvas.node.width = largeWidth;
          canvas.node.height = largeHeight;
          parent.appendChild(canvas.node);
          return canvas;
         }
    
        function init(container, width, height, fillColor) {
         var canvas = createCanvas(container, 3000, 3000);
         var ctx = canvas.context;
         ctx.fillCircle = function(x, y, radius, fillColor) {
          this.fillStyle = fillColor;
          this.beginPath();
          this.moveTo(x, y);
          this.arc(x, y, radius, 0, Math.PI * 2, false);
          this.fill();
         };
         ctx.clearTo = function(fillColor) {
          ctx.fillStyle = fillColor;
          ctx.fillRect(0, 0, width, height);
         };
         ctx.clearTo(fillColor || "#ddd");
         canvas.node.onmousemove = function(e) {
            var x = e.pageX - this.offsetLeft;
            var y = e.pageY - this.offsetTop;
            var radius = 100; // or whatever
            var fillColor = '#ff0000';
            var radgrad = ctx.createRadialGradient(x,y,0,x,y,radius);
    
             radgrad.addColorStop(0, 'rgba(255,0,0,1)');
             radgrad.addColorStop(0.6, 'rgba(228,0,0,.6)');
             radgrad.addColorStop(1, 'rgba(228,0,0,0)');
    
            ctx.globalCompositeOperation = 'destination-out';
            ctx.fillCircle(x, y, radius, radgrad);
        };
         canvas.node.onmousedown = function(e) {
          canvas.isDrawing = true;
         };
        }
    
        var container = document.getElementById('canvas');
        init(container, largeWidth, largeHeight, '#fff');
    
        })();
    /* CSS: */
    
    body {
      background: blue;
    }
    
    #canvas {
      z-index: 1;
      top: 0;
      left: 0;
      position: fixed;
      
    }
    <div id = "canvas"></div>

    【讨论】:

    • 这很接近,但确实没有达到与 CSS 相同的模糊程度
    • 您可以将第二个渐变色标调整为radgrad.addColorStop(0.4, 'rgba(228,0,0,.3)');
    【解决方案3】:

    你应该改变你的CSS如下

    (function() {
    
      var largeWidth = ( window.innerWidth * 3)+30;
      var largeHeight = (window.innerHeight * 3)+30;
    
      function createCanvas(parent, width, height) {
    
        var canvas = {};
        canvas.node = document.createElement('canvas');
        canvas.context = canvas.node.getContext('2d');
        canvas.node.width = largeWidth;
        canvas.node.height = largeHeight;
        parent.appendChild(canvas.node);
        var overlay = document.getElementById("overlay");
        overlay.style.width=(largeWidth -30) +"px";
        overlay.style.height =( largeHeight-30)+"px";
        return canvas;
      }
    
      function init(container, width, height, fillColor) {
        var canvas = createCanvas(container, 3000, 3000);
        var ctx = canvas.context;
        ctx.fillCircle = function(x, y, radius, fillColor) {
          this.fillStyle = fillColor;
          this.beginPath();
          this.moveTo(x, y);
          this.arc(x, y, radius, 0, Math.PI * 2, false);
          this.fill();
        };
        ctx.clearTo = function(fillColor) {
          ctx.fillStyle = fillColor;
          ctx.fillRect(0, 0, width, height);
        };
        ctx.clearTo(fillColor || "#ddd");
        canvas.node.onmousemove = function(e) {
          var x = e.pageX - this.offsetLeft;
          var y = e.pageY - this.offsetTop;
          var radius = 100; // or whatever
          var fillColor = '#ff0000';
          ctx.globalCompositeOperation = 'destination-out';
          ctx.fillCircle(x, y, radius, fillColor);
        };
        canvas.node.onmousedown = function(e) {
          canvas.isDrawing = true;
        };
      }
    
      var container = document.getElementById('canvas');
      init(container, largeWidth, largeHeight, '#fff');
    
    })();
    body {
      background: blue;
    }
    #canvas {
      margin: -15px;
      filter: blur(10px);
      -webkit-filter: blur(10px);
      position: relative;
    }
    #overlay {
      overflow:hidden;
      position: fixed;
      top: 0px;
      left: 0px;
      z-index: 1;
      filter: unset;
      -webkit-filter: unset;
      }
    <div id="overlay">
     <div id="canvas">
     </div>
    </div>

    【讨论】:

    • 这并没有改变画布周围的透明边缘,它在边缘周围显示蓝色
    • 现在检查它不会删除,而是通过移动边距 -15px 来隐藏。
    • 边缘的蓝色仍然存在,所以它不起作用
    猜你喜欢
    • 1970-01-01
    • 2015-03-18
    • 2021-06-24
    • 2015-10-25
    • 2017-12-28
    • 2019-07-15
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    相关资源
    最近更新 更多