作者:平凡天使心619 | 来源:互联网 | 2023-02-13 16:57
当数据量过大时,使用d3.js渲染各种图时,如果一下子加载出来,会出现加载过慢,这样使用效果就不是太好,为了解决这个问题,使用了分页加载数据并渐进渲染各种图。一、数据格式数据如下:
当数据量过大时,使用d3.js渲染各种图时,如果一下子加载出来,会出现加载过慢,这样使用效果就不是太好,为了解决这个问题,使用了分页加载数据并渐进渲染各种图。
一、数据格式
数据如下:这里是一个example.csv文件,
x,y,value
0,1,0.2
0,2,0.7
0,3,0.01
.......
100000, 20, 1
二、读取数据和拆分数据
// 定义拆分数据函数
let splitData = [];
function getSplitData(data, num=10000) {
let newArray = [];
for (let index = 0; index newArray.push(data.slice(index, index+num));
}
return newArray;
}
// 读取数据
d3.csv('example.csv').then(async function(data){
let heatmapBox, rectGU,xScale, yScale, colorScale;
let myXValue = [...new Set(data.map(d=>{return d.x;}))];
let myYValue = [...new Set(data.map(d=>{return d.y;}))];
// 初始化,代码在第三步骤
renderInit(data);
splitData = getSplitData(data);
// draw data
for (let c=0; c // 分页加载的函数放在了第四步
await renderUpdate(splitData[c]);
}
});
三、draw canvas和create scale
// 一个简单的初始化例子
function renderInit(data) {
const dms = {
width: 1000,
height: 600,
margin: {
top: 50,
right: 50,
bottom: 50,
left: 50
}
};
dms.innerWidth = dms.width - dms.margin.left - dms.margin.right;
dms.innerHeight = dms.height - dms.margin.top - dms.margin.bottom;
// draw canvas
const mainsvg = d3.select(id)
.append('svg')
.attr('width', dms.width)
.attr('height', dms.height)
.attr('id', 'mainsvg')
.style('background', '#f8f9fd');
const maingroup = mainsvg.append('g')
.attr('transform', `translate(${dms.margin.left}, ${dms.margin.top})`);
heatmapBox = maingroup.append('g');
// create scale
xScale = d3.scaleBand()
.domain(myXValue)
.range([0, dms.innerWidth])
.padding(0.01)
yScale = d3.scaleBand()
.domain(myYValue)
.range([dms.innerWidth, 0])
.padding(0.01)
颜色尺度的设置参考上一节,此处省略
}
四、分页加载
// 循环加载
const renderUpdate = async function (data) {
let transition = d3.transition().duration(1000).ease(d3.easeLinear);
rectGU = heatmapBox.append('g').selectAll('rect').data(data);
// heatmapBox.append('g').selectAll('rect').data(data)
// .join('rect')
// .attr('fill', d=>colorScale(d.value))
// .style('opacity', 1)
// .transition(transition)
// .attr('x', d=>xScale(d.x))
// .attr('y', d=>yScale(d.y))
// .attr('rx', 0)
// .attr('ry', 0)
// .attr('width', xScale.bandwidth())
// .attr('height', yScale.bandwidth());
let rectEnters = rectGU.enter().append('rect')
.attr('x', d=>xScale(d.x))
.attr('y', d=>yScale(d.y))
.attr('rx', 0)
.attr('ry', 0)
.attr('width', xScale.bandwidth())
.attr('height', yScale.bandwidth())
.attr('fill', d=>colorScale(d.value))
.style('opacity', 1);
rectGU.merge(rectEnters).transition(transition)
.attr('x', d=>xScale(d.x))
.attr('y', d=>yScale(d.y));
await transition.end();
};
到这里,分页渲染数据完成。