响应式 dc.js 图表正在接管整个 window
responsive dc.js chart is taking over the whole window
我在使我的图表响应时遇到问题,我正在尝试对 DC.js 和 Crossfilter 应用相同的示例 link:resizing-series.
该图表是响应式的,但是,在与我的表格交互时存在一些错误。例如,当我单击图形或任何表格时,图形变得非常大,占据了整个屏幕。如下图所示:
当我离开 Console
分割屏幕时,图形会响应地呈现,因为我更改屏幕尺寸时图形的大小也会更改,但是,如果我离开 Console
图形仍然占据整个屏幕,并且没有 return 到第一张图片中显示的默认初始大小。
有谁知道如何修复这些错误?我不明白为什么会这样。
提前致谢。
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>
感谢您发布示例!除非您进入整页模式,否则该错误不会出现在 SO 代码片段功能中。我发现 your fiddle 更容易使用。
注意:这是对我之前的回答的完全重写,当时还不清楚。
1。使用 ResizeObserver
20 年 4 月 28 日更新
从 Safari 13.1(2020 年 3 月 24 日发布)开始,所有现代浏览器都支持 ResizeObserver。这是检测图表大小调整的最简洁方法。
我推荐
- 使用自上而下的布局(例如 flexbox 或网格)来定位图表的 div
- 使用
ResizeObserver
确定 div 何时更改大小
- 告诉图表使用
.width(null).height(null)
检测图表 div 大小
目前有 one resizing example 执行此操作。
特殊值 null
告诉图表使 SVG 节点与其父节点大小相同 div:
chart1.width(null)
.height(null)
回调使用辅助函数来禁用转换,因为转换只会减慢调整大小并使其看起来笨拙:
const callback = chart => entries => {
redraw_chart_no_transitions(
chart
.width(null)
.height(null)
.rescale());
};
设置观察者看起来像
new ResizeObserver(callback(chart1)).observe(d3.select('#test1').node());
详情请看示例。
2。使用 window.onresize
另一个 resizing examples 关注 window.onresize
,因为直到最近,这是检测更改的唯一有效、可靠的跨浏览器方式。
他们根据 window 大小计算图表大小,如果您的布局是自下而上的,这很有效,例如使用默认的 float: left
布局。
这是设置它的函数:
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);
};
}
单个图表可以这样初始化:
apply_resizing(chart, 20);
这会填充 window 但会使图表宽度减少 20 像素。
该函数还可以采用数组中的多个图表,以及支持复杂布局的调整函数,例如两个图表应垂直拆分 window 的函数:
apply_resizing([heatmapChart, barChart], 20, y => y/2-fudge);
我在使我的图表响应时遇到问题,我正在尝试对 DC.js 和 Crossfilter 应用相同的示例 link:resizing-series.
该图表是响应式的,但是,在与我的表格交互时存在一些错误。例如,当我单击图形或任何表格时,图形变得非常大,占据了整个屏幕。如下图所示:
当我离开 Console
分割屏幕时,图形会响应地呈现,因为我更改屏幕尺寸时图形的大小也会更改,但是,如果我离开 Console
图形仍然占据整个屏幕,并且没有 return 到第一张图片中显示的默认初始大小。
有谁知道如何修复这些错误?我不明白为什么会这样。
提前致谢。
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>
感谢您发布示例!除非您进入整页模式,否则该错误不会出现在 SO 代码片段功能中。我发现 your fiddle 更容易使用。
注意:这是对我之前的回答的完全重写,当时还不清楚。
1。使用 ResizeObserver
20 年 4 月 28 日更新
从 Safari 13.1(2020 年 3 月 24 日发布)开始,所有现代浏览器都支持 ResizeObserver。这是检测图表大小调整的最简洁方法。
我推荐
- 使用自上而下的布局(例如 flexbox 或网格)来定位图表的 div
- 使用
ResizeObserver
确定 div 何时更改大小 - 告诉图表使用
.width(null).height(null)
检测图表 div 大小
目前有 one resizing example 执行此操作。
特殊值 null
告诉图表使 SVG 节点与其父节点大小相同 div:
chart1.width(null)
.height(null)
回调使用辅助函数来禁用转换,因为转换只会减慢调整大小并使其看起来笨拙:
const callback = chart => entries => {
redraw_chart_no_transitions(
chart
.width(null)
.height(null)
.rescale());
};
设置观察者看起来像
new ResizeObserver(callback(chart1)).observe(d3.select('#test1').node());
详情请看示例。
2。使用 window.onresize
另一个 resizing examples 关注 window.onresize
,因为直到最近,这是检测更改的唯一有效、可靠的跨浏览器方式。
他们根据 window 大小计算图表大小,如果您的布局是自下而上的,这很有效,例如使用默认的 float: left
布局。
这是设置它的函数:
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);
};
}
单个图表可以这样初始化:
apply_resizing(chart, 20);
这会填充 window 但会使图表宽度减少 20 像素。
该函数还可以采用数组中的多个图表,以及支持复杂布局的调整函数,例如两个图表应垂直拆分 window 的函数:
apply_resizing([heatmapChart, barChart], 20, y => y/2-fudge);