d3力未正确应用x比例

问题描述

我想对用d3力从数组中生成的圆应用比例尺。

此代码产生了正确的x轴,但是使用“ goalamount”类产生了许多圆,它们都在屏幕外成千上万个像素。 Goalamount类中应该只有六个圆圈,并且它们都应该缩放到xaxis-我在做什么错了?

const data = [{
    x: 2020,cx: 0,colour: "#69306D",scY: 0,y2: 50,rad: 10,amt: 5000
  },{
    x: 2020,colour: "#247BA0",colour: "#3F762C",y1: 0,colour: "#F25F5C",{
    x: 2022,colour: "#0C3957",y2: 170,{
    x: 2055,colour: "#BF802F",amt: 15000
  }
];

const maxYear = Math.max.apply(Math,data.map(function(o) {
  return o.x;
}));

const svg = d3.select("svg");
const pxX = svg.attr("width");
const pxY = svg.attr("height");
let tickLabelOffset = 170;

let minDotX = Math.min.apply(Math,data.map(function(o) {
  return o.y1;
}))
if (minDotX < -20) {
  tickLabelOffset += minDotX + 20;
}

const makeScale = (arr,accessor,range) => {
  return d3.scaleLinear()
    .domain(d3.extent(arr,accessor))
    .range(range)
    .nice()
}

const thisYear = new Date().getFullYear()

let tickTens = [];
for (let i = thisYear; i < maxYear; i++) {
  if (i % 10 === 0) {
    tickTens.push(i)
  }
}


const scX = makeScale(data,d => d.x,[0,pxX - 200]);
const scX1 = makeScale(data,pxX - 2020]);
const scY = d3.scaleLinear().domain([0,100]).range([0,100]);

const g = d3.axisBottom(scX).tickValues(
  tickTens.map((tickVal) => {
    return tickVal
  })
)

const rad = d3.scaleLinear()
  .domain(d3.extent(data,d => d.rad))
  .range([3,10]);

const amt = d3.scaleLinear()
  .domain(d3.extent(data,d => d.amt))
  .range([20,50]);

for (let dotindex = 0; dotindex < data.length; dotindex++) {
  if (data[dotindex - 1]) {
    if (data[dotindex - 1].x === data[dotindex].x) {
      data[dotindex].scY = data[dotindex - 1].scY - 20
    }
  }
}

const ticked = () => {
  var u = d3.select('svg')
    .append("g")
    .attr("class","goalAmounts")
    .selectAll('goalAmounts')
    .data(data)

  u.enter()
    .append("circle")
    // .attr( "transform","translate(" + 2000 + "," + 50 + ")")
    .attr("r",d => amt(d.amt))
    .merge(u)
    .attr("fill",d => d.colour)
    .attr("cx",d => scX(d.x))
    .attr("cy",d => scY(d.y2))

  u.exit().remove()
}


svg.append("g")
  .attr("transform","translate(" + 50 + "," + (pxY - 200) + ")")
  .call(g)
  .selectAll(".tick text")
  .attr("fill","#7A7A7A")

svg.selectAll("circle")
  .data(data)
  .enter()
  .append("g")
  .attr("class","circles")
  .append("circle")
  .attr("transform","translate(" + 100 + "," + 650 + ")")
  .attr("fill","white")
  .attr("stroke",d => d.colour)
  .attr("stroke-width","2px")
  .attr("cx",d => scX(d.x))
  .attr("cy",d => scY(d.y2))
  .attr("r",d => rad(d.rad));

svg.selectAll(".domain")
  .attr("stroke","#BDBDBD")
  .attr("stroke-width","2px")
  .attr("transform"," + 150 + ")")

svg.selectAll(".tick line")
  .attr("stroke","4px")
  .attr("transform"," + 150 + ")")

svg.selectAll(".tick text")
  .attr("font-size",20)
  .attr("transform"," + tickLabelOffset + ")")
  .attr("font-weight","bold")
  .attr("dy","0.5em")

d3.forceSimulation(data)
  .force('charge',d3.forceManyBody())
  .force('center',d3.forceCenter(pxX / 2,pxY / 2))
  .force('collision',d3.forceCollide().radius(function(d) {
    return d.amt
  }))
  .on('tick',ticked);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div class="App">
  <svg id="demo1" width="1200" height="700">
  </svg>
</div>

解决方法

请改用d3.forceXd3.forceY,以便将节点拉向其预期位置。另外,d3-force填充节点的xy属性,因此您需要使用d.x1或其他方法。 scX(d.x)导致了节点的巨大价值。

const data = [{
    x1: 2020,cx: 0,colour: "#69306D",scY: 0,y2: 50,rad: 10,amt: 5000
  },{
    x1: 2020,colour: "#247BA0",colour: "#3F762C",y1: 0,colour: "#F25F5C",{
    x1: 2022,colour: "#0C3957",y2: 170,{
    x1: 2055,colour: "#BF802F",amt: 15000
  }
];

const maxYear = Math.max.apply(Math,data.map(function(o) {
  return o.x1;
}));

const svg = d3.select("svg");
const pxX = svg.attr("width");
const pxY = svg.attr("height");
let tickLabelOffset = 170;

let minDotX = Math.min.apply(Math,data.map(function(o) {
  return o.y1;
}))
if (minDotX < -20) {
  tickLabelOffset += minDotX + 20;
}

const makeScale = (arr,accessor,range) => {
  return d3.scaleLinear()
    .domain(d3.extent(arr,accessor))
    .range(range)
    .nice()
}

const thisYear = new Date().getFullYear()

let tickTens = [];
for (let i = thisYear; i < maxYear; i++) {
  if (i % 10 === 0) {
    tickTens.push(i)
  }
}

const scX = makeScale(data,d => d.x1,[0,pxX - 200]);
const scX1 = makeScale(data,pxX - 2020]);
const scY = d3.scaleLinear().domain([0,100]).range([0,100]);

const g = d3.axisBottom(scX).tickValues(
  tickTens.map((tickVal) => {
    return tickVal
  })
)

const rad = d3.scaleLinear()
  .domain(d3.extent(data,d => d.rad))
  .range([3,10]);

const amt = d3.scaleLinear()
  .domain(d3.extent(data,d => d.amt))
  .range([20,50]);

for (let dotindex = 0; dotindex < data.length; dotindex++) {
  if (data[dotindex - 1]) {
    if (data[dotindex - 1].x1 === data[dotindex].x1) {
      data[dotindex].scY = data[dotindex - 1].scY - 20
    }
  }
}

const ticked = () => {
  circles
    .attr("cx",d => d.x)
    .attr("cy",d => d.y);
}


svg.append("g")
  .attr("transform","translate(" + 50 + "," + (pxY - 200) + ")")
  .call(g)
  .selectAll(".tick text")
  .attr("fill","#7A7A7A")

const circles = svg.append("g")
  .attr("class","circles")
  .attr( "transform","translate(" + 100 + "," + 100 + ")")
  .selectAll("circle")
  .data(data)
  .enter()
  .append("circle")
  .attr("fill","white")
  .attr("stroke",d => d.colour)
  .attr("stroke-width","2px")
  .attr("cx",d => scX(d.x1))
  .attr("cy",d => scY(d.y2))
  .attr("r",d => rad(d.rad));

svg.selectAll(".domain")
  .attr("stroke","#BDBDBD")
  .attr("stroke-width","2px")
  .attr("transform"," + 150 + ")")

svg.selectAll(".tick line")
  .attr("stroke","4px")
  .attr("transform"," + 150 + ")")

svg.selectAll(".tick text")
  .attr("font-size",20)
  .attr("transform"," + tickLabelOffset + ")")
  .attr("font-weight","bold")
  .attr("dy","0.5em")

d3.forceSimulation(data)
  .force("x",d3.forceX(d => scX(d.x1)))
  .force("y",d3.forceY(d => scY(d.y2)))
  .force('collision',d3.forceCollide().radius(d => rad(d.rad)))
  .on("tick",ticked);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div class="App">
  <svg id="demo1" width="1200" height="700">
  </svg>
</div>

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...