响应式dc.js图表​​占据了整个窗口 [英] responsive dc.js chart is taking over the whole window

查看:57
本文介绍了响应式dc.js图表​​占据了整个窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使图表响应时遇到麻烦,我试图通过以下链接对DC.js和Crossfilter应用相同的示例:

当我用 Console 分开屏幕时,图形将响应性地呈现,因为当我更改屏幕尺寸时,图形的大小也会改变,但是,如果我离开 Console 图表仍会占据整个屏幕,并且不会返回第一张图片中显示的默认初始大小.

有人知道如何告诉我如何解决这些错误吗?我不明白为什么会这样.

提前考虑

  var复合= dc.compositeChart('#composite');var vendedorTable = dc.dataTable(#vendedores");var citysTable = dc.dataTable(#cities");函数remove_empty_bins(source_group){返回 {顶部:function(N){返回source_group.all().filter(function(d){返回d.value.totalAno>1e-3 ||d.value.totalHomologo>1e-3;}).slice(0,N);}};}var url ='https://gist.githubusercontent.com/bernalvinicius/3cece295bc37de1697e7f83418e7fcc9/raw/a5820379ec6eae76ee792495cc5dd1685c977a73/vendedores.json';d3.json(url).then(function(data){data.forEach(d =>Object.assign(d,{邮件:d.Month,单位:d.Vendas_Ano,passado:d.Vendas_Ant}));var cf = crossfilter(data);vendedorDim = cf.dimension(function(d){返回d.vendnm;});var vendedorGroup = vendedorDim.group().reduce(reduceAdd,reduceRemove,reduceInitial);cityDim = cf.dimension(function(d){返回d.zona;});var cityGroup = cityDim.group().reduce(reduceAdd,reduceRemove,reduceInitial);var dim = cf.dimension(dc.pluck('mes')),grp1 = dim.group().reduceSum(dc.pluck('atual')),grp2 = dim.group().reduceSum(dc.pluck('passado'));var minMonth = dim.bottom(1)[0] .mes;var maxMonth = dim.top(1)[0] .mes;var all = cf.groupAll();dc.dataCount(.dc-data-count").dimension(cf).group(all);函数reduceAdd(p,v){p.totalAno + = + v.Vendas_Ano;p.totalHomologo + = + v.Vendas_Ant;返回p;}函数reduceRemove(p,v){p.totalAno-= v.Vendas_Ano;p.totalHomologo-= v.Vendas_Ant;返回p;}函数reduceInitial(){返回 {totalAno:0,totalHomologo:0,};}//伪尺寸等级=函数(p){返回 ""};//每月图表合成的.width(600).height(300).x(d3.scaleLinear().domain([1,12])).yAxisLabel(").xAxisLabel(月").legend(dc.legend().x(500).y(0).itemHeight(13).gap(5)).renderHorizo​​ntalGridLines(true).撰写([dc.lineChart(复合).dimension(dim).colors('steelblue').group(grp1,当前年份"),dc.lineChart(复合).dimension(dim).colors('darkorange').group(grp2,去年")]).brushOn(true);Composite.brush().extent([-0.5,data.length + 1.5])Composite.extendBrush = function(brushSelection){如果(brushSelection){vendedorTable.filter(null);vendedorDim.filter(null);cityTable.filter(null);cityDim.filter(null);const point = Math.round((brushSelection [0] + brushSelection [1])/2);返回 [点-0.5,点+ 0.5];}};//销售表vendedorTable.width(500).height(480).dimension(remove_empty_bins(vendedorGroup)).group(等级).columns([function(d){返回d.key;},功能(d){返回Number(Math.round(d.value.totalAno * 100)/100).toLocaleString("es-ES",{minimumFractionDigits:2})+'€';},功能(d){返回Number(Math.round(d.value.totalHomologo * 100)/100).toLocaleString("es-ES",{minimumFractionDigits:2})+'€';}]).sortBy(function(d){返回d.value.totalAno}).order(d3.descending)//城市表citysTable.width(500).height(480).dimension(remove_empty_bins(citiesGroup)).group(等级).columns([function(d){返回d.key;},功能(d){返回Number(Math.round(d.value.totalAno * 100)/100).toLocaleString("es-ES",{minimumFractionDigits:2})+'€';},功能(d){返回Number(Math.round(d.value.totalHomologo * 100)/100).toLocaleString("es-ES",{minimumFractionDigits:2})+'€';}]).sortBy(function(d){返回d.value.totalAno}).order(d3.descending)//销售点击事件vendedorTable.on('pretransition',function(table){table.selectAll('td.dc-table-column').on('click',function(d){让滤镜= table.filters().slice();如果(filters.indexOf(d.key)=== -1)filter.push(d.key);别的过滤器= filters.filter(k => k!= d.key);如果(filters.length === 0)vendedorDim.filter(null);别的vendedorDim.filterFunction(function(d){返回filters.indexOf(d)!== -1;})table.replaceFilter([filters]);cityTable.filter(null);cityDim.filter(null);Composite.filter(null);dc.redrawAll();});让滤镜= table.filters();table.selectAll('tr.dc-table-row').classed('sel-rows',d => filters.indexOf(d.key)!== -1);});//城市点击事件cityTable.on('pretransition',function(table){table.selectAll('td.dc-table-column').on('click',function(d){让滤镜= table.filters().slice();如果(filters.indexOf(d.key)=== -1)filter.push(d.key);别的过滤器= filters.filter(k => k!= d.key);如果(filters.length === 0)cityDim.filter(null);别的cityDim.filterFunction(function(d){返回filters.indexOf(d)!== -1;})table.replaceFilter([filters]);vendedorTable.filter(null);vendedorDim.filter(null);Composite.filter(null);dc.redrawAll();});让滤镜= table.filters();table.selectAll('tr.dc-table-row').classed('sel-rows,d => filters.indexOf(d.key)!== -1);});dc.renderAll();//重置功能$('#reset').on('click',function(){vendedorTable.filter(null);vendedorDim.filter(null);cityTable.filter(null);cityDim.filter(null);Composite.filter(null);dc.redrawAll();});$('#resetTable').on('click',function(){vendedorTable.filter(null);vendedorDim.filter(null);cityTable.filter(null);cityDim.filter(null);Composite.filter(null);dc.redrawAll();});$('#resetTable2').on('click',function(){vendedorTable.filter(null);vendedorDim.filter(null);cityTable.filter(null);cityDim.filter(null);Composite.filter(null);dc.redrawAll();});/*********************************************************************************///处理响应的函数var AdjustX = 10,AdjustY = 40;apply_resizing(composite,adjustX,adjustY,function(composite){Composite.legend().x(window.innerWidth-200);});var find_query = function(){var _map = window.location.search.substr(1).split('&').map(function(a){返回a.split('=');}).reduce(function(p,v){如果(v.length> 1)p [v [0]] = encodeURIComponent(v [1] .replace(/\ +/g,"));别的p [v [0]] = true;返回p;},{});返回函数(字段){返回_map [field] ||空值;};}();var resizeMode = find_query('resize')||'widhei';函数apply_resizing(composite,adjustX,adjustY,onresize){如果(resizeMode ==='viewbox'){合成的.width(300).height(200).useViewBoxResizing(true);d3.select(composite.anchor()).classed('fullsize',false);} 别的 {AdjustX = AdjustX ||0;AdjustY = AdjustY ||AdjustX ||0;合成的.width(window.innerWidth-AdjustX).height(window.innerHeight-AdjustY);window.onresize = function(){如果(调整大小){onresize(composite);}合成的.width(window.innerWidth-AdjustX).height(window.innerHeight-AdjustY);如果(composite.rescale){Composite.rescale();}Composite.redraw();};}}});  

  #composite {内边距:10px;}.dc-table-group {能见度:崩溃;}tr.dc-table-row.sel-rows {背景颜色:浅蓝色;}.brush .custom-brush-handle {显示:无;}  

 <!-网站图标->< link rel =快捷方式图标" href ="https://img.icons8.com/nolan/64/puzzle.png"><!-bootstrap.css->< link rel ="stylesheet" href ="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"完整性="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va + PmSTszz/K68vbdE4><!-bootstrap-theme.css->< link rel ="stylesheet" href ="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"完整性="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPpQbGYginan"><!-dc.css->< link rel ="stylesheet" href ="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.8/dc.css"><!-jquery.js->< script src ="https://code.jquery.com/jquery-3.4.1.js"完整性="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU =" crossorigin ="anonymous"</script>< ;!-bootstrap.js->< script src ="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"完整性="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7T< ous"<!-d3.v5.js->< script src ="https://d3js.org/d3.v5.js"></script><!-crossfilter.js->< script src ="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"</script><!-dc.js->< script src ="https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.js"</script>< title> 12</title></head><身体>< div class ="container-fluid">< div class ="row content">< div class ="col-md-10">< div class ="col-md-4">< div id ="composite"></div></div></div></div>< div class ="row content">< div class ="col-md-10">< div style ="padding:20px ;;"class ="row marginClass">< h4 class ="pull-left" id =简介">< small>虚拟公司数据|向下钻取示例|</small></h4>< h6 class ="dc-data-count" style ="float:left; margin-left:5px;">< span>< span class ="filter-count"></span>从中选择< span class ="total-count"></span>记录|< a id =重置">重置</a></span></h6></div>< div class ="col-md-4">< table class ="table" id ="vendedores">< thead>< tr>< th; Sales</th><当前年</th>< th>去年</th></tr></thead></table></div>< div class ="col-md-4">< table class ="table" id ="cities">< thead>< tr>< th> City< th><当前年</th>< th>去年</th></tr></thead></table></div></div></div></div></body>  

解决方案

感谢您发布示例!除非您进入整页模式,否则该错误不会显示在SO代码段功能中.我发现您的小提琴更易于使用.

注意:这是我以前的答案的完整重写,尚不清楚.

1.使用 ResizeObserver

更新4/28/20

从Safari 13.1(于2020年3月24日发布)开始,所有现代浏览器均支持 ResizeObserver .这是检测图表大小的最干净的方法.

我推荐

  1. 使用自上而下的布局(例如flexbox或网格)来放置图表的div
  2. 使用 ResizeObserver 确定div何时更改大小
  3. 告诉图表以使用 .width(null).height(null)
  4. 来检测图表div大小

当前有一个调整大小的示例就是这样做的.

特殊值 null 告诉图表使SVG节点的大小与其父div相同:

  chart1.width(空).height(空) 

回调函数使用辅助函数来禁用过渡,因为过渡只会减慢调整大小并使其显得笨拙:

  const回调=图表=>条目=>{redraw_chart_no_transitions(图表.width(null).height(空).rescale());}; 

设置观察者的样子

  new ResizeObserver(callback(chart1)).observe(d3.select('#test1').node()); 

有关更多详细信息,请参见示例.

2.使用 window.onresize

其他调整大小示例注意 window.onresize ,因为直到最近,这是检测更改的唯一有效,可靠的跨浏览器方式.

他们根据窗口大小计算图表大小,如果您的布局是自下而上的,例如使用默认的 float:left 布局.

以下是设置此功能的功能:

  function apply_resizing(图表,adjustX,adjustY,onresize){if(!Array.isArray(chart))图表= [图表];if(!isNaN(adjustX))AdjustX =(dx => x => x-dx)(adjustX);AdjustX = AdjustX ||(x => x);if(!isNaN(adjustY))AdjustY =(dy => y => y-dy)(adjustY);AdjustY = AdjustY ||AdjustX ||(y => y);chart.forEach(c => c.width(adjustX(window.innerWidth)).height(adjustY(window.innerHeight)));window.onresize = function(){如果(调整大小){chart.forEach(onresize);}chart.forEach(c => {c.width(adjustX(window.innerWidth)).height(adjustY(window.innerHeight));如果(c.rescale){c.rescale();}});redraw_chart_no_transitions(chart);};} 

可以像这样初始化单个图表:

  apply_resizing(图20); 

这会填满窗口,但会使图表的宽度减少20个像素.

该函数还可以在一个数组中获取多个图表,并且可以使用调整函数来支持复杂的布局,例如其中两个图表应垂直拆分窗口的情况:

  apply_resizing([heatmapChart,barChart],20,y => y/2-fudge); 

I'm having trouble making my chart responsive, I'm trying to apply the same example with DC.js and Crossfilter that is at this link: resizing-series.

The chart is responsive, however, there are some bugs when interacting with the tables I have. For example, when I click on either the graph or any of the tables, the graph becomes very large, occupying the entire screen. As shown in the image below:

When I leave the screen split with Console, the graph is rendered responsively, as I change the screen size the size of the graph is also changed, however, if I leaveConsole the graph remains occupying the entire the screen and does not return to the default initial size shown in the first image.

Does anyone know how to tell me how to fix these bugs? I couldn't understand why this is happening.

Thnaks in advance.

var composite = dc.compositeChart('#composite');
var vendedorTable = dc.dataTable("#vendedores");
var citiesTable = dc.dataTable("#cities");

function remove_empty_bins(source_group) {
  return {
    top: function(N) {
      return source_group.all().filter(function(d) {
        return d.value.totalAno > 1e-3 ||
          d.value.totalHomologo > 1e-3;
      }).slice(0, N);
    }
  };
}

var url = 'https://gist.githubusercontent.com/bernalvinicius/3cece295bc37de1697e7f83418e7fcc9/raw/a5820379ec6eae76ee792495cc5dd1685c977a73/vendedores.json';
d3.json(url).then(function(data) {

  data.forEach(d =>
    Object.assign(d, {
      mes: d.Month,
      atual: d.Vendas_Ano,
      passado: d.Vendas_Ant
    })
  );
  var cf = crossfilter(data);

  vendedorDim = cf.dimension(function(d) {
    return d.vendnm;
  });
  var vendedorGroup = vendedorDim.group().reduce(reduceAdd, reduceRemove, reduceInitial);

  citiesDim = cf.dimension(function(d) {
    return d.zona;
  });
  var citiesGroup = citiesDim.group().reduce(reduceAdd, reduceRemove, reduceInitial);

  var dim = cf.dimension(dc.pluck('mes')),
    grp1 = dim.group().reduceSum(dc.pluck('atual')),
    grp2 = dim.group().reduceSum(dc.pluck('passado'));
  var minMonth = dim.bottom(1)[0].mes;
  var maxMonth = dim.top(1)[0].mes;

  var all = cf.groupAll();

  dc.dataCount(".dc-data-count")
    .dimension(cf)
    .group(all);

  function reduceAdd(p, v) {
    p.totalAno += +v.Vendas_Ano;
    p.totalHomologo += +v.Vendas_Ant;
    return p;
  }

  function reduceRemove(p, v) {
    p.totalAno -= v.Vendas_Ano;
    p.totalHomologo -= v.Vendas_Ant;
    return p;
  }

  function reduceInitial() {
    return {
      totalAno: 0,
      totalHomologo: 0,
    };
  }

  // Fake Dimension
  rank = function(p) {
    return ""
  };

  // Chart by months
  composite
    .width(600)
    .height(300)
    .x(d3.scaleLinear().domain([1, 12]))
    .yAxisLabel("")
    .xAxisLabel("Month")
    .legend(dc.legend().x(500).y(0).itemHeight(13).gap(5))
    .renderHorizontalGridLines(true)
    .compose([
      dc.lineChart(composite)
      .dimension(dim)
      .colors('steelblue')
      .group(grp1, "Currently Year"),
      dc.lineChart(composite)
      .dimension(dim)
      .colors('darkorange')
      .group(grp2, "Last Year")
    ])
    .brushOn(true);

  composite.brush().extent([-0.5, data.length + 1.5])
  composite.extendBrush = function(brushSelection) {
    if (brushSelection) {
      vendedorTable.filter(null);
      vendedorDim.filter(null);
      citiesTable.filter(null);
      citiesDim.filter(null);
      const point = Math.round((brushSelection[0] + brushSelection[1]) / 2);
      return [
        point - 0.5,
        point + 0.5
      ];
    }
  };

  // Sales Table
  vendedorTable.width(500)
    .height(480)
    .dimension(remove_empty_bins(vendedorGroup))
    .group(rank)
    .columns([function(d) {
        return d.key;
      },
      function(d) {
        return Number(Math.round(d.value.totalAno * 100) / 100).toLocaleString("es-ES", {
          minimumFractionDigits: 2
        }) + '€';
      },
      function(d) {
        return Number(Math.round(d.value.totalHomologo * 100) / 100).toLocaleString("es-ES", {
          minimumFractionDigits: 2
        }) + '€';
      }
    ])
    .sortBy(function(d) {
      return d.value.totalAno
    })
    .order(d3.descending)

  // Cities Table
  citiesTable.width(500)
    .height(480)
    .dimension(remove_empty_bins(citiesGroup))
    .group(rank)
    .columns([function(d) {
        return d.key;
      },
      function(d) {
        return Number(Math.round(d.value.totalAno * 100) / 100).toLocaleString("es-ES", {
          minimumFractionDigits: 2
        }) + '€';
      },
      function(d) {
        return Number(Math.round(d.value.totalHomologo * 100) / 100).toLocaleString("es-ES", {
          minimumFractionDigits: 2
        }) + '€';
      }
    ])
    .sortBy(function(d) {
      return d.value.totalAno
    })
    .order(d3.descending)

  // Sales click events
  vendedorTable.on('pretransition', function(table) {
    table.selectAll('td.dc-table-column')
      .on('click', function(d) {
        let filters = table.filters().slice();
        if (filters.indexOf(d.key) === -1)
          filters.push(d.key);
        else
          filters = filters.filter(k => k != d.key);
        if (filters.length === 0)
          vendedorDim.filter(null);
        else
          vendedorDim.filterFunction(function(d) {
            return filters.indexOf(d) !== -1;
          })
        table.replaceFilter([filters]);

        citiesTable.filter(null);
        citiesDim.filter(null);
        composite.filter(null);

        dc.redrawAll();
      });
    let filters = table.filters();
    table.selectAll('tr.dc-table-row')
      .classed('sel-rows', d => filters.indexOf(d.key) !== -1);
  });

  // Cities click events
  citiesTable.on('pretransition', function(table) {
    table.selectAll('td.dc-table-column')
      .on('click', function(d) {
        let filters = table.filters().slice();
        if (filters.indexOf(d.key) === -1)
          filters.push(d.key);
        else
          filters = filters.filter(k => k != d.key);
        if (filters.length === 0)
          citiesDim.filter(null);
        else
          citiesDim.filterFunction(function(d) {
            return filters.indexOf(d) !== -1;
          })
        table.replaceFilter([filters]);

        vendedorTable.filter(null);
        vendedorDim.filter(null);
        composite.filter(null);

        dc.redrawAll();
      });
    let filters = table.filters();
    table.selectAll('tr.dc-table-row')
      .classed('sel-rows', d => filters.indexOf(d.key) !== -1);
  });


  dc.renderAll();

  // reset functions
  $('#reset').on('click', function() {
    vendedorTable.filter(null);
    vendedorDim.filter(null);
    citiesTable.filter(null);
    citiesDim.filter(null);
    composite.filter(null);

    dc.redrawAll();
  });

  $('#resetTable').on('click', function() {
    vendedorTable.filter(null);
    vendedorDim.filter(null);
    citiesTable.filter(null);
    citiesDim.filter(null);
    composite.filter(null);

    dc.redrawAll();
  });

  $('#resetTable2').on('click', function() {
    vendedorTable.filter(null);
    vendedorDim.filter(null);
    citiesTable.filter(null);
    citiesDim.filter(null);
    composite.filter(null);

    dc.redrawAll();
  });


  /****************************************************************************/
  // Functions to handle responsive

  var adjustX = 10,
    adjustY = 40;

  apply_resizing(composite, adjustX, adjustY, function(composite) {
    composite.legend().x(window.innerWidth - 200);
  });

  var find_query = function() {
    var _map = window.location.search.substr(1).split('&').map(function(a) {
      return a.split('=');
    }).reduce(function(p, v) {
      if (v.length > 1)
        p[v[0]] = decodeURIComponent(v[1].replace(/\+/g, " "));
      else
        p[v[0]] = true;
      return p;
    }, {});
    return function(field) {
      return _map[field] || null;
    };
  }();

  var resizeMode = find_query('resize') || 'widhei';

  function apply_resizing(composite, adjustX, adjustY, onresize) {
    if (resizeMode === 'viewbox') {
      composite
        .width(300)
        .height(200)
        .useViewBoxResizing(true);
      d3.select(composite.anchor()).classed('fullsize', false);
    } else {
      adjustX = adjustX || 0;
      adjustY = adjustY || adjustX || 0;
      composite
        .width(window.innerWidth - adjustX)
        .height(window.innerHeight - adjustY);
      window.onresize = function() {
        if (onresize) {
          onresize(composite);
        }
        composite
          .width(window.innerWidth - adjustX)
          .height(window.innerHeight - adjustY);

        if (composite.rescale) {
          composite.rescale();
        }
        composite.redraw();
      };
    }
  }
});

#composite {
  padding: 10px;
}

.dc-table-group {
  visibility: collapse;
}

tr.dc-table-row.sel-rows {
  background-color: lightblue;
}

.brush .custom-brush-handle {
  display: none;
}

<!-- favicon -->
<link rel="shortcut icon" href="https://img.icons8.com/nolan/64/puzzle.png">
<!-- bootstrap.css -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- bootstrap-theme.css -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- dc.css -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.8/dc.css">
<!-- jquery.js -->
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<!-- bootstrap.js -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<!-- d3.v5.js -->
<script src="https://d3js.org/d3.v5.js"></script>
<!-- crossfilter.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script>
<!-- dc.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.js"></script>

<title>12</title>
</head>

<body>
  <div class="container-fluid">
    <div class="row content">
      <div class="col-md-10">
        <div class="col-md-4">
          <div id="composite"></div>
        </div>
      </div>
    </div>
    <div class="row content">
      <div class="col-md-10">
        <div style="padding: 20px;;" class="row marginClass">
          <h4 class="pull-left" id="Introduction">
            <small>Fictitious company data | Drilldown Example |</small>
          </h4>
          <h6 class="dc-data-count" style="float: left;margin-left:5px;">
            <span>
                            <span class="filter-count"></span> selected from
            <span class="total-count"></span> records |
            <a id="reset"> Reset </a>
            </span>
          </h6>
        </div>

        <div class="col-md-4">
          <table class="table" id="vendedores">
            <thead>
              <tr>
                <th>Sales</th>
                <th>Current Year</th>
                <th>Last Year</th>
              </tr>
            </thead>
          </table>
        </div>

        <div class="col-md-4">
          <table class="table" id="cities">
            <thead>
              <tr>
                <th>City</th>
                <th>Current Year</th>
                <th>Last Year</th>
              </tr>
            </thead>
          </table>
        </div>
      </div>
    </div>
  </div>
</body>

解决方案

Thanks for posting an example! The bug doesn't show up in the SO code snippet feature unless you go to full page mode. I found your fiddle easier to work with.

Note: this is a complete rewrite of my previous answer, which was not clear.

1. Using ResizeObserver

updated 4/28/20

As of Safari 13.1 (released March 24 2020) all modern browsers support ResizeObserver. This is the cleanest way to detect chart resizing.

I recommend

  1. Use a top-down layout such as flexbox or grid to position the divs for your charts
  2. Use ResizeObserver to determine when the div has changed size
  3. Tell the charts to detect the chart div size using .width(null).height(null)

There is currently one resizing example that does this.

The special value null tells the chart to make the SVG node the same size as its parent div:

chart1.width(null)
    .height(null)

The callback uses a helper function to disable transitions, because transitions just slow resizing down and make it look clunky:

const callback = chart => entries => {
    redraw_chart_no_transitions(
        chart
            .width(null)
            .height(null)
            .rescale());
    };

Setting up the observer looks like

new ResizeObserver(callback(chart1)).observe(d3.select('#test1').node());

Please see the example for more details.

2. Using window.onresize

The other resizing examples watch for window.onresize because until recently that was the only efficient, reliable cross-browser way to detect changes.

They calculate chart sizes based on the window size, which works well if your layout is bottom-up, e.g. using the default float: left layout.

Here is the function which sets this up:

function apply_resizing(chart, adjustX, adjustY, onresize) {
    if(!Array.isArray(chart))
        chart = [chart];
    if(!isNaN(adjustX))
        adjustX = (dx => x => x-dx)(adjustX);
    adjustX = adjustX || (x => x);
    if(!isNaN(adjustY))
        adjustY = (dy => y => y-dy)(adjustY);
    adjustY = adjustY || adjustX || (y => y);
    chart.forEach(c => c.width(adjustX(window.innerWidth))
                  .height(adjustY(window.innerHeight)));
    window.onresize = function () {
        if (onresize) {
            chart.forEach(onresize);
        }
        chart.forEach(c => {
            c.width(adjustX(window.innerWidth))
                .height(adjustY(window.innerHeight));
            if (c.rescale) {
                c.rescale();
            }
        });
        redraw_chart_no_transitions(chart);
    };
}

A single chart can be initialized like so:

apply_resizing(chart, 20);

This fills the window but makes the chart 20 pixels less wide.

The function can also take multiple charts in an array, and adjustment functions to support complicated layouts, like one where two charts should split the window vertically:

apply_resizing([heatmapChart, barChart], 20, y => y/2-fudge);

这篇关于响应式dc.js图表​​占据了整个窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