繁体   English   中英

如何将 dc.js 与 d3 地平线图集成以进行数据渲染?

[英]How to integrate dc.js with d3 horizon chart for data rendering?

此 dc.js示例显示了一个折线图 ( source )。 我想知道如何使用d3-horizo​​n-chart示例源)用一组地平线图替换它的一个 focusChart?

这里(JSFiddle 代码示例)是我卡住的地方 - 它在直流图表上没有显示数据......请帮助=(

 class dcHorizonChart { constructor(parent, groupByKeyName, valueKeyName, group ) { this.data = null; this.height = 30 this._groupByKeyIdx = groupByKeyName; this._valueKeyName = valueKeyName; this._root = d3.select(parent); dc.registerChart(this, group); } groupAll(groupAll) { console.log("gac") if(!arguments.length) return this._groupAll; this._groupAll = groupAll; return this; } setData(data) { this.data = data } render() { console.log("called once"); this.redraw(); } redraw() { // console.log(this.data.all()) //console.log(this.data.all()) var ndata = Enumerable.From(this.data.all()).Select("r=> { 'name': r.key["+this._groupByKeyIdx+"], 'val': r.key["+this._valueKeyName + "]}"); ndata = ndata.GroupBy("$.name", "$.val" ).Select("{'id': $.Key(), 'values':$.ToArray()}") .ToArray(); console.log(ndata) this._root.html(null) this._root.selectAll('.horizon') .data(ndata) .enter() .append('div') .attr('class', 'horizon') .each(function(d) { d3.horizonChart() .title(d.id) .call(this, d.values); }); console.log("called"); /* d3.select('body').selectAll('.horizon') .data(stocks) .enter() .append('div') .attr('class', 'horizon') .each(function(d) { d3.horizonChart() .title(d.stock) .call(this, d.values); }); this._rect.transition() .duration(this._duration) .attr('fill', this._colors(this._groupAll.value())); */ } } function loadStockData(stock, callback) { d3.csv('https://bost.ocks.org/mike/cubism/intro/stocks/' + stock + '.csv').then(function(rows) { rows = rows.map(function(d) { return [d3.timeParse(d.Date), +d.Open]; }).filter(function(d) { return d[1]; }).reverse(); var date = rows[0][0], compare = rows[400][1], value = rows[0][1], values = [], indices = []; rows.forEach(function(d, i) { values.push(value = (d[1] - compare) / compare); indices.push(i); }); callback({ 'stock': stock, 'values': values, 'indices': indices }); }); } var promises = []; ['AAPL', 'GOOG', 'MSFT'].forEach(function(stock) { promises.push(new Promise(function(resolve, reject) { var r = loadStockData(stock, resolve); })); }); Promise.all(promises).then(function(stocks) { console.log(stocks); var data = []; data = Enumerable.From(stocks) .SelectMany( "val, index=>" + "Enumerable.From(val.values)" + ".Select(\\"v,i => {'value': v, 'idx':i, 'name':'\\" + val.stock + \\"' } \\")") .ToArray(); /* for(var i = 0; i < stocks.length; i++) { for(var j= 0; j < stocks[i].indices.length; j++) { data.push({ 'idx':stocks[i].indices[j], 'name': stocks[i].stock, 'value': stocks[i].values[j] }) } } */ console.log(data); var ndx, runDimension, runGroup, overviewRunDimension, overviewRunGroup; ndx = crossfilter(data); var allDim = ndx.dimension(function(d){ return [d.idx, d.name, d.value] ;}); runDimension = ndx.dimension(function(d) {return [d.name, d.idx]; }); overviewRunDimension = ndx.dimension(function(d) {return [d.name, d.idx]; }); runGroup = runDimension.group().reduceSum(function(d) { return d.value; }); overviewRunGroup = overviewRunDimension.group().reduceSum(function(d) { return d.value; }); var horizonChart = new dcHorizonChart("#test-hc", 1,2); horizonChart.setData(allDim.group()); var overviewChart = dc.seriesChart("#test-overview"); overviewChart .width(768) .height(100) .chart(function(c) { return dc.lineChart(c).curve(d3.curveCardinal); }) .x(d3.scaleLinear().domain([0,20])) .brushOn(true) .xAxisLabel("Run") .clipPadding(10) .dimension(runDimension) .group(runGroup) .seriesAccessor(function(d) {return "Expt: " + d.key[0];}) .keyAccessor(function(d) {return +d.key[1];}) .valueAccessor(function(d) {return +d.value;}); dc.renderAll(); });
 body { margin: 0; padding: 0; } .horizon { border-top: solid 1px #000; border-bottom: solid 1px #000; overflow: hidden; position: relative; } .horizon + .horizon { border-top: none; } .horizon canvas { display: block; image-rendering: pixelated; } .horizon .title, .horizon .value { bottom: 0; line-height: 30px; margin: 0 6px; position: absolute; font-family: sans-serif; text-shadow: 0 1px 0 rgba(255,255,255,.5); white-space: nowrap; } .horizon .title { left: 0; } .horizon .value { right: 0; }
 <!DOCTYPE html> <html lang="en"> <head> <title>dc.js - Custom Chart Example</title> <meta charset="UTF-8"> <link rel="stylesheet" type="text/css" href="//dc-js.github.io/dc.js/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="//unpkg.com/dc@4/dist/style/dc.css" /> <script src="//d3js.org/d3.v5.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter2/1.4.4/crossfilter.min.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/dc/3.2.1/dc.min.js"></script> <script src="//npmcdn.com/d3-horizon-chart/build/d3-horizon-chart.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script> </head> <body> <div class="container"> <div id="test-overview"></div> <div id="bar"></div> <br/> AAA <br> <div id="test-hc"></div> </div> </body> </html>

我为 dc.js 创建了一个地平线图示例

地平线图示例

将 d3-horizo​​n-chart 与 dc.js 集成的主要问题是它没有 X 比例 - 它只是将每个值显示为 1 像素的颜色列,按数组顺序。

这意味着它不使用组键,并且在绘制地平线图之前必须以正确的顺序对数据进行排序。

这是图表的定义:

  class HorizonChart {
      constructor(parent, group) {
          this._group = null;
          this._colors = null;
          this._seriesAccessor = null;
          this._root = d3.select(parent);
          dc.registerChart(this, group);
      }

      // initialization functions for user

      group(group) {
          if(!arguments.length)
              return this._group;
          this._group = group;
          return this;
      }

      // takes array of colors (not scale)
      colors(colors) {
          if(!arguments.length)
              return this._colors;
          this._colors = colors;
          return this;
      }

      seriesAccessor(seriesAccessor) {
          if(!arguments.length)
              return this._seriesAccessor;
          this._seriesAccessor = seriesAccessor;
          return this;
      }

      valueAccessor(valueAccessor) {
          if(!arguments.length)
              return this._valueAccessor;
          this._valueAccessor = valueAccessor;
          return this;
      }

      // interface for dc.js chart registry

      render() {
          this.redraw();
      }

      redraw() {
          const nester = d3.nest().key(this._seriesAccessor),
                nesting = nester.entries(this._group.all());
          let horizon = this._root.selectAll('.horizon')
              .data(nesting);
          horizon = horizon.enter()
              .append('div')
              .attr('class', 'horizon')
              .merge(horizon);
          const colors = this._colors,
                valueAccessor = this._valueAccessor;
          horizon
              .each(function(series) {
                  d3.select(this).selectAll('*').remove();
                  d3.horizonChart()
                      .colors(typeof colors === 'function' ? colors(series.key) : colors)
                      .title(series.key)
                      .call(this, series.values.map(valueAccessor));
            });
      }

它实现了 dc.js系列图表的一小部分接口。 一个区别是 d3-horizo​​n-chart 接受一组颜色,并根据该数组的长度决定绘制多少正负带。 所以HorizonChart.colors()接受一个颜色数组,或者一个接受 series 键并返回一个颜色数组的函数。

它使用d3.nest()通过系列访问器拆分数据。 然后它添加或删除地平线图的 div,删除每个 div 内的任何内容并在那里绘制地平线图。

对数据进行排序

由于数据需要排序,而我们从group.all()得到的一个 multikey 会排序错误,我们可以使用一个假的 group 来按 key 的两个元素进行排序:

  function sort_multikey_group(group) {
      return {
          all: () => {
              return group.all().slice().sort(
                  ({key: keyA}, {key: keyB}) => d3.ascending(keyA[0],keyB[0]) || d3.ascending(keyA[1],keyB[1]));
          }
      };
  }

我们在初始化地平线图时应用假组:

  var horizonChart = new HorizonChart("#horizon"),
  horizonChart
      .group(sort_multikey_group(exptRunGroup))
      .colors(n => [d3.schemeBlues, d3.schemeOranges, d3.schemeGreens, d3.schemeReds, d3.schemePurples][n-1][6]) // levels * 2
      .seriesAccessor(d => d.key[0])
      .valueAccessor(d => d.value - 500)

.colors()的函数参数为每个地平线图选择一种D3 配色方案 它选择6种颜色的方案来显示3个正和3个负带。

它根据键的第一个元素将数据放入每个系列图表中。 在此示例中,数据向下移动以使用负色带。

示例数据

示例中的数据是dc.js系列图表示例中使用的Michelson-Morley Experiment数据,每一个插值20个点:

  const experiments2 = d3.range(experiments.length-1).flatMap(i => {
      if(experiments[i].Expt !== experiments[i+1].Expt)
          return [];
      let {Expt, Run, Speed: Speed0} = experiments[i],
            {Speed: Speed1} = experiments[i+1];
      Expt = +Expt; Run = +Run; Speed0 = +Speed0; Speed1 = +Speed1;
      const terp = d3.scaleLinear().range([Speed0, Speed1]);
      return d3.range(mult).map(j => ({Expt, Run: Run + j/mult, Speed: terp(j/mult)}));
  });

这是 d3-horizo​​n-chart 和内置 dc.js 图表之间的另一个区别:它需要每个像素的数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM