如何创建具有不同大小d3.js的分组条形图

时间:2019-05-24 00:30:11

标签: javascript node.js d3.js

我正在创建分组的条形图,但是我的分组大小不一样。我的所有数据都有一个对象数组(array1)。

我正在创建一张地图,每组的大小与这篇文章相同:Making a grouped bar chart when my groups are varied sizes?

创建栏时遇到很多麻烦,我无法使用发布代码。

我还需要创建x和y线并将数字放在小节上方,这对我来说非常困难,因为我对node.js和d3.js不满意,如果有人可以帮助我,我将不胜感激我。

(注意:我不会说英语,所以我使用了谷歌翻译器)

这是我的数组:

const array1 = [
     {name: 'john', lastName: 'smith', amount: 2},
     {name: 'john', lastName: 'white', amount: 1},
     {name: 'mark', lastName: 'smith', amount: 1},
     {name: 'mary', lastName: 'brown', amount: 1}
]

这是我的代码:


    //My variables
    const d3 = require('d3')      
    const jsdom = require("jsdom")
    const { JSDOM } = jsdom
    var fs = require('fs')

    const groupKey = 'name'

    const keys = ['smith', 'white', 'brown']

    const width=800

    const margin = {top: 10, right: 10, bottom: 20, left: 40}

    const height = 600

    const y = d3.scaleLinear()
      .domain([0, d3.max(data, d => d3.max(keys, key => d[key]))]).nice()
      .rangeRound([height - margin.bottom, margin.top])  

    const x1 = d3.scaleBand()
        .domain(keys)
        .rangeRound([0, x0.bandwidth()])
        .padding(0.05)
    const x0 = d3.scaleBand()
      .domain(data.map(d => d[groupKey]))
      .rangeRound([margin.left, width - margin.right])
      .paddingInner(0.1)

    const color = d3.scaleOrdinal()
      .range(["#054a7f", "#0f527f", "#347180", "#5e9381", "#72a381", "#89b581", "#ff8c00"])

    const xAxis = g => g
      .attr("transform", `translate(0,${height - margin.bottom})`)
      .call(d3.axisBottom(x0).tickSizeOuter(0))
      .call(g => g.select(".domain").remove())

    const yAxis = g => g
      .attr("transform", `translate(${margin.left},0)`)
      .call(d3.axisLeft(y).ticks(null, "s"))
      .call(g => g.select(".domain").remove())
      .call(g => g.select(".tick:last-of-type text").clone()
        .attr("x", 3)
        .attr("text-anchor", "start")
        .attr("font-weight", "bold"))

    const legend = svg => {
      const g = svg
        .attr("transform", `translate(${width*1.2},0)`)
        .attr("text-anchor", "end")
        .attr("font-family", "sans-serif")
        .attr("font-size", 13)
        .selectAll("g")
        .data(color.domain().slice().reverse())
          .join("g")
          .attr("transform", (d, i) => `translate(0,${i * 20})`);

      g.append("rect")
        .attr("x", 19)
        .attr("width", 19)
        .attr("height", 19)
        .attr("fill", color);

      g.append("text")
        .attr("x", 0)
        .attr("y", 9.5)
        .attr("dy", "0.35em")
        .text(d => d);
    }

//Here is the map of groups
var x1s = d3.nest()
      .key(function(d) { return d[groupKey] })
      .rollup(function(d){
        return d3.scaleBand()
              .domain(d.map(function(c){return c.sobrenome}), console.log(d.map(function(c){return c.sobrenome})))
              .rangeRound([0, x0.bandwidth()])
              .padding(0.05)
    }).map(data)

//My document
const window = (new JSDOM(`<html><head></head><body></body></html>`, { pretendToBeVisual: false })).window;

window.d3 = d3.select(window.document)

//My svg object
  var svg = window.d3.select('body')
      .append('div').attr('class', 'container')
      .append('svg')
        .attr('xmlns', 'http://www.w3.org/2000/svg')
        .attr('width', width+200)
        .attr('height', height)
        .attr('transform', 'translate(' + 20 + ',' + 20 + ')')'

//Here is where i create the bars
svg.append("g")
          .selectAll("g")
          .data(data)
          .join("g")
            .attr("transform", d => `translate(${x0(d[groupKey])},0)`)
          .selectAll("rect")
          .data(d => keys.map(key => ({key, value: d[key]})))
          .join("rect")
            .attr("x", d => x1(d.key))
            .attr("y", d => y(d.value))
            .attr("width", x1.bandwidth())
            .attr("height", d => y(0) - y(d.value))
            .attr("fill", d => color(d.key))

//My last try
// svg.append("g")
    //     .selectAll("g")
    //     .data(data)
    //     .join("g")
    //         .attr("transform", d => `translate(${x0(d[groupKey])},0)`)
    //     .enter().append("rect")
    //     .style("fill", function(d, i) {
    //       return color(d.name);
    //     })
    //     .attr("x", 0)
    //     .attr("y", function(d) {
    //       return x0(d.name) + x1s["$"+d.name](d.lastName);
    //     })
    //     .attr("height", function(d) {
    //       return x1s["$"+d.name].bandwidth();
    //     })
    //     .attr("width", function(d) {
    //       return x0(d.amount);
    //     });

//And others
    svg.append("g")
      .call(xAxis)

    svg.append("g")
      .call(yAxis)

    svg.append("g")
      .call(legend)

    const xmlserializer = require('xmlserializer')
    console.log('*** SVG ***')
    console.log(xmlserializer.serializeToString(svg.node()))
    const chartComplete = xmlserializer.serializeToString(svg.node())

    fs.writeFile('chart.svg', chartComplete, function(erro) {
        if(erro) {
            throw erro
        }
        console.log("OK!");
    })
}

0 个答案:

没有答案