lucky1928
lucky1928

Reputation: 8935

d3.js - svg filter equivalent with d3.js

I got below svg filter from svg file:

   <defs>
      <filter height="300%" id="blurfilter" width="300%" x="-1" y="-1">
         <feGaussianBlur result="blurOut" stdDeviation="2.0" />
         <feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0" />
         <feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3" />
         <feBlend in="SourceGraphic" in2="blurOut3" mode="normal" />
      </filter>
   </defs>

What's the correct way to implement it with d3.js?

I try below code but it looks like not correct:

 svg.append('defs')
    .append('filter')
    .attr('width','300%')
    .attr('id','blurfilter')
    .attr('x',-1)
    .attr('y',-1)
    .append('feGaussianBlur')
    .attr('result','blurOut')
    .attr('stdDeviation',2.0)
    .append('feColorMatrix')
    .attr('id','blurOut')
    .attr('result','blurOut2')
    .attr('type','matrix')
    .attr('values','0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0')
    .append('feOffset')
    .attr('dx',4.0)
    .attr('dy',4.0)
    .attr('in','blurOut2')
    .attr('result','blurOut3')
    .append('feBlend')
    .attr('in','SourceGraphic')
    .attr('in2','blurOut3')
    .attr('mode','normal')

Upvotes: 5

Views: 392

Answers (1)

Andrew Reid
Andrew Reid

Reputation: 38221

You need to break the chain, currently you are appending as follows:

 svg.append('defs')
    .append('filter')
    ...
    .append('feGaussianBlur')
    ...
    .append('feColorMatrix')
    ...
    .append('feOffset')
    ...
    .append('feBlend')

Each time you use .append() you return a new selection of the append element(s). So you're appending a feBlend element to a parent feOffset element, not the filter itself. Eg:

   <defs>
      <filter height="300%" id="blurfilter" width="300%" x="-1" y="-1">
         <feGaussianBlur result="blurOut" stdDeviation="2.0">
             <feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0" >
                 <feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3" >
                     <feBlend in="SourceGraphic" in2="blurOut3" mode="normal" />
                 </feOffset>
              </feColorMatrix>
          </feGaussianBlur>
      </filter>
   </defs>

Instead, break the chains and append to a selection of the filter:

var filter = svg.append('defs')
  .append('filter')
  .attr(...

filter.append('feGaussianBlur')
  .attr(...

filter.append('feColorMatrix')
  .attr(...

filter.append('feOffset')
   .attr(...

filter.append('feBlend')
   .attr(...

Which will give you a DOM structure the same as your example.

Upvotes: 5

Related Questions