如何将X轴值绘制在栏上?

发布于 2025-01-28 08:31:12 字数 860 浏览 2 评论 0原文

我更改了X轴的属性,以将其值绘制在图表的栏上。但是,在我放置代码的任何地方,这些值总是在(“后面”)栏之前绘制,因此我们看不到它。

  //This part of the code is OUTSIDE of the update function (line 44 of the fiddle)
  //append group to plot X axis
  const xAxisGroup = g.append("g")
    .attr("class", "x axis")
    .attr("transform", `translate(0, ${HEIGHT})`)


  //This part of the code is INSIDE the update function (line 92)
  const xAxisCall = d3.axisBottom(x)
  xAxisGroup.call(xAxisCall)
    .selectAll("text")
    .attr("x", "-5") // <<<--- I change this to 50
    .attr("y", "10")
      .attr("text-anchor", "end")
      .attr("transform", "rotate(-45)") // <<<--- I changed this to -90

如何将此值绘制在栏上?

这是修改一个。月值可能在酒吧后面...: - /

I changed the attributes of the X axis to plot its values over the bars of the chart. But anywhere I put the code, the values are always plotted before ("behind") the bars and therefore we cannot see it.

  //This part of the code is OUTSIDE of the update function (line 44 of the fiddle)
  //append group to plot X axis
  const xAxisGroup = g.append("g")
    .attr("class", "x axis")
    .attr("transform", `translate(0, ${HEIGHT})`)


  //This part of the code is INSIDE the update function (line 92)
  const xAxisCall = d3.axisBottom(x)
  xAxisGroup.call(xAxisCall)
    .selectAll("text")
    .attr("x", "-5") // <<<--- I change this to 50
    .attr("y", "10")
      .attr("text-anchor", "end")
      .attr("transform", "rotate(-45)") // <<<--- I changed this to -90

How would be possible to plot this values over the bars instead?

This is the fiddle of the original chart and this is the modified one. The month values may be behind the bars... :-/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

可爱咩 2025-02-04 08:31:12

在SVG中,无论绘制以后都停留在顶部。因此,只需在绘制矩形后附加x轴&lt; g&gt;元素即可。另外,请提高:

xAxisGroup.raise()

这是您的代码,其中包括:

//set general margin, width and height values
const MARGIN = {
  LEFT: 128,
  RIGHT: 8,
  TOP: 32,
  BOTTOM: 128
}
const WIDTH = 400 - MARGIN.LEFT - MARGIN.RIGHT
const HEIGHT = 300 - MARGIN.TOP - MARGIN.BOTTOM

//append svg plot area into div chart area
const svg = d3.select("#chart-area").append("svg")
  .attr("width", WIDTH + MARGIN.LEFT + MARGIN.RIGHT)
  .attr("height", HEIGHT + MARGIN.TOP + MARGIN.BOTTOM)

//append group into svg 
const g = svg.append("g")
  .attr("transform", `translate(${MARGIN.LEFT}, ${MARGIN.TOP})`)

//X label
g.append("text")
  .attr("class", "x axis-label")
  .attr("x", WIDTH / 2)
  .attr("y", HEIGHT + 60)
  .attr("font-size", "20px")
  .attr("text-anchor", "middle")
  .text("Month")

//Y label
g.append("text")
  .attr("class", "y axis-label")
  .attr("x", -(HEIGHT / 2))
  .attr("y", -60)
  .attr("font-size", "20px")
  .attr("text-anchor", "middle")
  .attr("transform", "rotate(-90)")
  .text("Value")

//set scale for X axis
const x = d3.scaleBand()
  .range([0, WIDTH])
  .paddingInner(0.3)
  .paddingOuter(0.2)

//set scale for Y axis
const y = d3.scaleLinear()
  .range([HEIGHT, 0])

//append group to plot X axis
const xAxisGroup = g.append("g")
  .attr("class", "x axis")
  .attr("transform", `translate(0, ${HEIGHT})`)

