首页 > 解决方案 > 如何通过按散点图中的更新按钮来更改(过渡)每个圆的半径?

问题描述

我是 d3-v5 的新手,并试图用更新按钮创建一个基本的散点图。

我使用 , 创建了一个包含 10 个随机(介于 0 到 100 之间)数据的散点图Math.floor(Math.random() *100),并cx使用cy更新按钮进行了很好的更改。但是,axis(x, y) 和半径的过渡没有正确改变..

x 和 y 轴都应更改为cxcy更改,但事实并非如此。

以下代码是带有更新功能的 HTML 脚本,

<script>
  //Scatter Plot
  //Creating data
  let data1 = [
      {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
      {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
      {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
      {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
      {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
      {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
      {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
      {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
      {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
      {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)}
  ]


  //Creating svg, margin, width, height
  let svg1 = d3.select("#svg1")
  let margin1 = 30;
  let width1 = 500 - 2 * margin1;
  let height1 = 500 - 2 * margin1;

  //Creating xScale and yScale
  let xScale1 = d3.scaleLinear()
      .range([0, width1])
      .domain([d3.min(data1, d=>d.x_val), d3.max(data1, d=>d.x_val)])
  let yScale1 = d3.scaleLinear()
      .range([height1, 0])
      .domain([d3.min(data1, d=>d.y_val), d3.max(data1, d=>d.y_val)])

  let plot1 = svg1.append('g')
      .attr('transform', 'translate(30, 30)')

  plot1.append('g')
    .attr('transform', 'translate(0, 440)')
    .call(d3.axisBottom(xScale1));
  plot1.append('g')
    .call(d3.axisLeft(yScale1));

  let colorScale1 = d3.scaleOrdinal(d3.schemeCategory10)

  plot1.selectAll()
    .data(data1)
    .enter()
    .append('circle')
    .attr('cx', (d) => xScale1(d.x_val))
    .attr('cy', (d) => yScale1(d.y_val))
    .attr('r', 5)
    .attr('height', height1)
    .attr('width', width1)

  //Putting colors on the bar
  plot1.selectAll('circle')
      .style('fill', d => colorScale1(d.x_val))
      .on('mouseenter', function(){
        d3.select(this)
          .transition()
          .duration(300)
          .attr('r', 15)
          .style('fill', 'lightblue')
      })
      .on('mouseleave', function(){
        d3.select(this)
          .transition()
          .duration(300)
          .attr('r', 5)
          .style('fill', d => colorScale1(d.x_val))
      })
  function updateData(){
    //For updating scatter plot============================================
    let data1 = [
        {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
        {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
        {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
        {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
        {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
        {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
        {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
        {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
        {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)},
        {x_val: Math.floor(Math.random() * 100), y_val: Math.floor(Math.random() * 100)}
    ]
    //Creating xScale and yScale
    let xScale1 = d3.scaleLinear()
        .range([0, width1])
        .domain([d3.min(data1, d=>d.x_val), d3.max(data1, d=>d.x_val)])
    let yScale1 = d3.scaleLinear()
        .range([height1, 0])
        .domain([d3.min(data1, d=>d.y_val), d3.max(data1, d=>d.y_val)])

    let u1 = plot1.selectAll('circle')
        .data(data1)
    u1
      .enter()
      .append('circle')
      .merge(u1)
      .transition()
      .duration(1000)
        .attr('cx', (d) => xScale1(d.x_val))
        .attr('cy', (d) => yScale1(d.y_val))
        .attr('r', Math.floor(Math.random() * 30)
        .attr('height', height1)
        .attr('width', width1)
}

这是我创建的带有更新按钮的散点图图像

带有更新按钮的散点图

我应该从代码中修复什么..?是因为selectAll吗?

请帮帮我。。

谢谢。

标签: javascriptd3.jsscatter-plot

解决方案


半径的过渡工作正常。但是,如果您想为每个圆使用不同的半径,而不是:

.attr('r', Math.floor(Math.random() * 30)

它应该是:

.attr('r', function() {
    return Math.floor(Math.random() * 30)
})

这是您进行更改的代码:

 let data1 = [{
     x_val: Math.floor(Math.random() * 100),
     y_val: Math.floor(Math.random() * 100)
   },
   {
     x_val: Math.floor(Math.random() * 100),
     y_val: Math.floor(Math.random() * 100)
   },
   {
     x_val: Math.floor(Math.random() * 100),
     y_val: Math.floor(Math.random() * 100)
   },
   {
     x_val: Math.floor(Math.random() * 100),
     y_val: Math.floor(Math.random() * 100)
   },
   {
     x_val: Math.floor(Math.random() * 100),
     y_val: Math.floor(Math.random() * 100)
   },
   {
     x_val: Math.floor(Math.random() * 100),
     y_val: Math.floor(Math.random() * 100)
   },
   {
     x_val: Math.floor(Math.random() * 100),
     y_val: Math.floor(Math.random() * 100)
   },
   {
     x_val: Math.floor(Math.random() * 100),
     y_val: Math.floor(Math.random() * 100)
   },
   {
     x_val: Math.floor(Math.random() * 100),
     y_val: Math.floor(Math.random() * 100)
   },
   {
     x_val: Math.floor(Math.random() * 100),
     y_val: Math.floor(Math.random() * 100)
   }
 ]


 d3.select("button").on("click", updateData)

 //Creating svg, margin, width, height
 let svg1 = d3.select("#svg1")
 let margin1 = 30;
 let width1 = 500 - 2 * margin1;
 let height1 = 500 - 2 * margin1;

 //Creating xScale and yScale
 let xScale1 = d3.scaleLinear()
   .range([0, width1])
   .domain([d3.min(data1, d => d.x_val), d3.max(data1, d => d.x_val)])
 let yScale1 = d3.scaleLinear()
   .range([height1, 0])
   .domain([d3.min(data1, d => d.y_val), d3.max(data1, d => d.y_val)])

 let plot1 = svg1.append('g')
   .attr('transform', 'translate(30, 30)')

 plot1.append('g')
   .attr('transform', 'translate(0, 440)')
   .call(d3.axisBottom(xScale1));
 plot1.append('g')
   .call(d3.axisLeft(yScale1));

 let colorScale1 = d3.scaleOrdinal(d3.schemeCategory10)

 plot1.selectAll()
   .data(data1)
   .enter()
   .append('circle')
   .attr('cx', (d) => xScale1(d.x_val))
   .attr('cy', (d) => yScale1(d.y_val))
   .attr('r', 5)
   .attr('height', height1)
   .attr('width', width1)

 //Putting colors on the bar
 plot1.selectAll('circle')
   .style('fill', d => colorScale1(d.x_val))
   .on('mouseenter', function() {
     d3.select(this)
       .transition()
       .duration(300)
       .attr('r', 15)
       .style('fill', 'lightblue')
   })
   .on('mouseleave', function() {
     d3.select(this)
       .transition()
       .duration(300)
       .attr('r', 5)
       .style('fill', d => colorScale1(d.x_val))
   })

 function updateData() {
   //For updating scatter plot============================================
   let data1 = [{
       x_val: Math.floor(Math.random() * 100),
       y_val: Math.floor(Math.random() * 100)
     },
     {
       x_val: Math.floor(Math.random() * 100),
       y_val: Math.floor(Math.random() * 100)
     },
     {
       x_val: Math.floor(Math.random() * 100),
       y_val: Math.floor(Math.random() * 100)
     },
     {
       x_val: Math.floor(Math.random() * 100),
       y_val: Math.floor(Math.random() * 100)
     },
     {
       x_val: Math.floor(Math.random() * 100),
       y_val: Math.floor(Math.random() * 100)
     },
     {
       x_val: Math.floor(Math.random() * 100),
       y_val: Math.floor(Math.random() * 100)
     },
     {
       x_val: Math.floor(Math.random() * 100),
       y_val: Math.floor(Math.random() * 100)
     },
     {
       x_val: Math.floor(Math.random() * 100),
       y_val: Math.floor(Math.random() * 100)
     },
     {
       x_val: Math.floor(Math.random() * 100),
       y_val: Math.floor(Math.random() * 100)
     },
     {
       x_val: Math.floor(Math.random() * 100),
       y_val: Math.floor(Math.random() * 100)
     }
   ]
   //Creating xScale and yScale
   let xScale1 = d3.scaleLinear()
     .range([0, width1])
     .domain([d3.min(data1, d => d.x_val), d3.max(data1, d => d.x_val)])
   let yScale1 = d3.scaleLinear()
     .range([height1, 0])
     .domain([d3.min(data1, d => d.y_val), d3.max(data1, d => d.y_val)])

   let u1 = plot1.selectAll('circle')
     .data(data1)
   u1
     .enter()
     .append('circle')
     .merge(u1)
     .transition()
     .duration(1000)
     .attr('cx', (d) => xScale1(d.x_val))
     .attr('cy', (d) => yScale1(d.y_val))
     .attr('r', function() {
       return Math.floor(Math.random() * 30)
     })
     .attr('height', height1)
     .attr('width', width1)
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<button>Update</button>
<br>
<svg id="svg1" width="600" height="600"></svg>


推荐阅读