为许多 D3 力模拟节点添加投影



我有一个 D3 v4 力模拟,里面有 100 个节点。每个节点都是一个图像,我想为每个图像添加一个投影,但是,我认为由于我渲染投影的方式,这不会缩放。对于 100 张没有投影的图像,它运行 60fps,但投影更像是 8fps。有没有一个黑客解决方案,或者有更好的方法来做到这一点。这是我现在所拥有的(在图像后面的圆圈上渲染(:

var dropShadowFilter = this.d3Graph.append('svg:filter')
  .attr('id', 'drop-shadow')
  .attr('filterUnits', "userSpaceOnUse")
  .attr('width', '250%')
  .attr('height', '250%');
dropShadowFilter.append('svg:feGaussianBlur')
  .attr('in', 'SourceGraphic')
  .attr('stdDeviation', 2)
  .attr('result', 'blur-out');
dropShadowFilter.append('svg:feColorMatrix')
  .attr('in', 'blur-out')
  .attr('type', 'hueRotate')
  .attr('values', 180)
  .attr('result', 'color-out');
dropShadowFilter.append('svg:feOffset')
  .attr('in', 'color-out')
  .attr('dx', 3)
  .attr('dy', 3)
  .attr('result', 'the-shadow');
dropShadowFilter.append('svg:feBlend')
  .attr('in', 'SourceGraphic')
  .attr('in2', 'the-shadow')
  .attr('mode', 'normal');

this.node = this.d3Graph.selectAll(null)
   .data(Nodes)
   .enter()
   .append("g")
   .attr("class", "nodes");
this.node.append("circle")
    .attr("r", 30)
    .attr("fill", "red")
    .style("filter", "url(#drop-shadow)")

如果您愿意自己完成更多繁重的工作,那么您可以考虑通过在每个项目后面添加节点并适当地缩放、定位和着色来近似于简单形状的投影。

在下面的示例中,我创建了一个额外的圆,它略大且偏离顶层圆。它还应用了自定义fake-shadow径向渐变。

var d3Graph = d3.select('svg')
var dropShadowFilter = d3Graph.append('svg:filter')
  .attr('id', 'drop-shadow')
  .attr('filterUnits', "userSpaceOnUse")
  .attr('width', '250%')
  .attr('height', '250%');
dropShadowFilter.append('svg:feGaussianBlur')
  .attr('in', 'SourceGraphic')
  .attr('stdDeviation', 2)
  .attr('result', 'blur-out');
dropShadowFilter.append('svg:feColorMatrix')
  .attr('in', 'blur-out')
  .attr('type', 'hueRotate')
  .attr('values', 180)
  .attr('result', 'color-out');
dropShadowFilter.append('svg:feOffset')
  .attr('in', 'color-out')
  .attr('dx', 3)
  .attr('dy', 3)
  .attr('result', 'the-shadow');
dropShadowFilter.append('svg:feBlend')
  .attr('in', 'SourceGraphic')
  .attr('in2', 'the-shadow')
  .attr('mode', 'normal');
var simpleGradient = d3Graph.append('defs')
  .append('radialGradient')
  .attr('id', 'fake-shadow');
simpleGradient.append('stop')
  .attr('offset', "80%")
  .attr('stop-color', '#01AFAF');
simpleGradient.append('stop')
  .attr('offset', "100%")
  .attr('stop-color', "#01AFAF00");
body {
  background: papayawhip
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg height="120" width="600" text-anchor="middle">
<text x="200" y="105">Original</text>
<text x="400" y="105">Fake Shadow</text>
<circle cx="200" cy="50" r="30" filter="url(#drop-shadow)" fill="red"/>
<circle cx="403" cy="53" r="32.5" fill="url(#fake-shadow)"/>
<circle cx="400" cy="50" r="30" fill="red"/>
</svg>

最新更新