使用D3动态生成设计的有机形状吗?

时间:2019-04-09 14:55:43

标签: javascript d3.js svg graphics

当我在为另一个项目使用d3雷达图时,我注意到当在极线上使用基本插值时,我得到了非常平滑的曲线,类似于有机形状,我想知道该如何解决?用D3.js做到这一点我想要的形状是:

enter image description here

1 个答案:

答案 0 :(得分:2)

像这样吗? =)

example img

card('https://i.stack.imgur.com/EK1my.png?s=128')
card('https://i.stack.imgur.com/EK1my.png?s=128')
card('https://i.stack.imgur.com/EK1my.png?s=128')

function card(url) {

  let s = 500;            // size
  let step = 100;         // x-axis step
  let range = [-50, 50];  // y-axis range
    
  // add new svg to document.body with origin at 0  
  let svg = d3.select('body')
              .append('svg')
              .attr('viewBox', `0 0 ${s} ${s}`);

  // interpolation algorithm for points used to form masking shape
  let line = d3.line()
               .curve(d3.curveCardinalClosed);

  // random values generator function
  let rnd = d3.randomUniform.apply(0, range);
  
  // image goes first
  svg.append("svg:image")
     .attr('mask', 'url(#mask)')
     .attr('width', s)
     .attr('height', s)
     .attr("xlink:href", url)

  // here i place points with fixed `step` by `x` axis  
  // and random value in `range` by `y` axis
  // which forms the "original path"
  let pts = d3.range(-1, s/step+2).map(i => [i*step, rnd()]);

  // shift points down from "original path", 
  // amount of shift depends from point index 
  let pts1 = pts.map((p, i) => [
      p[0], p[1] + s*0.3 - i*s*0.08
  ]);
  
  // reverse order of original and shift points down on 
  // bigger values, depending from point index
  let pts2 = pts.reverse().map((p, i) => [
      p[0], p[1] + s*0.8 - i*s*0.03
  ]);

  // forming single interpolated path for all 
  // points from prev steps concatenated in single array
  let d = line(pts2.concat(pts1));
  
  // append rect sized as viewport with hole formed by interpolated path
  // with random color from hsl palette and opacity 0.9
  svg.append('path')
     .attr('opacity', 0.9)
     .attr('fill', `hsl(${Math.random()*255}, 55%, 55%)`)
     .attr('d', `M0,0 v${s} h${s} v${-s} z ${d}`)
}
svg {
    height: 150px;
    margin: 10px;
    box-shadow: 0 2px 10px 2px lightgray;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>