2

I have researched this pretty thoroughly on stackoverflow as well as the rest of the internet. The problem I am having is with d3 and having a circle change color each time the mouse is clicked.

The Idea: I have already implemented working code to add a circle each time the mouse is clicked showing where the person clicked. However, I want the color of each circle and thus each click to be different. I have looked into a toggle feature but that doesn't change the color of each circle created via each click.

Here is the code so far:

HTML:    
<svg class="plot">
</svg>

CSS:
.plot 
{
    background-color: #000;
    width: 500px;
    height: 500px;
}

JavaScript:
(function() {
    var svg = d3.select('svg');

    function drawCircle(x, y, size) {
        console.log('Drawing circle at', x, y, size);
        svg.append("circle")
            .style("fill","red")
            .attr("cx", x)
            .attr("cy", y)
            .attr("r", size);
    }

    svg.on('click', function() {
        var coords = d3.mouse(this);
        console.log(coords);
        drawCircle(coords[0], coords[1], 5);
    });


})();

Any help would be great! Also here is the jsfiddle link: https://jsfiddle.net/pwilliams/2yczn6q3/

ParkerWilliams
  • 329
  • 1
  • 3
  • 19

3 Answers3

0

Use this:

svg.style("fill",'#'+Math.floor(Math.random()*16777215).toString(16));

as the function :

'#'+Math.floor(Math.random()*16777215).toString(16);

would return an Hex number from 000000 to FFFFFF.

Ps: 16777215 is FFFFFF in decimale.

Hope this helped you.

yahya el fakir
  • 562
  • 2
  • 12
0

You need to provide a different value for the style("fill", ...) property on each circle. This will cause each new circle to have a different color but will not change the color of existing circles (that is somewhat more complex).

If you want a random selection from a prepared list of colors, you should create an array of colors (by name or hex code) and a function to return a random color. Each time you draw a circle, call the function and it will select and return a color from the array.

Something like so:

var colors = ["red", "green", "blue", "yellow", "orange", "purple", "gray"];

function getColor() {
  return colors[Math.round(Math.random() * colors.length)];
}

(function() {
  var svg = d3.select('svg');

  function drawCircle(x, y, size) {
    console.log('Drawing circle at', x, y, size);
    svg.append("circle")
      .style("fill", getColor())
      .attr("cx", x)
      .attr("cy", y)
      .attr("r", size);
  }

  svg.on('click', function() {
    var coords = d3.mouse(this);
    console.log(coords);
    drawCircle(coords[0], coords[1], 5);
  });


})();
.plot {

  background-color: #000;

  width: 500px;

  height: 500px;

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg class="plot">
</svg>

To use the colors in order, you would just keep a counter like:

var colors = ["red", "green", "blue", "yellow", "orange", "purple", "gray"];
var colorState = 0;

function getColor() {
  var color = colors[colorState];
  colorState = (colorState + 1) % colors.length; // keep it from going OOB
  return color;
}
ssube
  • 47,010
  • 7
  • 103
  • 140
  • I really like how this one works. I was wondering though, if I would be able to have it sequentially go through the array color so that the first dot would be red, the second one green, the third blue, and so on. In what I am using this for I will never exceed 7 or so clicks thus the order for the color would be awesome. Thank you for your help! – ParkerWilliams Apr 30 '15 at 21:25
  • Added an example for sequential colors. It will loop around at the end, but since the `getColor` function is isolated, you can change the behavior in any way you want (loop, ping-pong, count up and ceiling, random every time, etc). – ssube Apr 30 '15 at 21:30
0

With the help of this answer for the random color, here is what you could do:

(function() {
    var svg = d3.select('svg');

    function getRandomColor() {
        var letters = '0123456789ABCDEF'.split('');
        var color = '#';
        for (var i = 0; i < 6; i++ ) {
            color += letters[Math.floor(Math.random() * 16)];
        }
        return color;
    }

    function drawCircle(x, y, size) {
        console.log('Drawing circle at', x, y, size);
        svg.append("circle")
            .style('fill',getRandomColor())
            .attr("cx", x)
            .attr("cy", y)
            .attr("r", size);
    }

    svg.on('click', function() {
        var coords = d3.mouse(this);
        console.log(coords);
        drawCircle(coords[0], coords[1], 5);
    });


})();

I updated you jsFiddle: https://jsfiddle.net/2yczn6q3/19/

Community
  • 1
  • 1
laruiss
  • 3,780
  • 1
  • 18
  • 29