D3自定义曲线:捆绑插值用于区域。

7
考虑这个使用插值的D3JS图表:

D3JS v3, basis interpolation

在D3JS v3中,我可以在区域上使用bundle插值(.interpolate("bundle").tension(0))来实现这种类型的渲染:

D3JS v3, bundle interpolation

请注意,图形的每个部分都与相邻的部分完美配合。这就是我需要的。
使用D3JS v4和v5,bundle插值的语法现在是这样的:.curve(d3.curveBundle)。然而,它现在"旨在与d3.line一起使用,而不是d3.area。" 我最近从v3升级到v5,因此我正在尝试创建一个自定义的bundle曲线,以便也可以与面积一起使用,以保持我在v3中喜欢的插值类型。
我离成功很近。这是我目前所拥有的:

///////////////////// Custom curves.

/** Bundle-ish.
 * Trying to adapt curveBundle for use with areas…
 */
function myBundle(context, beta) {
 this._basis = new d3.curveBasis(context);
 this._beta = beta;

 this._context = context; // temporary. shouldn't be needed for bundle.
}
myBundle.prototype = {

 areaStart: function() {
  this._line = 0;
 },
 areaEnd: function() {
  this._line = NaN;
 },
 lineStart: function() {
  this._x = [];
  this._y = [];
  this._basis.lineStart();
 },
 lineEnd: function() {
  var x = this._x,
    y = this._y,
    j = x.length - 1;

  if (j > 0) {
   var x0 = x[0],
     y0 = y[0],
     dx = x[j] - x0,
     dy = y[j] - y0,
     i = -1,
     t;

   while (++i <= j) {
    t = i / j;
    this._basis.point(
     this._beta * x[i] + (1 - this._beta) * (x0 + t * dx),
     this._beta * y[i] + (1 - this._beta) * (y0 + t * dy)
    );
   }
  }

  this._x = this._y = null;
  this._basis.lineEnd();
 },
 point: function(x, y) {
  this._x.push(+x);
  this._y.push(+y);
  // console.log( this._x.push(+x), this._y.push(+y) );
 }
};
myCurveBundle = (function custom(beta) {
 function myCurveBundle(context) {
  return beta === 1 ? new myBasis(context) : new myBundle(context, beta);
 }

 myCurveBundle.beta = function(beta) {
  return custom(+beta);
 };

 return myCurveBundle;
})(0.85);






