我有一个表,可以使用节点实时提供的数据进行更新。该表使用d3.js进行渲染。
我的问题是我不知道如何使用d3.js向表中添加过滤,搜索和分页功能。我是一名初学者,无法理解放置代码的最佳位置。我一直在考虑使用外部库来实现它,但如果我找到一种方法来使用d3.js,它会更好更清洁。
这是我的代码:
var table = d3.select('#data')
table.append('thead')
.append('tr')
.selectAll('th')
.data(['Title', 'Visits', 'Sales', 'Conversion(%)'])
.enter()
.append('th')
.text(function (d) { return d })
table.append('tbody')
function setupData(data) {
var rows = d3.select('tbody')
.selectAll('tr')
.data(data, function(d) { return d.title })
var entertd = rows.enter()
.append('tr')
.selectAll('td')
.data(function(d) { return d3.map(d).values() })
.enter()
.append('td')
entertd.append('div')
entertd.append('span')
var td = rows.selectAll('td')
.data(function(d) { return d3.map(d).entries() })
.attr('class', function (d) { return d.key })
td.select('div')
.transition()
.duration(800)
.style('width', function(d) {
switch (d.key) {
case 'conversion_rate' :
// percentage scale is static
scale = d3.scale.linear()
.domain([0, 1])
.range([0, 100])
break;
case 'today_visits':
case 'sold_today' :
scale = d3.scale.linear()
.domain(d3.extent(data, function(d1) { return d1[d.key] }))
.range([0, 100])
break;
default:
return '0px'
}
return scale(d.value) + 'px'
})
td.select('span')
.text(function(d) {
if (d.key == 'conversion_rate') {
return Math.round(100*d.value).toFixed(2) + '%';
}
return d.value
})
}
var socket = io();
//var data = [];
socket.on('sellers-'.concat(<%= seller %>), function(msg){
var data = [];
var seller = $.parseJSON(msg);
var items = seller['items'];
for(item in items) {
var item_data = items[item];
data.push({'title': item_data['title'], 'today_visits': item_data['today_visits'], 'sold_today': item_data['sold_today'], 'conversion_rate': item_data['conversion_rate']});
}
setupData(data);
//setupData(JSON.parse(msg).items)
});
答案 0 :(得分:2)
看起来你的主要D3图表渲染方法已经设置为使用General Update Pattern,所以你应该很高兴去那里。
您最好选择过滤和搜索可能只是使用本机JavaScript解决方案。只需使用过滤后的数据集调用setupData
方法,图表就会更新。例如:
var allData;
var loadItems = function(items) {
var item;
allData = [];
for (item in items) {
allData.push(item);
}
}
var filterMatching = function(matcher) {
var item;
var filteredData = [];
for (item in allData) {
if (matcher(item)) filteredData.push(item);
}
setupData(filteredData);
}
// filter on conversion rate
filterMatching(function(item) { return item.conversion_rate > 0.5; });
// search on title
filterMatching(function(item) { return /foobar/.test(item); });
分页有点棘手,但仍然很简单。你只需要做一些数学运算。
var itemsPerPage = 10;
var numberOfPages() {
return Math.ceil(allData.length / itemsPerPage);
}
var goToPage(pageNumber) {
var firstIndex = (pageNumber - 1) * itemsPerPage;
var pageItems = allData.slice(firstIndex, firstIndex + itemsPerPage);
setupData(pageItems);
}
现在让这些人很好地合作可能需要一些努力。
或者,您可以考虑应用像Crossfilter这样的库,它可以很好地与D3一起使用。您的过滤和分页在Crossfilter中看起来像这样:
var filter = crossfilter(records);
var conversion_rate = filter.dimension(function(d) { return d.conversion_rate; });
var title = filter.dimension(function(d) { return d.title; });
// filter on a dimension
conversion_rate.filterRange([0.5, 1]);
title.filterFunction(function (d) { return /foobar/.test(d); });
// take the top x of a dimension
conversion.group().top(5);
如果您要过滤大量数据,那么使用Crossfilter会快得多。但是,由于你无论如何都要在开始时绘制所有数据,所以看起来你并没有那么多,所以用原生JavaScript手工绘制它可能就好了。