添加过滤,search和分页到实时stream表

我有一个表使用节点实时提供的数据进行更新。 该表使用d3.js呈现

我的问题是,我不知道如何使用d3.js添加过滤,search和分页function到表中。 我是一个begginer,并且无法理解哪里是放置代码的最佳位置。 我一直在考虑使用外部库来做这件事,但是如果我find一种方法来使用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) }); 

它看起来像你的主要的D3图表渲染方法已经设置为使用通用更新模式 ,所以你应该很好去那里。

过滤和search最好的办法可能就是使用本地JavaScript解决scheme。 只需使用筛选的数据集调用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); }); 

分页是有点棘手,但仍然非常简单。 你只需要做一点math。

 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进行手动滚动可能是一种可行的方法。