<div id="canvasArea"><canvas id="canvas" width="400" height="400"></canvas></div>
  <div class="export_log"><span>click circle...</span></div>
<span class="src">src by http://kkoo.hateblo.jp/entry/2015/02/18/192007</span>
	body
	{
    margin: 0;
		background-color:#cccccc;
	}

	#canvasArea{
		background-color:#ffffff;
    position: absolute;
    top: 0;bottom: 0;left: 0;right: 0;
    margin:auto;
		width:400px;
		height:400px;
	}

span.src{
  display: inline-block;
  width: 100%;
  font-size: 0.8em;
  text-align: center;
}

.export_log{
  span{
    position: absolute;
    top: 4px;
  }
  p{
    margin: 20px 8px;
  }
  position: relative;
  overflow: auto;
  box-sizing: border-box;
  position: fixed;
  bottom: 0;
  width: 100%;
  padding: 10px;
  min-height: 10px;
  background: #000;
  color: #fff;
  height: 10px;
  height: calc(1em + 8px);
  // &:hover{
  //   height: 50%;
  // }
}
var circle;

var MAX = 8;
var RADIUS = 100;
var wobblyPitch = 32.19;
var wobblyPitchGap = 49.82;
var wobblyVol = 38.32;
var wobblyVolGap = 24.91;
var circleColor = "#ffaa00";
var bgColor = "#000000";
var strokeColor = "#ffd175";
var strokeWidth = 4;

var FPS = 60;
var CENTER = {x:200, y:200};
var canvas, ctx, timer, point;
var maskFlag = false;
var img = document.createElement('img');
img.src = 'http://creatorsblog.nijibox.jp/wp/wp-content/uploads/2016/07/doya_cat_s.png';

var Point = function(c, r, rota)
{
  this.x, this.y;
  this.centerX = c.x;
  this.centerY = c.y;
  this.radian = rota * (Math.PI / 180);
  this.radius = r;

  this.speed = Math.random() * 10 * (wobblyPitchGap / 50) + 5 * (wobblyPitch / 50);
  this.r = Math.random() * 0.1 * (wobblyVolGap / 50) + 1 * (wobblyVol / 50);
  this.rota = 0;

  this.update = function()
  {
    var plus = Math.cos(this.rota * (Math.PI / 180)) * this.r;

    this.radius += plus; 
    var cos = Math.cos(this.radian) * this.radius;
    var sin = Math.sin(this.radian) * this.radius;

    this.x = cos + this.centerX;
    this.y = sin + this.centerY;

    this.rota += this.speed;

    if(this.rota > 360){ this.rota -= 360; };
  }  

}


function initialize()
{
  var rota = 360 / MAX;
  var i;
  for(i = 0; i < MAX; i++)
  {
    point[i] = new Point(CENTER, RADIUS, rota * i);
  }
}


function update()
{
  for(var i = 0; i < MAX; i++)
  {
    point[i].update();
  }
  
  draw();
}


function draw() 
{
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  if(maskFlag == true)
  {
    ctx.drawImage(img, 0, (canvas.width - (RADIUS * 2.5))/2, RADIUS * 4, RADIUS * 2.5);
  }
  ctx.fiiStyle = "rgba(0, 0, 0, 0)";

  ctx.beginPath();

  var xc1 = (point[0].x + point[MAX - 1].x) / 2;
  var yc1 = (point[0].y + point[MAX - 1].y) / 2;

  ctx.moveTo(xc1, yc1);

  for(var i = 0; i < MAX - 1; i++){

    var xc = (point[i].x + point[i + 1].x) / 2;
    var yc = (point[i].y + point[i + 1].y) / 2;

    ctx.quadraticCurveTo(point[i].x, point[i].y, xc, yc)
  }

  ctx.quadraticCurveTo(point[i].x, point[i].y, xc1, yc1);

  if(maskFlag == true)
  {
    ctx.strokeStyle = circleColor;
    ctx.fillStyle = bgColor;
    ctx.lineWidth = strokeWidth * 2;
    ctx.rect(0, 0, canvas.width, canvas.height)
    
    if(strokeWidth > 0)
    {
      ctx.stroke();
    }
    
    ctx.closePath();
    ctx.fill("evenodd");
  }
  else
  {
    ctx.strokeStyle = strokeColor;
    ctx.fillStyle = circleColor;
    ctx.lineWidth = strokeWidth;
    ctx.closePath();
    ctx.fill();
    
    if(strokeWidth > 0)
    {
      ctx.stroke();
    }
    
  }

}


function changeFlag()
{
  maskFlag = (maskFlag) ? false : true;
  if(maskFlag == true)
  {  
    MAX = 74;
    RADIUS = 116.91;
    wobblyPitch = 90.44;
    wobblyPitchGap = 72.79;
    wobblyVol = 176.46;
    wobblyVolGap = 39.7;
  }
  else
  {
    MAX = 8;
    RADIUS = 100;
    wobblyPitch = 32.19;
    wobblyPitchGap = 49.82;
    wobblyVol = 38.32;
    wobblyVolGap = 24.91;
  }
  point = [];
  initialize();
}


$("#canvasArea").css("background-color",bgColor);

window.onload = function() 
{
  canvas = document.getElementById("canvas");
  ctx = canvas.getContext("2d");
  point = [];
  initialize();
  timer = setInterval(update, 1000 / FPS);
};

window. addEventListener("click", changeFlag);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.0/dat.gui.min.js