'''
'''
<!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>