Feb 28, 2017 Design + Creative

Randomizing SVG Shapes

Say we wanted to continuously randomize the radius of a circle. We could kinda fake a random look with just CSS, but let’s go for full-on pseudo random numbers created in JavaScript.

We’re talking SVG here, so here’s our base circle:

<svg viewBox="0 0 100 100">
  <circle id="circle" cx="50" cy="50" r="50" />
</svg>

A little JavaScript function to generate random integers for us within a range:

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

To randomize that radius every second, we could do:

var circle = document.querySelector("#circle");
setInterval(function() {
  circle.setAttribute("r", getRandomInt(5, 50));
}, 1000);

Just for kicks, we could have it transition to the new size in the browsers that support it:

circle {
  transition: r 0.2s;
}

svgcircle1

See the demo.


All SVG shapes are essentially built from numbers, which means all of them are fair game for randomizing.

Imagine a shape with a random-looking jagged bottom like this:

svgshape2

That’s probably normally a <polygon> (straight lines), but it’s just about as easy to draw as a <path>, which will make it transitionable (in Chrome). So let’s do that. Here’s what that path might look like:

<path d="M-4,-4 L1004,-4 L1004,100 L940,161 L617,186 L555,122 L306,179 L17,177 L-4,100 L-4,-4 Z"></path>

Some of those points are fixed and the rest of those points will be randomized. Here’s a diagram:

random-points

Our job now is to generate those random numbers, then assemble them into a string, then replace that string in the DOM (the d attribute of the <path>).

Remember we already have a function for generating random numbers: getRandomInt(). Here’s a simplified concept:

var a = getRandomInt(1, 100);
var b = getRandomInt(1, 100);
var c = getRandomInt(1, 100);

var newString = `${a} ${b} ${c}`;

The trick is to generate and arrange them in the exact format needed for the path syntax. It’s not hard, it’s just a lot of number generation and such. I’ll dump the whole thing here:

var csstricks = {

  init: function() {
    csstricks.randomizeBackgrounds();
  },

  generateRandomPoints: function(minSpread, maxSpread) {
    let points = {};
    points.a = `${getRandomInt(800, 1000)},${getRandomInt(minSpread, maxSpread)}`;
    points.b = `${getRandomInt(600, 800)},${getRandomInt(minSpread, maxSpread)}`;
    points.c = `${getRandomInt(400, 600)},${getRandomInt(minSpread, maxSpread)}`;
    points.d = `${getRandomInt(200, 400)},${getRandomInt(minSpread, maxSpread)}`;
    points.e = `${getRandomInt(0, 200)},${getRandomInt(minSpread, maxSpread)}`;
    return points;
  },

  randomizeHeader: function() {
    let newPoints = csstricks.generateRandomPoints(120, 190);
    let downFacingPoints = `M-4,-4 L1004,-4 L1004,100 L${newPoints.a} L${newPoints.b} L${newPoints.c} L${newPoints.d} L${newPoints.e} L-4,100 L-4,-4 Z`;
    $("#jagged-top").attr("d", downFacingPoints);
  },

  randomizeBackgrounds: function() {
    csstricks.randomizeHeader();
    setInterval(function() {
      csstricks.randomizeHeader();
    }, 2000);
  },

};

csstricks.init();

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

It’s just broken into smaller functions for organizational purposes. In the final version, I also dropped in a more performant version of setInterval.

Here’s the final demo:

See the Pen CSS-Tricks Header by Chris Coyier (@chriscoyier) on CodePen.

Worth a mention: SVG isn’t really “hardware accelerated” like some web graphics are. For example, if you transition an elements transform or opacity properties, you don’t have to be overly worried about performance as those will be transferred to the computers graphics processor, as available. No such luck with SVG here in changing out this path data. You might see pretty intense memory and CPU usage in this demo in Chrome because of the CSS transition we have applied. Without the transition (just the instant changing of shape), performance shouldn’t be much of a concern in any browser.

Have fun randomizing!

About the Author Chris is a web designer and developer. He writes about all things web at CSS-Tricks, talks about all things web at conferences around the world and on his podcast ShopTalk, and co-founded the web coding playground CodePen. More by this Author