单击按钮后,条形图无法执行转换

时间:2019-01-04 08:44:48

标签: d3.js

我正在绘制带有两个按钮的简单条形图,以基于两个数据集切换图表。

但是,当我单击按钮时,图表不会进行转换。

数据是从csv文件加载的。

party,ge14,latest
PKR,47,50
DAP,42,42
Umno,54,38
GPS,0,19
PAS,18,18
Bersatu,13,16
Independent,3,12
Amanah,11,11
Warisan,8,9
GBS,0,3
Other BN parties,25,2
Upko,0,1

源代码

d3.csv('data/seatcount.csv')
.then(data => {

    const width = 900,
    height = 700,
    margin = 25;

    const svg = d3.select('#bar')
    .append('svg')
    .attr('width', width)
    .attr('height', height)
    .attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
    .attr('preserveAspectRatio', 'xMinYMin')
    .append('g');

    // define scale
    const xScale = d3.scaleBand()
        .domain(data.map(d => d.party))
        .range([margin, (width - margin)])
        .padding(.2);

    const yScale = d3.scaleLinear()
        .domain([0, 60])
        .range([(height - margin), margin]);

    // define axes
    const xAxis = d3.axisBottom(xScale)
        .ticks(12)

    const yAxis = d3.axisLeft(yScale)
        .ticks(6);

    svg.append('g')
        .attr('transform', `translate(0, ${height - margin})`)
        .call(xAxis)
        .style('font-size', '.7em');

    svg.append('g')
        .attr('transform', `translate(${margin}, 0)`)
        .call(yAxis)
        .style('font-size', '.7em');

    // plot columns
    let cols = svg.selectAll('.col')
        .data(data)
        .enter();

    cols.append('rect')
        .attr('x', (d) => xScale(d.party))
        .attr('y', (height - margin))
        .attr('width', xScale.bandwidth())
        .attr('height', 0)
        .style('fill', '#dddddd')
        .transition()
        .delay((d, i) => 100 * i)
        .attr('y', (d) => {
            return yScale(d.latest)
        })
        .attr('height', (d) => (height - margin - yScale(d.latest)));

    // label the bars

    cols.append('text')
        .attr('x', d => {
            return (xScale(d.party) + xScale.bandwidth() / 2);
        })
        .attr('y', d => {
            return (yScale(d.latest) + 13);
        })
        .style('fill', '#333333')
        .attr('text-anchor', 'middle')
        .text(d => d.latest)
        .style('font-size', '.8em')
        .style('visibility', 'hidden')
        .transition()
        .delay((d, i) => 100 * i)
        .style('visibility', 'visible');

    function moveCols(data, period) {

            cols.data(data)
            .transition()
            .attr('x', function(d) { 
                return xScale(d.party);
            })
            .attr('y', function(d) {
                console.log(yScale(d[period]));
                return yScale(d[period]);
            })
            .attr('width', xScale.bandwidth())
            .attr('height', function(d) {
                return (height - margin - yScale(d[period]));
            });

        cols.selectAll('text')
        .remove();

        cols.append('text')
            .attr('x', d => {
                return (xScale(d.party) + xScale.bandwidth() / 2);
            })
            .attr('y', d => {
                return (yScale(d[period]) + 13);
            })
            .style('fill', '#333333')
            .attr('text-anchor', 'middle')
            .text(d => d[period])
            .style('font-size', '.8em')
            .style('visibility', (d, i) => {
                // console.log(d[period]);
                if (d[period] <= 0) {
                    return 'hidden';
                } else {
                    return 'visible';
                }
            });
    }

    d3.select('#latest').on('click', () => {
        moveCols(data, 'latest')
    });

    d3.select('#ge14').on('click', () => {
        moveCols(data, 'ge14')
    })

});

最后,当我单击#latest或#ge14后,只有条形的标签发生了变化,而条形本身没有变化。

控制台中显示错误。

Uncaught TypeError: this.getAttribute is not a function
at ot.<anonymous> (d3.v5.min.js:2)
at ot.e (d3.v5.min.js:2)
at o (d3.v5.min.js:2)
at d3.v5.min.js:2
at fr (d3.v5.min.js:2)
at cr (d3.v5.min.js:2)

1 个答案:

答案 0 :(得分:0)

我已经重新格式化了代码,它可以工作了!我没有抱怨。

const margin = { top: 20, right: 20, bottom: 50, left: 40 },
width = 900
height = 700

const svg = d3.select('#bar')
.append('svg')
.attr('width', width)
.attr('height', height)
.attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
.attr('preserveAspectRatio', 'xMinYMin');


const x = d3.scaleBand()
.rangeRound([0, (width - margin.left - margin.right)])
.padding(0.1);

const y = d3.scaleLinear()
.rangeRound([(height - margin.bottom), 0]);

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

d3.csv('data/seatcount.csv')
.then(data => {

    data.forEach(d => {
        d.party = d.party;
        d.ge14 = +d.ge14;
        d.latest = +d.latest;
    });

    x.domain(data.map(d => d.party));
    y.domain([0, d3.max(data, d => d.latest)]);

    let duration = 1000;

    // define axes
    g.append('g')
        .attr('class', 'axis, x-axis')
        .attr('transform', `translate(0, ${height - margin.bottom})`)
        .call(d3.axisBottom(x));

    g.append('g')
        .attr('class', 'axis, y-axis')
        .call(d3.axisLeft(y));

    // plot columns
    g.selectAll('.col')
        .data(data)
        .enter()
        .append('rect')
        .attr('x', d => x(d.party))
        .attr('y', height - margin.bottom)
        .attr('width', x.bandwidth())
        .attr('height', 0)
        .attr('class', 'col')
        .transition()
        .duration(duration)
        .attr('y', d => y(d.latest))
        .attr('height', d => (height - margin.bottom - y(d.latest)))
        .ease(d3.easeBounce);

    g.selectAll('.label')
        .data(data)
        .enter()
        .append('text')
        .attr('class', 'label')
        .attr('x', d => {
            return (x(d.party) + x.bandwidth() / 2);
        })
        .attr('y', (d, i) => {
            if (d.latest <= 5) {
                return (y(d.latest) - 5);
            } else {
                return (y(d.latest) + 13);
            }
        })
        .text(d => d.latest)
        .style('font-size', '.8em')
        .style('visibility', 'hidden')
        .transition()
        .delay(duration)
        .style('visibility', 'visible');

    function moveCols(data, period) {

        y.domain([0, d3.max(data, d => d[period])]);

        g.select('.y-axis')
        .transition()
        .call(d3.axisLeft(y));

        g.selectAll('.label')
            .remove();

        g.selectAll('.col')
            .data(data)
            .transition()
            .attr('x', d => x(d.party))
            .attr('y', d => y(d[period]))
            .attr('width', x.bandwidth())
            .attr('height', d => (height - margin.bottom - y(d[period])))
            .ease(d3.easeBounce);

        g.selectAll('.label')
            .data(data)
            .enter()
            .append('text')
            .attr('class', 'label')
            .attr('x', d => {
                return (x(d.party) + x.bandwidth() / 2);
            })
            .attr('y', (d, i) => {
                if (d[period] <= 5) {
                    return (y(d[period]) - 5);
                } else {
                    return (y(d[period]) + 13);
                }
            })
            .style('fill', '#333333')
            .attr('text-anchor', 'middle')
            .text(d => d[period])
            .style('font-size', '.8em');
    }

    d3.select('#latest').on('click', () => {
        moveCols(data, 'latest');
    });

    d3.select('#ge14').on('click', () => {
        moveCols(data, 'ge14');
    })

});