如何使用d3.js在条形图中添加升序-降序排序按钮?

atmip9wb  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(103)

我在想如何在条形图中添加交互功能。
现在,我坚持约程序功能的点击行动使用一个按钮排序升序和降序。
这是我的代码:

const width = 800
const height = 400
const margin = {
    top: 40, 
    bottom: 60, 
    left: 40, 
    right: 10
}
const svg = d3.select("div#chart").append("svg").attr("width", width).attr("height", height)
const elementGroup = svg.append("g").attr("id", "elementGroup").attr("transform", `translate(${margin.left}, ${margin.top})`)
const axisGroup = svg.append("g").attr("id", "axisGroup")
const xAxisGroup = axisGroup.append("g").attr("id", "xAxisGroup").attr("transform", `translate(${margin.left}, ${height - margin.bottom})`)
const yAxisGroup = axisGroup.append("g").attr("id", "yAxisGroup").attr("transform", `translate(${margin.left}, ${margin.top})`)

const x = d3.scaleBand().range([0, width - margin.left - margin.right]).padding(0.1)
const y = d3.scaleLinear().range([height - margin.bottom - margin.top, 0])

const xAxis = d3.axisBottom().scale(x)
const yAxis = d3.axisLeft().scale(y).ticks(5)

d3.csv("WorldCup.csv").then(data => {

  let nest = d3.nest()
  .key(d => d.Winner)
  .entries(data)
nest.map(d => d.values = d.values.length)
console.log(nest)

    
    x.domain(nest.map(d => d.key))
    y.domain([0, d3.max(nest.map(d => d.values))])

    xAxisGroup.call(xAxis)
    yAxisGroup.call(yAxis)

        //Asceding sort

        function sortAscending() {nest.sort((a, b) => d3.ascending(a.values, b.values))
          
          let xLabel = elementGroup.append("text").text("Countries")
          .attr("transform", `translate(${width - margin.right - 30}, ${height - margin.bottom})`)
          .attr("text-anchor", "end").attr("font-weight", 700)
      
          let yLabel = elementGroup.append("text").text("Cups per country")
          .attr("transform", `translate(${-20}, ${-10})`).attr("font-weight", 700)
      
          let elements = elementGroup.selectAll("rect").data(nest)
          elements.enter().append("rect")
              .attr("class", "bar")
              .attr("x", d => x(d.key))
              .attr("width", x.bandwidth())
              .attr("height", d => height - margin.top - margin.bottom - y(d.values))
              .attr("y", d => y(d.values))
        }
        d3.select("#Ascending").on("click", sortAscending)

       //Descending sort

        function sortDescending() {nest.sort((a, b) => d3.descending(a.values, b.values))

          let xLabel = elementGroup.append("text").text("Countries")
          .attr("transform", `translate(${width - margin.right - 30}, ${height - margin.bottom})`)
          .attr("text-anchor", "end").attr("font-weight", 700)
      
          let yLabel = elementGroup.append("text").text("Cups per country")
          .attr("transform", `translate(${-20}, ${-10})`).attr("font-weight", 700)
      
          let elements = elementGroup.selectAll("rect").data(nest)
          elements.enter().append("rect")
              .attr("class", "bar")
              .attr("x", d => x(d.key))
              .attr("width", x.bandwidth())
              .attr("height", d => height - margin.top - margin.bottom - y(d.values))
              .attr("y", d => y(d.values))
        }
        d3.select("#Ascending").on("click", sortDescending)

      })

我尝试了不同的例子。
到目前为止,我才明白这是关于配置一个功能,然后通过“on”将该功能与按钮链接。

uhry853o

uhry853o1#

你已经接近了,但是你必须把第一次用来绘制图的代码和数据排序后需要更新的代码分开。基于您的代码,一个可行的框架是

const height = 400, width = 600;
const margin = {
    top: 40,
    bottom: 60,
    left: 40,
    right: 10
};
const svg = d3.select("div#chart").append("svg").attr("width", width).attr("height", height)
const elementGroup = svg.append("g").attr("id", "elementGroup").attr("transform", `translate(${margin.left}, ${margin.top})`)
const axisGroup = svg.append("g").attr("id", "axisGroup")
const xAxisGroup = axisGroup.append("g").attr("id", "xAxisGroup").attr("transform", `translate(${margin.left}, ${height - margin.bottom})`)
const yAxisGroup = axisGroup.append("g").attr("id", "yAxisGroup").attr("transform", `translate(${margin.left}, ${margin.top})`)

const x = d3.scaleBand().range([0, width - margin.left - margin.right]).padding(0.1)
const y = d3.scaleLinear().range([height - margin.top - margin.bottom, 0])

const xAxis = d3.axisBottom().scale(x)
const yAxis = d3.axisLeft().scale(y).ticks(5)

function drawBarPlot(nest){
    x.domain(nest.map(d => d.key))
    y.domain([0, d3.max(nest.map(d => d.values))])

    xAxisGroup.call(xAxis)
    yAxisGroup.call(yAxis)

    elementGroup.append("text").text("Countries")
        .attr("transform", `translate(${width - margin.right - 30}, ${height - margin.bottom})`)
        .attr("text-anchor", "end").attr("font-weight", 700);

    elementGroup.append("text").text("Cups per country")
        .attr("transform", `translate(${-20}, ${-10})`).attr("font-weight", 700);

    elementGroup.selectAll("rect").data(nest).enter().append("rect")
        .attr("class", "bar")
        .attr("x", d => x(d.key))
        .attr("width", x.bandwidth())
        .attr("height", d => height - margin.top - margin.bottom - y(d.values))
        .attr("y", d => y(d.values));
}

function updateBarPlot(nest){
    x.domain(nest.map(d => d.key));
    xAxisGroup.call(xAxis);
    elementGroup.selectAll("rect").data(nest).call(update => update
        .attr("height", d => height - margin.top - margin.bottom - y(d.values))
        .attr("y", d => y(d.values)));
}

//Ascending sort
function sortAscending(nest) {
    nest.sort((a, b) => d3.ascending(a.values, b.values));
    updateBarPlot(nest);
}

function sortDescending(nest) {
    nest.sort((a, b) => d3.descending(a.values, b.values));
    updateBarPlot(nest);
}

//d3.csv("WorldCup.csv").then(data => {
new Promise(resolve => resolve(d3.csvParse("Year,Winner\n" + "1930,Uruguay\n" + "1934,Italy\n" + "1938,Italy\n" + "1950,Uruguay\n" +
    "1954,Germany\n" + "1958,Brazil\n" + "1962,Brazil\n" + "1966,England\n" + "1970,Brazil\n" +
    "1974,Germany\n" + "1978,Argentina\n" + "1982,Italy\n" + "1986,Argentina\n" + "1990,Germany\n" +
    "1994,Brazil\n" + "1998,France\n" + "2002,Brazil\n" + "2006,Italy\n" + "2010,Spain\n" +
    "2014,Germany\n" + "2018,France\n" + "2022,Argentina\n"))).then(data => {
    let nest = d3.nest()
        .key(d => d.Winner)
        .entries(data)
    nest.map(d => d.values = d.values.length)

    drawBarPlot(nest);

    d3.select("#Ascending").on("click", ()=>sortAscending(nest));
    d3.select("#Descending").on("click", ()=>sortDescending(nest));
});
<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="https://d3js.org/d3-collection.v1.min.js"></script>

<div id="chart"></div>
<button id="Ascending">Ascending</button><button id="Descending">Descending</button>

相关问题