///////////////////// The chart.

 var width = 960;
 var height = 540;
 var data = [];
 data.prosody = [116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.578, 125.552, 134.888, 144.225, 153.561, 162.898, 172.235, 181.571, 190.908, 200.244, 209.581, 218.917, 227.715, 218.849, 209.591, 200.333, 191.076, 181.818, 172.560, 163.302, 154.044, 144.787, 135.529, 126.271, 117.013, 107.755, 98.498, 89.240, 97.511, 118.857, 140.202, 161.547, 182.893, 192.100, 188.997, 185.895, 182.792, 179.690, 176.587, 173.485, 170.382, 167.280, 164.177, 161.075, 157.972, 154.870, 151.767, 148.665, 145.562, 142.460, 139.357, 136.255, 133.152, 130.050, 126.947, 124.244, 122.275, 120.307, 118.338, 116.369, 114.400, 112.431, 110.462, 108.493, 106.524, 104.555, 102.586, 100.617, 98.648, 99.659, 101.531, 103.402, 105.273, 107.145, 109.016, 110.887, 112.758, 114.630, 116.501, 118.372, 120.244, 122.115, 123.986, 125.857, 127.729, 129.600, 131.471, 133.343, 135.214, 137.085, 138.956, 140.828, 142.699, 144.570, 146.442, 148.313, 150.184, 149.175, 146.384, 143.594, 140.803, 138.013, 135.222, 132.432, 129.642, 126.851, 124.061, 121.270, 118.480, 115.689, 112.899, 110.109, 107.318, 104.528, 101.737, 98.947, 96.156, 93.366, 90.576, 87.785, 84.995, 82.204, 79.414, 76.623, 0, 0, 0, 0, 0, 0, 76.601, 78.414, 80.227, 82.041, 83.854, 85.667, 87.480, 89.294, 91.107, 92.920, 94.733, 96.547, 98.360, 100.173, 101.986, 103.800, 105.613, 107.426, 109.239, 111.053, 112.866, 114.679, 116.492, 115.917, 114.338, 112.760, 111.181, 109.602, 108.023, 106.444, 104.865, 103.286, 101.707, 100.128, 98.549, 96.970, 95.391, 93.812, 92.233, 90.654, 89.075, 87.534, 88.055, 88.646, 89.237, 89.827, 90.418, 91.009, 91.600, 92.191, 92.782, 93.373, 93.964, 94.555, 95.146, 95.737, 96.328, 96.919, 97.509, 98.100, 98.691, 99.282, 99.873, 100.062, 98.230, 96.399, 94.567, 92.736, 90.904, 89.072, 87.241, 85.409, 83.578, 81.746, 79.914, 78.083, 78.839, 80.880, 82.922, 84.964, 87.006, 89.048, 91.090, 93.132, 95.174, 97.216, 99.257, 101.299, 103.341, 105.383, 107.425, 109.467, 111.509, 113.551, 112.633, 110.755, 108.877, 106.999, 105.121, 103.243, 101.365, 99.487, 97.609, 95.731, 93.853, 91.975, 90.097, 88.219, 86.341, 84.463, 82.585, 80.707, 78.829, 76.951, 78.067, 81.290, 84.513, 87.736, 90.958, 94.181, 97.404, 100.627, 103.849, 107.072, 110.295, 113.517, 116.740, 119.963, 123.186, 126.408, 129.631, 132.854, 136.077, 139.299, 142.522, 145.745, 148.968, 152.190, 155.413, 154.840, 152.899, 150.958, 149.017, 147.076, 145.135, 143.194, 141.253, 139.312, 137.371, 135.429, 133.488, 131.547, 129.606, 127.665, 125.724, 124.874, 126.734, 128.594, 130.454, 132.314, 134.174, 136.034, 137.894, 139.754, 141.614, 143.474, 145.334, 147.194, 149.054, 150.914, 152.774, 154.634, 156.494, 158.354, 160.214, 162.074, 163.934, 165.664, 161.795, 157.761, 153.726, 149.692, 145.658, 141.624, 137.589, 133.555, 129.521, 125.487, 121.452, 117.418, 113.384, 109.350, 105.316, 101.281, 97.247, 93.213, 89.179, 85.144, 81.110, 77.076, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
 data.TextGrid = {  "phone" : [ /** segment type, beginning, and end of each segment **/ [ "sp", 0.0124716553288, 0.271882086168 ], [ "M", 0.271882086168, 0.401587301587 ], [ "OW", 0.401587301587, 0.521315192744 ], [ "S", 0.521315192744, 0.660997732426 ], [ "T", 0.660997732426, 0.710884353741 ], [ "AH", 0.710884353741, 0.760770975057 ], [ "V", 0.760770975057, 0.820634920635 ], [ "DH", 0.820634920635, 0.860544217687 ], [ "IY", 0.860544217687, 0.940362811791 ], [ "AH", 0.940362811791, 0.980272108844 ], [ "D", 0.980272108844, 1.04013605442 ], [ "V", 1.04013605442, 1.10997732426 ], [ "EH", 1.10997732426, 1.21972789116 ], [ "N", 1.21972789116, 1.289569161 ], [ "CH", 1.289569161, 1.42925170068 ], [ "ER", 1.42925170068, 1.51904761905 ], [ "Z", 1.51904761905, 1.57891156463 ], [ "R", 1.57891156463, 1.66870748299 ], [ "AH", 1.66870748299, 1.69863945578 ], [ "K", 1.69863945578, 1.75850340136 ], [ "AO", 1.75850340136, 1.88820861678 ], [ "R", 1.88820861678, 1.91814058957 ], [ "D", 1.91814058957, 1.95804988662 ], [ "AH", 1.95804988662, 1.99795918367 ], [ "D", 1.99795918367, 2.07777777778 ], [ "AH", 2.07777777778, 2.10770975057 ], [ "N", 2.10770975057, 2.18752834467 ], [ "DH", 2.18752834467, 2.22743764172 ], [ "AH", 2.22743764172, 2.2873015873 ], [ "S", 2.2873015873, 2.42698412698 ], [ "B", 2.42698412698, 2.51678004535 ], [ "UH", 2.51678004535, 2.68639455782 ], [ "K", 2.68639455782, 2.79614512472 ], [ "sp", 2.79614512472, 2.81609977324 ], [ "R", 2.81609977324, 2.95578231293 ], [ "IY", 2.95578231293, 3.00566893424 ], [ "L", 3.00566893424, 3.09546485261 ], [ "IY", 3.09546485261, 3.23514739229 ], [ "AH", 3.23514739229, 3.27505668934 ], [ "K", 3.27505668934, 3.41473922902 ], [ "ER", 3.41473922902, 3.68412698413 ], [ "D", 3.68412698413, 3.75396825397 ], [ "sp", 3.75396825397, 4.01337868481 ] ] }


 /**
  * Set up D3JS
  */
 var x = d3.scaleLinear()
  .domain([0, 401])
  .range([0, width]);
 var y = d3.scaleLinear()
  .domain([0, 800])
  .range([height, 0]);

 /** Center the stream vertically **/
 var shift = d3.scaleLinear()
  .domain([0, 0])
  .range([-height/2, 0]);

 /** Draw a stream segment **/
 var pathGenerator = d3.area()
  .curve( myCurveBundle.beta(0) )
  .x(function(d, i) { return x(i); })
  .y1(function(d) { return y(d + 72 ); }) /** 72 is just some arbitrary thickess given to the graph **/
  .y0(function(d) { return y(d); });

 var svg = d3.select("body").append("svg")
  .attr("width", width)
  .attr("height", height);



 /**
  * Render the chart
  */
 
 /** Draw the stream, on a per-segment basis **/
 var path = svg.selectAll("path")
  .data(data.TextGrid.phone)
  .enter().append("path")
   .attr("transform", function(d, i) { return "translate(" + x(Math.floor(d[1]*100)) + ", " + shift(i) + ")"; })
   .attr("class", function(d) { return "segment " + d[0]; })
   .on('click', function(d, i) { playFromTo(Math.floor(d[1] * 1000), Math.floor(d[2] * 1000)); })
   .attr("d", function(d) { return pathGenerator(data.prosody.slice( Math.floor(d[1]*100), Math.floor(d[2]*100)+1)); });
.segment { fill: #ccc; }
.segment.sp { display: none; }

/** Adapted from Margaret Horrigan for American English **/
.segment.IY { fill: #7AC141; }
.segment.IH { fill: #F9C5DC; }
.segment.UH { fill: #FF00FF; }
.segment.UW { fill: #0153A5; }
.segment.EY { fill: #8B8C90; }
.segment.EH { fill: #E61A25; }
.segment.AX { fill: #DF5435; }
.segment.ER { fill: #805EAA; }
.segment.AO { fill: #E2A856; }
.segment.OY { fill: #2E3094; }
.segment.OW { fill: #FC2B1C; }
.segment.AE { fill: #21201E; }
.segment.AH { fill: #DF5435; }
.segment.AA { fill: #bf181f; }
.segment.AY { fill: #FFFFFF; }
.segment.AW { fill: #7C4540; }
<script src="https://cdn.jsdelivr.net/npm/d3@5.4.0/dist/d3.min.js"></script>

(The bundle code is adapted from bundle.js in d3-shape.)
我非常接近了:如果您检查SVG,您会发现即使没有显示任何内容,路径实际上确实被创建了。
如果您查看第一个“可见”段落(类segment M),您会发现它在中间包含一个move命令:
M31.122194513715712,398.532825

如果我将它重命名为行命令,就像这样:
L31.122194513715712,398.532825

如果那个部分被选中,那么该段将显示出来。
我不确定自定义曲线的哪个部分负责这个。如何把M变成L?
生成的路径也缺少最后的Z。我该如何处理?
在D3JS中,关于自定义曲线的帮助很少。欢迎任何帮助。

1
为了帮助你,我们能否也在d3js问题跟踪器上提交此问题?他们可能已经收到过此类问题,并且有些人可能不使用stackoverflow,但是对d3做出贡献的人可能知道已知的解决方案。 - Mike 'Pomax' Kamermans
1
我最终在此相关主题的线程上发布了一条评论:https://github.com/d3/d3-shape/issues/70 - Fabien Snauwaert
感谢您发表评论 - 我也很想知道为什么被排除了。 - Steve
1个回答

3

调用 areaStartareaEnd

看起来你已经从 d3.curveBasis 中复制了 areaStartareaEnd 函数到你的自定义曲线中,该曲线主要是从 d3.curveBundle 绘制而成。

你不能简单地将代码从 d3.curveBasis 复制到 d3.curveBundle 中,因为 this 指向不同的东西。 this._basis(d3.curveBasis 的实例)无法访问 this._lineareaStartareaEnd 所需的变量,并可通过你的 customBundle 访问)。

你可以将 this._line 更改为 this._basis._line,但如果你注意到,d3.curveBundle 中的所有线函数都调用它们各自的 this._basis 函数(例如,lineStart 调用 this._basis.lineStart())。如果你在这里也这样做,应该是等效的:

areaStart: {
    // this._basis._line = 0; // this should work, for now
    this._basis.areaStart(); // but this makes more sense semantically
},
areaEnd: {
    // this._basis._line = NaN; // this should work, for now
    this._basis.areaEnd(); // but this makes more sense semantically
}

以这种方式进行操作的附加好处是,如果d3.curveBasis在将来更改其实现方式,则这样做更有可能兼容。
无需使用 new
顺便说一下,在构造函数中,您可以使用 new 运算符创建 this._basis 的新实例。
this._basis = new d3.curveBasis(context);
< p > Basis 构造函数在 d3 模块内部通过 new 使用,但在捆绑库中,它是一个功能构造函数。它可以简单地写成:

this._basis = d3.curveBasis(context);

尽管使用new似乎没有破坏任何东西。有关更多信息,请参见https://dev59.com/PWox5IYBdhLWcg3wDgIz#9468106

您是否应该使用曲线包束来呈现区域?

正如您所指出的,d3.curveBundle“旨在与d3.line一起使用,而不是d3.area。” 值得问一下,您是否应该使用curveBundle来呈现区域,因为此省略似乎是故意的。 @mbostock在https://github.com/d3/d3-shape/issues/70中写道:

正确的,d3.curveBundle只打算与d3.line一起使用。它用于分层边缘捆绑,而不是用于呈现区域。

还可以参见https://github.com/d3/d3-shape#curveBundle

您应该将curveBundle与其他插值方法进行比较,以查看是否使用它会以误导性的方式扭曲您的区域。

结果:

所有更改都可以在此fiddle中看到:https://jsfiddle.net/g4ya2qso/

或者:

或者,由于功能与d3.curveBundle如此相似,因此您可以添加.areaStart.areaEnd方法,并省略所有其他自定义代码,如下所示:

var myCurveBundle = (function custom(beta) {
    function myCustomBundle(context) {
      var bundle = d3.curveBundle.beta(beta)(context);
      bundle.areaStart = function () {
        bundle._basis.areaStart();
      };
      bundle.areaEnd = function () {
        bundle._basis.areaEnd();
      };
      return bundle;
    }
    myCustomBundle.beta = function(newBeta) {
      return custom(+newBeta);
    };
    return myCustomBundle;
})(0.85);

///////////////////// Custom curves.

/** Bundle-ish.
 * Trying to adapt curveBundle for use with areas…
 */
var myCurveBundle = (function custom(beta) {
  function myCustomBundle(context) {
    var bundle = d3.curveBundle.beta(beta)(context);
    bundle.areaStart = function () {
      bundle._basis.areaStart();
    };
    bundle.areaEnd = function () {
      bundle._basis.areaEnd();
    };
    return bundle;
  }
  myCustomBundle.beta = function(newBeta) {
    return custom(+newBeta);
  };
  return myCustomBundle;
})(0.85);

///////////////////// The chart.

 var width = 960;
 var height = 540;
 var data = [];
 data.prosody = [116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.473, 116.578, 125.552, 134.888, 144.225, 153.561, 162.898, 172.235, 181.571, 190.908, 200.244, 209.581, 218.917, 227.715, 218.849, 209.591, 200.333, 191.076, 181.818, 172.560, 163.302, 154.044, 144.787, 135.529, 126.271, 117.013, 107.755, 98.498, 89.240, 97.511, 118.857, 140.202, 161.547, 182.893, 192.100, 188.997, 185.895, 182.792, 179.690, 176.587, 173.485, 170.382, 167.280, 164.177, 161.075, 157.972, 154.870, 151.767, 148.665, 145.562, 142.460, 139.357, 136.255, 133.152, 130.050, 126.947, 124.244, 122.275, 120.307, 118.338, 116.369, 114.400, 112.431, 110.462, 108.493, 106.524, 104.555, 102.586, 100.617, 98.648, 99.659, 101.531, 103.402, 105.273, 107.145, 109.016, 110.887, 112.758, 114.630, 116.501, 118.372, 120.244, 122.115, 123.986, 125.857, 127.729, 129.600, 131.471, 133.343, 135.214, 137.085, 138.956, 140.828, 142.699, 144.570, 146.442, 148.313, 150.184, 149.175, 146.384, 143.594, 140.803, 138.013, 135.222, 132.432, 129.642, 126.851, 124.061, 121.270, 118.480, 115.689, 112.899, 110.109, 107.318, 104.528, 101.737, 98.947, 96.156, 93.366, 90.576, 87.785, 84.995, 82.204, 79.414, 76.623, 0, 0, 0, 0, 0, 0, 76.601, 78.414, 80.227, 82.041, 83.854, 85.667, 87.480, 89.294, 91.107, 92.920, 94.733, 96.547, 98.360, 100.173, 101.986, 103.800, 105.613, 107.426, 109.239, 111.053, 112.866, 114.679, 116.492, 115.917, 114.338, 112.760, 111.181, 109.602, 108.023, 106.444, 104.865, 103.286, 101.707, 100.128, 98.549, 96.970, 95.391, 93.812, 92.233, 90.654, 89.075, 87.534, 88.055, 88.646, 89.237, 89.827, 90.418, 91.009, 91.600, 92.191, 92.782, 93.373, 93.964, 94.555, 95.146, 95.737, 96.328, 96.919, 97.509, 98.100, 98.691, 99.282, 99.873, 100.062, 98.230, 96.399, 94.567, 92.736, 90.904, 89.072, 87.241, 85.409, 83.578, 81.746, 79.914, 78.083, 78.839, 80.880, 82.922, 84.964, 87.006, 89.048, 91.090, 93.132, 95.174, 97.216, 99.257, 101.299, 103.341, 105.383, 107.425, 109.467, 111.509, 113.551, 112.633, 110.755, 108.877, 106.999, 105.121, 103.243, 101.365, 99.487, 97.609, 95.731, 93.853, 91.975, 90.097, 88.219, 86.341, 84.463, 82.585, 80.707, 78.829, 76.951, 78.067, 81.290, 84.513, 87.736, 90.958, 94.181, 97.404, 100.627, 103.849, 107.072, 110.295, 113.517, 116.740, 119.963, 123.186, 126.408, 129.631, 132.854, 136.077, 139.299, 142.522, 145.745, 148.968, 152.190, 155.413, 154.840, 152.899, 150.958, 149.017, 147.076, 145.135, 143.194, 141.253, 139.312, 137.371, 135.429, 133.488, 131.547, 129.606, 127.665, 125.724, 124.874, 126.734, 128.594, 130.454, 132.314, 134.174, 136.034, 137.894, 139.754, 141.614, 143.474, 145.334, 147.194, 149.054, 150.914, 152.774, 154.634, 156.494, 158.354, 160.214, 162.074, 163.934, 165.664, 161.795, 157.761, 153.726, 149.692, 145.658, 141.624, 137.589, 133.555, 129.521, 125.487, 121.452, 117.418, 113.384, 109.350, 105.316, 101.281, 97.247, 93.213, 89.179, 85.144, 81.110, 77.076, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
 data.TextGrid = {  "phone" : [ /** segment type, beginning, and end of each segment **/ [ "sp", 0.0124716553288, 0.271882086168 ], [ "M", 0.271882086168, 0.401587301587 ], [ "OW", 0.401587301587, 0.521315192744 ], [ "S", 0.521315192744, 0.660997732426 ], [ "T", 0.660997732426, 0.710884353741 ], [ "AH", 0.710884353741, 0.760770975057 ], [ "V", 0.760770975057, 0.820634920635 ], [ "DH", 0.820634920635, 0.860544217687 ], [ "IY", 0.860544217687, 0.940362811791 ], [ "AH", 0.940362811791, 0.980272108844 ], [ "D", 0.980272108844, 1.04013605442 ], [ "V", 1.04013605442, 1.10997732426 ], [ "EH", 1.10997732426, 1.21972789116 ], [ "N", 1.21972789116, 1.289569161 ], [ "CH", 1.289569161, 1.42925170068 ], [ "ER", 1.42925170068, 1.51904761905 ], [ "Z", 1.51904761905, 1.57891156463 ], [ "R", 1.57891156463, 1.66870748299 ], [ "AH", 1.66870748299, 1.69863945578 ], [ "K", 1.69863945578, 1.75850340136 ], [ "AO", 1.75850340136, 1.88820861678 ], [ "R", 1.88820861678, 1.91814058957 ], [ "D", 1.91814058957, 1.95804988662 ], [ "AH", 1.95804988662, 1.99795918367 ], [ "D", 1.99795918367, 2.07777777778 ], [ "AH", 2.07777777778, 2.10770975057 ], [ "N", 2.10770975057, 2.18752834467 ], [ "DH", 2.18752834467, 2.22743764172 ], [ "AH", 2.22743764172, 2.2873015873 ], [ "S", 2.2873015873, 2.42698412698 ], [ "B", 2.42698412698, 2.51678004535 ], [ "UH", 2.51678004535, 2.68639455782 ], [ "K", 2.68639455782, 2.79614512472 ], [ "sp", 2.79614512472, 2.81609977324 ], [ "R", 2.81609977324, 2.95578231293 ], [ "IY", 2.95578231293, 3.00566893424 ], [ "L", 3.00566893424, 3.09546485261 ], [ "IY", 3.09546485261, 3.23514739229 ], [ "AH", 3.23514739229, 3.27505668934 ], [ "K", 3.27505668934, 3.41473922902 ], [ "ER", 3.41473922902, 3.68412698413 ], [ "D", 3.68412698413, 3.75396825397 ], [ "sp", 3.75396825397, 4.01337868481 ] ] }

 /**
  * Set up D3JS
  */
 var x = d3.scaleLinear()
  .domain([0, 401])
  .range([0, width]);
 var y = d3.scaleLinear()
  .domain([0, 800])
  .range([height, 0]);

 /** Center the stream vertically **/
 var shift = d3.scaleLinear()
  .domain([0, 0])
  .range([-height/2, 0]);

 /** Draw a stream segment **/
 var pathGenerator = d3.area()
  .curve( myCurveBundle.beta(0) )
  .x(function(d, i) { return x(i); })
  .y1(function(d) { return y(d + 72 ); }) /** 72 is just some arbitrary thickess given to the graph **/
  .y0(function(d) { return y(d); });

 var svg = d3.select("body").append("svg")
  .attr("width", width)
  .attr("height", height);

 /**
  * Render the chart
  */
 
 /** Draw the stream, on a per-segment basis **/
 var path = svg.selectAll("path")
  .data(data.TextGrid.phone)
  .enter().append("path")
   .attr("transform", function(d, i) { return "translate(" + x(Math.floor(d[1]*100)) + ", " + shift(i) + ")"; })
   .attr("class", function(d) { return "segment " + d[0]; })
   .on('click', function(d, i) { playFromTo(Math.floor(d[1] * 1000), Math.floor(d[2] * 1000)); })
   .attr("d", function(d) { return pathGenerator(data.prosody.slice( Math.floor(d[1]*100), Math.floor(d[2]*100)+1)); });
.segment { fill: #ccc; }
.segment.sp { display: none; }

/** Adapted from Margaret Horrigan for American English **/
.segment.IY { fill: #7AC141; }
.segment.IH { fill: #F9C5DC; }
.segment.UH { fill: #FF00FF; }
.segment.UW { fill: #0153A5; }
.segment.EY { fill: #8B8C90; }
.segment.EH { fill: #E61A25; }
.segment.AX { fill: #DF5435; }
.segment.ER { fill: #805EAA; }
.segment.AO { fill: #E2A856; }
.segment.OY { fill: #2E3094; }
.segment.OW { fill: #FC2B1C; }
.segment.AE { fill: #21201E; }
.segment.AH { fill: #DF5435; }
.segment.AA { fill: #bf181f; }
.segment.AY { fill: #FFFFFF; }
.segment.AW { fill: #7C4540; }
<script src="https://cdn.jsdelivr.net/npm/d3@5.4.0/dist/d3.min.js"></script>


谢谢,这非常有帮助并澄清了一些事情;感谢提供更短的替代方案。 - Fabien Snauwaert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接