CSS引用单独元素中的SVG过滤器

时间:2016-08-23 09:06:11

标签: css svg svg-filters

使用SVG过滤器,我遇到了一个从CSS引用SVG过滤器的问题。在某些情况下,应用过滤器将从页面中删除应用过滤器的元素。我认为可能有两个原因:

  1. 我使用D3JS;
  2. 动态添加过滤器
  3. 我在CSS中引用过滤器,在单独的文件中定义。
  4. 为了测试这一点,我创建了一个MWE来演示这个问题。对我来说,这在Firefox和Chrome中呈现左框中没有任何内容,右框中没有灰色圆圈(预期结果)。我认为这可以消除原因1。在我这样做之后,我尝试了:

    1. 使用url(.#filter-id)引用,因此使用前导点。这并没有改变结果。
    2. defs移动到圈子所在的svg元素中。这个fixes问题。
    3. 我的问题:是否仍然可以以某种方式引用在单独的SVG元素中定义的过滤器?我非常希望在我的应用程序中这样做。我have read外部文件有问题,但是同一个文件中的不同元素肯定是可能的吗?

1 个答案:

答案 0 :(得分:1)

我认为问题是display:none类中的hidden,您可以使用其他隐藏方式,例如:

svg.hidden {
  height:0;
  margin:0;
  border:none;
}

var svg = d3.select('#container').append('svg'),
    defs = svg.append('defs'),
    dsFilter;

svg.attr('width', 400).attr('height', 200);

dsFilter = defs.append('filter').attr('id', 'grayscale-d3')
dsFilter.append('feColorMatrix')
  .attr('type', 'matrix')
  .attr('values',
        '0.3333 0.3333 0.3333 0 0 ' +
        '0.3333 0.3333 0.3333 0 0 ' +
        '0.3333 0.3333 0.3333 0 0 ' +
        '0      0      0      1 0')

svg.append('text').attr('x', 2).attr('y', 2).text('appended by D3');
svg.append('circle').attr('class', 'd3').attr('cx', 200).attr('cy', 120).attr('r', 60);
body {
  margin: 0;
  font-size: 0;
}

circle {
  fill: #bada55;
  stroke: #000;
  stroke-width: 1px;
}
circle.of {
  filter: url('#grayscale-of');
}
circle.d3 {
  filter: url('#grayscale-d3');
}

svg {
  display: inline-block;
  margin: 1rem 0 0 1rem;
  border: 1px solid #000;
}
svg.hidden {
  height:0;
  margin:0;  
  border:none;
}

text {
  dominant-baseline: text-before-edge;
  font-size: 1rem;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<svg class="hidden">
  <defs>
    <filter id="grayscale-of">
      <feColorMatrix values="0.3333 0.3333 0.3333 0 0
                             0.3333 0.3333 0.3333 0 0
                             0.3333 0.3333 0.3333 0 0
                             0      0      0      1 0"
                     type="matrix">
      </feColorMatrix>
    </filter>
  </defs>
</svg>
<div id="container">
  <svg width="400" height="200">
    <text x="2" y="2">already in page</text>
    <circle class="of" cx="200" cy="120" r="60" />
  </svg>
</div>