//append group to plot Y axis
const yAxisGroup = g.append("g")
  .attr("class", "y axis")

//import data
d3.csv("https://raw.githubusercontent.com/dbahiense/sotabook/main/revenues.csv").then(data => {
  //parse values
  data.forEach(d => {
    d.revenue = Number(d.revenue)
    d.profit = Number(d.profit)
  })

  //listen drop-down lists and trigger update function on change
  //state
  d3.select("#state")
    .on("change", function(event, d) {
      update(data)
    })
  //round
  d3.select("#round")
    .on("change", function(event, d) {
      update(data)
    })

  //plot chart on page first load
  update(data)
})

// update chart function
function update(data) {
  //drop-down list listened values
  let state = d3.select("#state").property("value")
  let round = d3.select("#round").property("value")

  //filter data by drop-down list values
  let filteredData = data.filter(function(d) {
    return d.state == state & d.round == round
  })

  //set domains for X and Y axes
  x.domain(filteredData.map(d => d.month))
  y.domain([0, d3.max(filteredData, d => d.revenue)])

  const xAxisCall = d3.axisBottom(x)

  const yAxisCall = d3.axisLeft(y)
  //.tickFormat(d => d + "m")
  yAxisGroup.call(yAxisCall)

  // JOIN new data with old elements.
  const rects = g.selectAll("rect")
    .data(filteredData)

  // EXIT old elements not present in new data.
  rects.exit().remove()

  // UPDATE old elements present in new data.
  rects
    .attr("y", d => y(d.revenue))
    .attr("x", (d) => x(d.month))
    .attr("width", x.bandwidth)
    .attr("height", d => HEIGHT - y(d.revenue))

  // ENTER new elements present in new data.  
  rects.enter().append("rect")
    .attr("y", d => y(d.revenue))
    .attr("x", (d) => x(d.month))
    .attr("width", x.bandwidth)
    .attr("height", d => HEIGHT - y(d.revenue))
    .attr("fill", "steelblue")

  xAxisGroup.raise()
    .call(xAxisCall)
    .selectAll("text")
    .attr("x", "50")
    .attr("y", "10")
    .attr("text-anchor", "end")
    .attr("transform", "rotate(-90)")
}
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="description" content="">
    <title>5.4</title>
    <!-- Bootstrap -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <!-- Custom styling -->
    <link rel="stylesheet" href="css/style.css">
</head>
<body>

    <!-- Bootstrap grid setup -->
    <div class="container">
        <div class="row">
            <select id="state">
                <option value="US">US</option>
                <option value="EU">EU</option>
                <option value="AS">AS</option>
            </select>

            <select id="round">
                <option value="1">1</option>
                <option value="2">2</option>
            </select>
        </div>
        <div class="row">
            <div id="chart-area"></div>
        </div>
    </div>

    <!-- External JS libraries -->
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <!-- Custom JS below-->
</body>
</html>

In an SVG, whatever is painted later stays on top. So, just append your x axis <g> element after painting the rectangles. Alternatively, raise it:

xAxisGroup.raise()

Here's your code with that change:

//set general margin, width and height values
const MARGIN = {
  LEFT: 128,
  RIGHT: 8,
  TOP: 32,
  BOTTOM: 128
}
const WIDTH = 400 - MARGIN.LEFT - MARGIN.RIGHT
const HEIGHT = 300 - MARGIN.TOP - MARGIN.BOTTOM

//append svg plot area into div chart area
const svg = d3.select("#chart-area").append("svg")
  .attr("width", WIDTH + MARGIN.LEFT + MARGIN.RIGHT)
  .attr("height", HEIGHT + MARGIN.TOP + MARGIN.BOTTOM)

//append group into svg 
const g = svg.append("g")
  .attr("transform", `translate(${MARGIN.LEFT}, ${MARGIN.TOP})`)

