D3: D3散点图测试大数据分批渲染

一: 准备工作:

d3.js  :  /static/js/d3.min.js

test.csv :  /static/data/test.csv

读取测试数据类似下图:

二: 代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>D3散点图</title>
    <script src="./static/js/d3.min.js"></script>
</head>
<body>
    <svg width="800" height="400" id="mainSvg" class="svg"></svg>
    
    <script>
        const svg = d3.select('#mainSvg');
        const width = +svg.attr('width');
        const height = +svg.attr('height');
        const margin = { top: 60, right: 30, bottom: 60, left: 80 };
        const innerWidth = width - margin.left - margin.right;
        const innerHeight = height - margin.top - margin.bottom;

        let xScale, yScale;
        let sequential;
        // x轴y轴标题
        const xAxisLabel = 'log2';
        const yAxisLabel = '-log10';
        
        let xValue = d => d['x'];
        let yValue = d => d['y'];
        let duration = 500;
        // 根据类型设定颜色
        var color = {
            "Down_116": "#1E90FF",
            "no-DEGS_139": "#A9A9A9",
            "Up_139": "#FF0000",
        }

        const renderInit = function (data) {
            // 设置x坐标
            xScale = d3.scaleLinear()
                .domain(d3.extent(data, xValue))
                .range([0, innerWidth]);

            // 设置y坐标
            yScale = d3.scaleLinear()
                .domain(d3.extent(data, yValue).reverse())
                .range([0, innerHeight]);

            const g = svg.append('g')
                .attr('transform', `translate(${margin.left}, ${margin.top})`)
                .attr('id', 'mainGroup');

            // Adding axes; 
            const yAxis = d3.axisLeft(yScale); 
            const xAxis = d3.axisBottom(xScale);

            // 加入y轴
            let yAxisGroup = g.append('g').call(yAxis)
                .attr('id', 'yaxis');
            yAxisGroup.append('text')
                .attr('font-size', '2em')
                .attr('transform', `rotate(-90)`)
                .attr('x', -innerHeight / 2)
                .attr('y', -60)
                .attr('fill', '#333333')
                .text(yAxisLabel)
                .attr('text-anchor', 'middle') // Make label at the middle of axis. 
            // yAxisGroup.selectAll('.domain').remove(); // we can select multiple tags using comma to seperate them and we can use space to signify nesting; 

            // 加入x轴
            let xAxisGroup = g.append('g').call(xAxis)
                .attr('transform', `translate(${0}, ${innerHeight})`)
                .attr('id', 'xaxis');
            xAxisGroup.append('text')
                .attr('font-size', '2em')
                .attr('y', 50)
                .attr('x', innerWidth / 2)
                .attr('fill', '#333333')
                .text(xAxisLabel);
            // xAxisGroup.selectAll('.domain').remove();
        };

        const renderUpdate = function(data){
            const g = d3.select('#mainGroup');
            let circleUpdates = g.selectAll('circle').data(data,d=>d['name']);
            // console.log(data)
            let circleEnter = circleUpdates.enter().append('circle')
                .attr('cx', d => xScale(xValue(d)))
                .attr('cy', d => yScale(yValue(d)))
                .attr('r', 3)
                .attr('fill', d => color[d['category']])
                .attr('opacity', 0.8)
            // console.log(circleEnter)
            circleUpdates.merge(circleEnter)
                .transition().ease(d3.easeLinear).duration(duration)
                .attr('cx', d => xScale(xValue(d)))
                .attr('cy', d => yScale(yValue(d)));
        }
        // 拆分数组
        const splitArray = function (arr, len){    
            var a_len = arr.length;    
            var result = [];    
            for(var i=0;i<a_len;i+=len){        
                result.push(arr.slice(i,i+len));    
            }    
            return result;}

        d3.csv('/static/data/test.csv').then(data=>{
            // 数据处理
            data.forEach(d => {
                d['x'] = +(d['x']);
                d['y'] = +(d['y']);
            });
           
            sequential = splitArray(data,5000);
           
            // 初始化
            renderInit(data);
            
            // 直接加载
            // renderUpdate(data);
            console.log('开始:')
            console.log(new Date());
            // 循环加载
            let c = 0;
            let intervalId = setInterval(() => {
                if (c >= sequential.length) {
                    console.log('结束了')
                    console.log(new Date());
                    clearInterval(intervalId);
                } else {
                    // console.log(data[c]);
                    // renderUpdate([data[c]]);
                    renderUpdate(sequential[c]);
                    c = c + 1;
                }
            }, duration)
        });
    </script>
</body>
</html>

 

posted @ 2022-06-30 15:09  wish_yang  阅读(190)  评论(0编辑  收藏  举报