1

I am learning D3.js. I wrote following code which moves the circle on click. I want to move this circle forward (+100px) from its current position on every click.

I want to do it without CSS

Following is my code

var svgContainer = d3.select("body").append("svg").attr("id", "root")
  .attr("width", 500)
  .attr("height", 500).append("g")


//Draw the Circle
var circle = svgContainer.append("circle")
  .attr("id", "Zubi")
  .attr("cx", 100)
  .attr("cy", 30)
  .attr("r", 20)
  .on("click", function() {
    d3.select(this)
      .transition()
      .duration(3000)
      .style("fill", "red")
      .attr("cx", 100)
  })
//.attr("transform", "translate(200,200)")})
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
Zubair
  • 119
  • 8

1 Answers1

2

The easiest way to achieve what you want is using a getter (selection.attr("cx")) to get the current position and increasing it. You can also use a translate, but since you're a D3 learner using the circle's cx attribute is probably easier to understand.

Here is a demo, each click increases 50px:

const circle = d3.select("circle")
  .on("click", function() {
    d3.select(this)
      .transition()
      .attr("cx", +d3.select(this).attr("cx") + 50)
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="100">
  <circle cx="50" cy="50" r="30" fill="teal"></circle>
</svg>

Have in mind that the getter always returns a string, so you have to coerce it to a number.

Also, since you have just one element in the selection and it has a name, you don't need d3.select(this):

const circle = d3.select("circle")
  .on("click", function() {
    circle.transition()
      .attr("cx", +circle.attr("cx") + 50)
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="100">
  <circle cx="50" cy="50" r="30" fill="teal"></circle>
</svg>
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
  • Hi Gerardo, Many thanks. I almost exactly tried the same technique few minutes before your answer. Just missed the "+" can you tell how it affects the result My trial .attr("cx", d3.select(this).attr("cx") + 50) Your code .attr("cx", + d3.select(this).attr("cx") + 50) Please also show me the translate method. I know a bit of SVGs but am new to D3. Many thanks again – Zubair Oct 29 '19 at 06:00
  • @Zubair the problem with the translate is that, after getting the `translate` string, you'll have to parse it, which can be a bit complicated. Please have a look at this answer: https://stackoverflow.com/q/38224875/5768908 – Gerardo Furtado Oct 29 '19 at 06:31