//X label
g.append("text")
  .attr("class", "x axis-label")
  .attr("x", WIDTH / 2)
  .attr("y", HEIGHT + 60)
  .attr("font-size", "20px")
  .attr("text-anchor", "middle")
  .text("Month")

//Y label
g.append("text")
  .attr("class", "y axis-label")
  .attr("x", -(HEIGHT / 2))
  .attr("y", -60)
  .attr("font-size", "20px")
  .attr("text-anchor", "middle")
  .attr("transform", "rotate(-90)")
  .text("Value")

//set scale for X axis
const x = d3.scaleBand()
  .range([0, WIDTH])
  .paddingInner(0.3)
  .paddingOuter(0.2)

//set scale for Y axis
const y = d3.scaleLinear()
  .range([HEIGHT, 0])

//append group to plot X axis
const xAxisGroup = g.append("g")
  .attr("class", "x axis")
  .attr("transform", `translate(0, ${HEIGHT})`)

//append group to plot Y axis
const yAxisGroup = g.append("g")
  .attr("class", "y axis")

//import data
d3.csv("https://raw.githubusercontent.com/dbahiense/sotabook/main/revenues.csv").then(data => {
  //parse values
  data.forEach(d => {
    d.revenue = Number(d.revenue)
    d.profit = Number(d.profit)
  })

  //listen drop-down lists and trigger update function on change
  //state
  d3.select("#state")
    .on("change", function(event, d) {
      update(data)
    })
  //round
  d3.select("#round")
    .on("change", function(event, d) {
      update(data)
    })

  //plot chart on page first load
  update(data)
})

// update chart function
function update(data) {
  //drop-down list listened values
  let state = d3.select("#state").property("value")
  let round = d3.select("#round").property("value")

  //filter data by drop-down list values
  let filteredData = data.filter(function(d) {
    return d.state == state & d.round == round
  })

  //set domains for X and Y axes
  x.domain(filteredData.map(d => d.month))
  y.domain([0, d3.max(filteredData, d => d.revenue)])

  const xAxisCall = d3.axisBottom(x)

  const yAxisCall = d3.axisLeft(y)
  //.tickFormat(d => d + "m")
  yAxisGroup.call(yAxisCall)

  // JOIN new data with old elements.
  const rects = g.selectAll("rect")
    .data(filteredData)

  // EXIT old elements not present in new data.
  rects.exit().remove()

  // UPDATE old elements present in new data.
  rects
    .attr("y", d => y(d.revenue))
    .attr("x", (d) => x(d.month))
    .attr("width", x.bandwidth)
    .attr("height", d => HEIGHT - y(d.revenue))

  // ENTER new elements present in new data.  
  rects.enter().append("rect")
    .attr("y", d => y(d.revenue))
    .attr("x", (d) => x(d.month))
    .attr("width", x.bandwidth)
    .attr("height", d => HEIGHT - y(d.revenue))
    .attr("fill", "steelblue")

  xAxisGroup.raise()
    .call(xAxisCall)
    .selectAll("text")
    .attr("x", "50")
    .attr("y", "10")
    .attr("text-anchor", "end")
    .attr("transform", "rotate(-90)")
}
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="description" content="">
    <title>5.4</title>
    <!-- Bootstrap -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <!-- Custom styling -->
    <link rel="stylesheet" href="css/style.css">
</head>
<body>

    <!-- Bootstrap grid setup -->
    <div class="container">
        <div class="row">
            <select id="state">
                <option value="US">US</option>
                <option value="EU">EU</option>
                <option value="AS">AS</option>
            </select>

            <select id="round">
                <option value="1">1</option>
                <option value="2">2</option>
            </select>
        </div>
        <div class="row">
            <div id="chart-area"></div>
        </div>
    </div>

    <!-- External JS libraries -->
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    <!-- Custom JS below-->
</body>
</html>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文