为什么我的文本没有显示在svg轴标签中? (D3保证金惯例)

时间:2018-06-21 15:36:27

标签: d3.js svg

这是一个散点图,显示按体积(x)和IBU(y)的酒精含量的啤酒。我无法显示轴标签。我检查了DOM,并且文本在树中,但是由于某种原因,它没有显示在屏幕上。

对于y标签,边距似乎不起作用,对于x,它位于我想要的位置,但是我根本看不到任何文本。

const dataFiles = ['https://raw.githubusercontent.com/inspectordanno/beer_components/master/scatterplot/data/beers.csv', 'https://raw.githubusercontent.com/inspectordanno/beer_components/master/scatterplot/data/breweries.csv']; //data files to be parsed

const promises = []; //empty array which will contain the promises

dataFiles.forEach(url => {
  promises.push(d3.csv(url)); //this parses each csv file and pushes it to the array
});


//dimensions and margins of plot
const margin = {
    top: 10,
    right: 30,
    bottom: 30,
    left: 60
  },
  width = 960 - margin.left - margin.right,
  height = 500 - margin.top - margin.bottom,
  padding = 30;

const svg = d3.select('body')
  .append('svg')
  .attr('width', width)
  .attr('height', height);

Promise.all(promises).then(data => { //here, I am combining the two arrays in the promise into one big array of beer objects
  data[0].forEach(beer => {
    const breweryid = beer.brewery_id;
    data[1].forEach(brewery => {
      if (parseInt(breweryid) == parseInt(brewery.id)) {
        beer.brewery_name = brewery.name;
        beer.brewery_city = brewery.city;
        beer.brewery_state = brewery.state;
      }
    });
  });
  let beers = data[0]; //beer data

  const xScale = d3.scaleLinear()
    .domain([0, d3.max(beers, d => d.abv)])
    .range([padding, width - padding *2]);

  const yScale = d3.scaleLinear()
    .domain([0, d3.max(beers, d => d.ibu)])
    .range([height - padding, padding]);

  const xAxis = d3.axisBottom()
    .scale(xScale)
    .ticks(10) //ask steven
    .tickFormat(d3.format(',.1%'));

    const yAxis = d3.axisLeft()
      .scale(yScale)
      .ticks(10); //ask steven
      // .tickFormat

    svg.selectAll('circle')
      .data(beers)
      .enter()
      .append('circle')
      .attr('cx', d => {
        return xScale(d.abv);
      })
      .attr('cy', d => {
        return yScale(d.ibu);
      })
      .attr('r', 1)
      .attr('fill', 'steelblue')
      .on('mouseover', d => console.log(d))

    //Create X axis
    svg.append("g")
      .attr("class", "axis")
      .attr("transform", "translate(0," + (height - padding) + ")")
      .call(xAxis);

    //text label for x axis
    svg.append("text")
      .attr("transform", `translate(${(width/2)}, ${height + margin.top * 4})`)
      .style("text-anchor", "middle")
      .text("Alcohol by Volume");

      // text label for the y axis
    svg.append("text")
        .attr("transform", "rotate(-90)")
        .attr('y', 0 - margin.left * .75)
        .attr('x', 0 - (height/2))
        .style("text-anchor", "middle")
        .text("IBU")

    //Create Y axis
    svg.append("g")
      .attr("class", "axis")
      .attr("transform", "translate(" + padding + ",0)")
      .call(yAxis);

}) //end .then of promise
  .catch(err => console.log(err)); // catching error in promises
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script src="main.js" charset="utf-8"></script>
  </body>
</html>

1 个答案:

答案 0 :(得分:3)

处理边距,尺寸,填充和平移的方式毫无意义。例如,您设置了margin对象的属性,但是SVG的宽度和高度仅减去了这些值。

我个人既不是这种模式的用户,也不是其粉丝(Mike Bostock称margin convention),但这是您可以做到的:

首先,像您一样设置边距,并定义widthheight。然后,添加用于设置SVG尺寸的边距:

.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)

最后,附加一个<g>元素,并使用margin.leftmargin.top对其进行翻译:

.append("g")
.attr("transform", "translate(" + margin.left + ","+ margin.top + ")");

这是您所做的更改(以及更改轴的平移)的代码:

const dataFiles = ['https://raw.githubusercontent.com/inspectordanno/beer_components/master/scatterplot/data/beers.csv', 'https://raw.githubusercontent.com/inspectordanno/beer_components/master/scatterplot/data/breweries.csv']; //data files to be parsed

const promises = []; //empty array which will contain the promises

dataFiles.forEach(url => {
  promises.push(d3.csv(url)); //this parses each csv file and pushes it to the array
});


//dimensions and margins of plot
const margin = {
    top: 10,
    right: 30,
    bottom: 200,
    left: 100
  },
  width = 960 - margin.left - margin.right,
  height = 500 - margin.top - margin.bottom;

const svg = d3.select('body')
  .append('svg')
  .attr('width', width + margin.left + margin.right)
  .attr('height', height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + ","+ margin.top + ")");

Promise.all(promises).then(data => { //here, I am combining the two arrays in the promise into one big array of beer objects
  data[0].forEach(beer => {
    const breweryid = beer.brewery_id;
    data[1].forEach(brewery => {
      if (parseInt(breweryid) == parseInt(brewery.id)) {
        beer.brewery_name = brewery.name;
        beer.brewery_city = brewery.city;
        beer.brewery_state = brewery.state;
      }
    });
  });
  let beers = data[0]; //beer data

  const xScale = d3.scaleLinear()
    .domain([0, d3.max(beers, d => d.abv)])
    .range([0, width]);

  const yScale = d3.scaleLinear()
    .domain([0, d3.max(beers, d => d.ibu)])
    .range([height, 0]);

  const xAxis = d3.axisBottom()
    .scale(xScale)
    .ticks(10) //ask steven
    .tickFormat(d3.format(',.1%'));

    const yAxis = d3.axisLeft()
      .scale(yScale)
      .ticks(10); //ask steven
      // .tickFormat

    svg.selectAll('circle')
      .data(beers)
      .enter()
      .append('circle')
      .attr('cx', d => {
        return xScale(d.abv);
      })
      .attr('cy', d => {
        return yScale(d.ibu);
      })
      .attr('r', 1)
      .attr('fill', 'steelblue')
      .on('mouseover', d => console.log(d))

    //Create X axis
    svg.append("g")
      .attr("class", "axis")
      .attr("transform", "translate(0," + (height) + ")")
      .call(xAxis);

    //text label for x axis
    svg.append("text")
      .attr("transform", `translate(${(width/2)}, ${height + margin.top * 4})`)
      .style("text-anchor", "middle")
      .text("Alcohol by Volume");

      // text label for the y axis
    svg.append("text")
        .attr("transform", "rotate(-90)")
        .attr('y', 0 - margin.left * .75)
        .attr('x', 0 - (height/2))
        .style("text-anchor", "middle")
        .text("IBU")

    //Create Y axis
    svg.append("g")
      .attr("class", "axis")
      .call(yAxis);

}) //end .then of promise
  .catch(err => console.log(err)); // catching error in promises
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script src="main.js" charset="utf-8"></script>
  </body>
</html>