我构建了一个应用程序,它通过socketio消耗来自redis频道(卖家)的数据,并将数据实时推送到前端。数据集最多可包含一千行,因此我正在考虑使用数据表以干净的方式表示数据。表元素将定期更新,但不会添加/删除行,只会更新。
我面临的问题是,由于我对可视化生态系统缺乏经验,我不知道哪种方法可以实现。我一直在玩弄d3js,但我认为很难快速准备一些东西并且尝试使用datatables js库但是我没有看到如何使数据表实时化。< / p>
这是前端的代码摘录:
socket.on('sellers', function(msg){
var seller = $.parseJSON(msg);
var sales = [];
var visits = [];
var conversion = [];
var items = seller['items'];
var data = [];
for(item in items) {
var item_data = items[item];
//data.push(item_data)
data.push([item_data['title'], item_data['today_visits'], item_data['sold_today'], item_data['conversion-rate']]);
}
//oTable.dataTable(data);
$(".chart").html("");
drawBar(data);
});
答案 0 :(得分:1)
使用d3解决您的问题简单而优雅。今天早上我花了一点时间来创造一个你可以适应自己需要的小提琴:
http://jsfiddle.net/CelloG/47nxxhfu/
要使用d3,您需要了解将数据连接到html元素的工作原理。请查看http://bost.ocks.org/mike/join/以获取作者的简要说明。
小提琴中的代码是:
var table = d3.select('#data')
// set up the table header
table.append('thead')
.append('tr')
.selectAll('th')
.data(['Title', 'Visits', 'Sold', 'Conversion Rate'])
.enter()
.append('th')
.text(function (d) { return d })
table.append('tbody')
// set up the data
// note that both the creation of the table AND the update is
// handled by the same code. The code must be run on each time
// the data is changed.
function setupData(data) {
// first, select the table and join the data to its rows
// just in case we have unsorted data, use the item's title
// as a key for mapping data on update
var rows = d3.select('tbody')
.selectAll('tr')
.data(data, function(d) { return d.title })
// if you do end up having variable-length data,
// uncomment this line to remove the old ones.
// rows.exit().remove()
// For new data, we create rows of <tr> containing
// a <td> for each item.
// d3.map().values() converts an object into an array of
// its values
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')
// now that all the placeholder tr/td have been created
// and mapped to their data, we populate the <td> with the data.
// First, we split off the individual data for each td.
// d3.map().entries() returns each key: value as an object
// { key: "key", value: value}
// to get a different color for each column, we set a
// class using the attr() function.
// then, we add a div with a fixed height and width
// proportional to the relative size of the value compared
// to all values in the input set.
// This is accomplished with a linear scale (d3.scale.linear)
// that maps the extremes of values to the width of the td,
// which is 100px
// finally, we display the value. For the title entry, the div
// is 0px wide
var td = rows.selectAll('td')
.data(function(d) { return d3.map(d).entries() })
.attr('class', function (d) { return d.key })
// the simple addition of the transition() makes the
// bars update smoothly when the data changes
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) + '%'
}
return d.value
})
}
setupData(randomizeData())
d3.select('#update')
.on('click', function() {
setupData(randomizeData())
})
// dummy randomized data: use this function for the socketio data
// instead
//
// socket.on('sellers', function(msg){
// setupData(JSON.parse(msg).items)
// })
function randomizeData() {
var ret = []
for (var i = 0; i < 1000; i++) {
ret.push({
title: "Item " + i,
today_visits: Math.round(Math.random() * 300),
sold_today: Math.round(Math.random() * 200),
conversion_rate: Math.random()
})
}
return ret
}