ギアにペンを差し込んでグルグルまわるやつ

'''


HTML <a class="keyword" href="http://d.hatena.ne.jp/keyword/canvas">canvas</a>



















  1. -------- Option ---------









'''

<!DOCTYPE html>
<meta charset="UTF-8">
<title>HTML canvas </title>
<style>
ol li label { display: inline-block; width: 10em; padding: 0 1ex; }
ol li { margin: 2px; list-style: none; }
ol li label, ol li input { border: 2px silver ridge; border-radius: 5px; }
</style>
<body>
<form id="STATE">
  <ol>
    <li>
      <label>Aria</label>
      <input type="number" value="1200" step="50" min="50" max="10000">
    <li>
      <label>B:radius</label>
      <input type="number" value="352" min="0" max="5000">
    <li>
      <label>B:offset</label>
      <input type="number" value="0.52" min="0.01" max="1" step=".01">
    <li>
      <label>Line color</label>
      <select>
        <option value="rgba(0,0,0,.3)">Gray</option>
        <option value="rgba(255,0,0,.2)">Red</option>
        <option value="rgba(0,128,0,.2)">Green</option>
        <option value="rgba(0,0,255,.2)">Blue</option>
        <option value="rgba(128,0,255,.2)" selected>Violet</option>
      </select>
    <li>
      <label>Line speed</label>
      <select>
        <option value="1">Slow</option>
        <option value="5">Normal</option>
        <option value="25" selected>Early</option>
        <option value="100">High speed</option>
      </select>
    </li>
    <li>-------- Option ---------
    </li>
    <li>
      <label>C:radius</label>
      <input type="number" value="1" min="1" max="20">
    <li>
      <label>C:offset</label>
      <input type="number" value="0" min="0" max="1" step=".03" max="1">
  </ol>
</form>
<canvas width="1200" height="1200"></canvas>

<script>

//-----------------------------------------------

class Canvas {
  constructor (e, area, color = 'rgba(0,0,0,.5)') {
    this.canvas = e;
    this.ctx = e.getContext ('2d');
    this.color = color;
    this.area = area;
    this.m = null;
  }

  cls () {
    let { ctx, canvas } = this;
    ctx.clearRect (0, 0, canvas.width, canvas.height);
    return this;
  }

  set area (p) {
    if (p) {
      let { ctx, canvas } = this;
      [canvas.width, canvas.height] = p.value;
      this.m = null;
      ctx.translate (canvas.offsetWidth / 2, canvas.offsetHeight / 2);
    }
  }

  set color (rgba) {
    this.ctx.strokeStyle = rgba;
  }

  line (p) {
    let {ctx, m} = this;
    if (null === m) {
      ctx.moveTo (...p.value);      
    }
    else {
      ctx.beginPath ();
      ctx.moveTo (...m.value);
      ctx.lineTo (...p.value);
      ctx.stroke ();
    }
    this.m = p;
    return this;
  }
}

//-----------------------------------------------

class P {
  #p = [ ];
  constructor (a) { this.#p = a; }
  add (q) { return new this.constructor (q.value.map ((a,i)=> this.#p[i]+a)) }
  sub (q) { return new this.constructor (q.value.map ((a,i)=> this.#p[i]-a)) }
  get value () { return this.#p }
  set value (p) { this.#p = p }
}

//-----------------------------------------------

class Circle {
  #rad = null; //ラジアン
  #c = null; //円周

  constructor (radius = 1, offset = 1/* (%) */, rad = 0) {
    this.radius = radius;
    this.offset = offset;
    this.#rad = rad;
    this.#c = 2 * Math.PI * radius;
  }

  rotation (n) {
    this.#rad += n / this.#c;
    return this.position;
  }

  get position () {
    let r = this.radius *  this.offset;
    let rad = this.#rad;
    return new P ([Math.sin (rad) * r, Math.cos (rad) * r]);
  }
}

//-----------------------------------------------

let
  CG = new Canvas (document.querySelector ('canvas')),
  C0 = null,
  C1 = null,
  C2 = null,
  ANIME_ID = null,
  PM = [...document.querySelectorAll ('form input[type="number"], form select')],
  STEP = 25,
  SPEED = null;
  

function draw () {
  for (let i = SPEED; i--; )
    CG.line (C0.rotation (STEP).add (C1.rotation (-STEP)).add(C2.rotation(-STEP)));
  requestAnimationFrame (draw);
}

//-----------------------------------------------

function demo () {
  if (ANIME_ID)
    cancelAnimationFrame (ANIME_ID);

  let [a, r, offset, col, sp, gr, go] = PM.map (e=> 'valueAsNumber' in e ? e.valueAsNumber: e.value);
  let r0 = a/2*.95 - ( r * offset);
  CG.area = new P ([a, a]);
  CG.color = col;
  SPEED = +sp;

  C0 = new Circle (r0, 1),
  C1 = new Circle (r, offset);
  C2 = new Circle (gr, go);

  draw ();
}

//-----------------------------------------------

function hndler () { demo (); }
STATE.addEventListener ('change', hndler, false);

demo ();

</script>
    

www.amazon.co.jp