SVG位移图过滤器

时间:2017-05-12 17:48:15

标签: javascript css svg filter mapping

我试图在我的SVG中实现fisheye-esque过滤器并找到此codepen:  http://codepen.io/johanberonius/pen/RopjYW

它完全正常,但我希望这个效果略微变得更难,但我无法改变置换贴图,因为它是在js中生成的。

var canvas = document.getElementById('canvas'),
        barrel = document.getElementById('filter-image'),
        width = canvas.width,
        height = canvas.height,
        ctx = canvas.getContext('2d');

    for (var y = 0; y < height; y++) {
        for (var x = 0; x < width; x++) {
            var dx = x - 128,
                dy = y - 128,
                l = Math.sqrt(dx * dx + dy * dy),
                a = l < 128 ? Math.asin(l/128) : 0,
                z = l < 128 ? 255 - Math.cos(a) * 255 : 0,
                r = l < 128 ? 128 + (dx / 128) * (z / 255) * 128 : 0,
                g = l < 128 ? 128 + (dy / 128) * (z / 255) * 128 : 0,
                o = l >= 124 ? Math.max(0, 1 - (l-124)/4) : 1;

            ctx.fillStyle = 'rgba('+Math.floor(r)+','+Math.floor(g)+',0,'+o+')';
            ctx.fillRect(x,y,1,1);
        }
    }

    barrel.setAttribute('xlink:href', canvas.toDataURL());

    var tx = 0,
        ty = 0;
    requestAnimationFrame(function updateAnimationFrame() {
        tx += 0.027;
        ty += 0.031;
        barrel.setAttribute('x', 128 + Math.sin(tx) * 120);
        barrel.setAttribute('y', 128 + Math.cos(ty) * 120);
        requestAnimationFrame(updateAnimationFrame);
    });
对于我来说,公式太先进了。 所以我想知道是否有任何方法可以生成这些类型的地图,或者有人可以帮助我使用公式。

1 个答案:

答案 0 :(得分:0)

位移图可以,至少大致相当,可以构造为SVG过滤器本身。

因此,您可能会认为您可以在一个SVG文件中将置换贴图及其应用程序的绘图组合到图像中。事实证明你不能,因为浏览器没有实现enable-background

但是,分布在两个文件中,它可以工作。首先是位移图:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
     version="1.1" height="300" width="300">
  <defs>
    <filter id="barrel" x="-30%" y="-30%" width="160%" height="160%"
            color-interpolation-filters="sRGB">
      <feGaussianBlur result="result1" stdDeviation="10" />
      <feMorphology operator="erode" radius="5" result="result5"  />
      <feColorMatrix result="result3" type="matrix"
           values="0 0 0 -0.3 0.8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 " />
      <feOffset result="result4" dy="-5" dx="5" />
      <feColorMatrix result="result2" in="result5" type="matrix"
           values="0 0 0 0 0 0 0 0 -0.3 0.8 0 0 0 0 0 0 0 0 0 1 " />
      <feOffset dy="5" dx="-5" />
      <feComposite result="result6" k3="1" k2="1" operator="arithmetic" in2="result4" />
    </filter>
    <clipPath id="cp" clipPathUnits="userSpaceOnUse">
      <circle r="100" cx="150" cy="150" />
    </clipPath>
  </defs>
  <circle clip-path="url(#cp)" filter="url(#barrel)"
          cy="150" cx="150" r="100" />
</svg>

其次,对图像的应用:

<svg width="512" height="512" viewBox="0 0 512 512"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">

  <defs>
    <filter id="barrel">
      <feImage id="filter-image" xlink:href="circle.svg" result="barrel"
               x="64" y="64" width="256" height="256" />
      <feDisplacementMap in2="barrel" in="SourceGraphic"
               xChannelSelector="R" yChannelSelector="G" scale="64" />
      <feComposite operator="in" in2="barrel"/>
    </filter>
  </defs>

  <image xlink:href="https://i.imgsafe.org/3353aef52f.jpg"
         x="0" y="0" height="512" width="512"/>
  <image xlink:href="https://i.imgsafe.org/3353aef52f.jpg"
         x="-16" y="-16" height="512" width="512" filter="url(#barrel)"/>
</svg>

我使用Inkscape Filter编辑器生成了这个,它为操作过滤器组件提供了一个公平的接口。您可能应该尝试更多。要玩的数字可能是:

  • feGaussianBlur模糊半径 - 彩色边框的宽度,这将是我所说的第一个候选人&#34;锐度&#34;
  • feMorphology侵蚀半径应该总是模糊半径值的一半
  • feOffset dx / dy相对于彼此替换红色和绿色组件
  • feColorMatrix那些不为零的数字可以变化。查看过滤器编辑器以获得解释。