- d = 2000
- rf = .35
svg(viewbox=`${-.5*d} ${-.5*d} ${d} ${d}`)
	defs
		circle(id='vertex' r='8')
		path(id='axis' 
				 d=`M${-.5*d},0 L${.5*d},0`)
	
	g(class='axes')
		use(xlink:href='#axis')
		use(xlink:href='#axis' 
				transform='rotate(90)')
		
	circle(id='ccirc' r=`${rf*d}`)
	
	polygon(id='poly')
	
	line(class='axis--cover' x2=`${.9*rf*d}`)
	
	line(id='radius' x2=`${rf*d}`)
	
	g(id='vertices')
	
	g(class='arc')
		path(class='arc__fill')
		path(class='arc__line')
		text 
	
	circle(id='origin' r='8')
		
form
	input(id='n' type='range' 
				min='3' max='10' value='3')
	label(for='n') number of vertices: 
		span(id='val--n') 3
	hr
	p base angle: 
		span(id='val--a') 120°
View Compiled
$theme-c: #e18728;
$hl-c: #be4c39;

$csyst-c: #ccc;
$circle-c: #555;
$poly-c: $theme-c;
$arc-bg: #d49b00;
$arc-c: $hl-c;
$arc-txt: #9351a6;
$radius-c: $theme-c;
$guide-c: #838383;
$vertex-bg: #d49b00;
$vertex-c: $hl-c;
$vertex-txt: #9351a6;

html { overflow: hidden; }

body { margin: 0; }

svg {
	display: block;
	margin: calc(50vh - 50vmin) auto;
	min-width: 10em; min-height: 10em;
	width: 100vmin; height: 100vmin;
	max-width: 100em; max-height: 100em;
	font-size: 1em;
}

text {
	font: 700 100px monospace;
	opacity: .001;
}

.q1, .q2 { dominant-baseline: hanging; }
.q2, .q3 { text-anchor: end; }

.hidden {
	opacity: .001;
	pointer-events: none;
}

[id='axis'], [id='ccirc'], [id='poly'], 
[id='radius'], .arc__line, 
[id='vertices'] line, [id='vertices'] circle {
	vector-effect: non-scaling-stroke;
}

[id='axis'], .axis--cover {
	fill: $csyst-c;
	stroke: $csyst-c;
	stroke-width: 2;
}

[id='ccirc'] {
	fill: transparent;
	stroke: $circle-c;
	stroke-width: 2;
}

[id='poly'] {
	fill: transparent;
	stroke: $poly-c;
	stroke-width: 4;
}

.arc {
	&__fill {
		fill: lighten($arc-bg, 30%);
	}
	&__line {
		fill: none;
		stroke: $arc-c;
		stroke-width: 4;
		vector-effect: non-scaling-stroke;
	}
	
	text {
		fill: $arc-txt;
		dominant-baseline: middle;
		text-anchor: middle;
	}
}

[id='radius'] {
	stroke: $radius-c;
	stroke-width: 4;
}

[id='vertices'] {
	line {
		stroke: $guide-c;
		stroke-dasharray: 8;
		stroke-width: 2
	}
	
	circle {
		fill: lighten($vertex-bg, 30%);
		stroke: $vertex-c;
		stroke-width: 4;
	}
	
	text {
		fill: $vertex-txt;
	}
}


@media ( min-width: 240px) and 
			 (min-height: 240px) {
	text { opacity: .999; }
}

@media ( min-width: 320px) and 
			 (min-height: 320px) {	
	text { font-size: 80px; }
}

@media ( min-width: 480px) and 
			 (min-height: 480px) {
	text { font-size: 56px; }
}

@media ( min-width: 800px) and 
			 (min-height: 800px) {
	text { font-size: 40px; }
}


/* controls */

$theme-hl: #e18728;

$ctrl-bg: #262626;
$ctrl-ll: #aaa;
$ctrl-hl: $theme-hl;

$track-w: 13em;
$track-h: .25em;

$thumb-d: 1.25em;

@mixin track() {
	width: $track-w; height: $track-h;
	background: $ctrl-ll;
}

@mixin fill() {
	background: $ctrl-hl;
}

@mixin thumb() {
	border: none;
	width: $thumb-d; height: $thumb-d;
	border-radius: 50%;
	background: $ctrl-hl;
}

form {
	position: absolute;
	top: .25em; right: .25em;
	margin: .25em;
	padding: .5em;
	background: $ctrl-bg;
	color: $ctrl-ll;
	font: 1em/1.375em trebuchet ms, sans serif;
	text-align: center;
}

input[type='range'] {
	&, 
	&::-webkit-slider-runnable-track, 
	&::-webkit-slider-thumb {
		-webkit-appearance: none;
	}
	
	display: block;
	margin: 1em auto 0;
	padding: 0;
	width: $track-w; height: 2em;
	background: none;
	font-size: 1em;
	cursor: pointer;
	
	&::-webkit-slider-runnable-track {
		@include track();
	}
	&::-moz-range-track {
		@include track();
	}
	&::-ms-track {
		border: none;
		@include track();
		color: transparent;
	}
	
	&::-moz-range-progress {
		height: $track-h;
		@include fill();
	}
	&::-ms-fill-lower {
		@include fill();
	}
	
	&::-webkit-slider-thumb {
		margin-top: ($track-h - $thumb-d)/2;
		@include thumb();
	}
	&::-moz-range-thumb {
		@include thumb();
	}
	&::-ms-thumb {
		@include thumb();
	}
	
	&::-ms-tooltip { display: none; }
	
	+ label {
		display: block;
	}
		
	&:focus { outline: none; }
}
View Compiled
/* because me lazy */
Object.getOwnPropertyNames(Math).map(function(p) {
  window[p] = Math[p];
});

Node.prototype.setAttrs = function(attr_obj) {
  for(var prop in attr_obj) {
    this.setAttribute(prop, attr_obj[prop]);
  }
};

var NS_URI = 'http://www.w3.org/2000/svg', 
    XLink_NS = 'http://www.w3.org/1999/xlink', 
		DEG_MOTION_SPEED = 3, 
		T_HL = 60, 
		LEN_MOTION_SPEED = 16, 
		V_RADIUS = 8, 
		PULSE_F = .32, 
		RAD_F = PI/180, 
    
		svg = document.querySelector('svg'), 
		vb = svg.getAttribute('viewBox').split(' ')
					.map(function(d) {
						return ~~d;
					}), 
		c_el = document.getElementById('ccirc'), 
		p_el = document.getElementById('poly'), 
		r_el = document.getElementById('radius'), 
		w_el = document.getElementById('vertices'),
		r = ~~c_el.getAttribute('r'), 
		p, curr_off, 
		r_a = .2*r, 
		n_el = document.getElementById('n'), 
		vn_el = document.getElementById('val--n'), 
		va_el = document.getElementById('val--a'), 
		arc_el = document.querySelector('.arc'), 
		arc_f_el = document.querySelector('.arc__fill'), 
		arc_l_el = document.querySelector('.arc__line'), 
		arc_t_el = document.querySelector('.arc text'), 
		n = ~~n_el.value, vertices = [], 
		a_base = 360/n, k = 360%n, 
		a_target = 0, a = 0, idx = 0, 
		r_id = null, t = 0;

var init = function() {
	createPoly();
};

var f = function() {
	var m = ~~n_el.value;
	
	if(m !== n) {
		if(r_id) {
			cancelAnimationFrame(r_id);
			r_id = null;
		}
		
		idx = 0;
		a = 0;
		t = 0;
		n = m;
		a_base = 360/n;
		k = 360%n;
		
		stepDisplay();
		
		vn_el.textContent = n;
				
		va_el.textContent = 
			('' + a_base).slice(0, 5) + '°';	
		
		createPoly();
	}
};

var createPoly = function() {
	var frg = document.createDocumentFragment(), 
			curr_vx, curr_pt, curr_txt, curr_r, 
			x, y, l, q, j1, j2, p_txt ='', 
			rad_a_base = 2*PI/n, rad_a;
	
	vertices = [];
	w_el.textContent = '';
	
	l = 2*r*sin(rad_a_base/2);
	curr_off = p = n*l;
	
	p_el.setAttrs({
		'stroke-dasharray': p, 
		'stroke-dashoffset': curr_off
	});
	
	for(var i = 0; i < n; i++) {
		rad_a = i*rad_a_base;
		q = floor(2*rad_a/PI);
		j1 = floor(q/2);
		j2 = q%2;
		x = r*cos(rad_a);
		y = r*sin(rad_a);
		
		p_txt += x + ',' + y + ' ';
		
		curr_r = document.createElementNS(
			NS_URI, 
			'line'
		);
		curr_r.setAttrs({
			'x2': x, 'y2': y, 'class': 'hidden'
		});
		
		curr_pt = document.createElementNS(
			NS_URI, 
			'circle'
		);
		curr_pt.setAttrs({
			'cx': x, 'cy': y
		});
		
		curr_txt = document.createElementNS(
			NS_URI, 
			'text'
		);
		curr_txt.textContent = 
			(i + '*' + a_base).slice(0, 7) + '°';
		curr_txt.setAttrs({
			'x': x + 2*V_RADIUS*pow(-1, j2 ^ j1), 
			'y': y + 2*V_RADIUS*pow(-1, j1), 
			'class': 'q' + (q + 1)
		});
		
		curr_vx = document.createElementNS(
			NS_URI, 
			'g'
		);
		curr_vx.setAttrs({
			'class': 'hidden'
		});
		
		vertices.push({
			'v': curr_vx, 
			'p': curr_pt, 
			'r': curr_r
		});
		
		curr_vx.appendChild(curr_r);
		curr_vx.appendChild(curr_pt);
		curr_vx.appendChild(curr_txt);
		frg.appendChild(curr_vx);
	}
	
	p_el.setAttribute('points', p_txt.trim());
	
	w_el.appendChild(frg);
	
	constructPoly();
};

var constructPoly = function() {
	r_el.setAttribute('class', '');
	arc_el.setAttribute('class', 'arc');
	pulse();
};

var updateAngle = function() {	
	if(a >= a_target) {
		a = a_target;
		stepDisplay();
		
		cancelAnimationFrame(r_id);
		r_id = null;
		
		pulse();
		return;
	}
	
	a += DEG_MOTION_SPEED;
	stepDisplay();
	
	r_id = requestAnimationFrame(updateAngle);
};

var stepDisplay = function() {
	var sn = (a > 100)?6:5, 
			rad_a = RAD_F*a, 
			x = r_a*cos(rad_a), 
			y = r_a*sin(rad_a), 
			d_txt = 'M' + ~~x + ' ' + ~~y + 'A' + 
							r_a + ' ' + r_a + ' 0 ' + 
							floor(a/180) + ' 0 ' + 
							r_a + ' 0';
		
	r_el.setAttribute(
		'transform', 
		'rotate(' + a + ')'
	);
	arc_l_el.setAttribute('d', d_txt);
	
	d_txt += 'L0,0z';
	
	arc_f_el.setAttribute('d', d_txt);
	
	arc_t_el.setAttribute(
		'transform', 
		'rotate(' + .5*a + ')' + 
		'translate(' + 1.5*r_a + ')' + 
		'rotate(' + -.5*a + ')'
	);
	
	arc_t_el.textContent = 
		('' + a).slice(0, sn) + '°';
};

var pulse = function() {	
	if(t > T_HL) {
		cancelAnimationFrame(r_id);
		r_id = null;
		t = 0;
		if(idx < n) {
			a = ~~a;
			vertices[idx].r.setAttribute('class', '');
			
			if(idx < n - 1) {
				a_target = (++idx)*a_base;
				updateAngle();
			}
			else {
				r_el.setAttribute('class', 'hidden');
				arc_el.setAttribute('class', 'hidden');
				drawPolyLine();
			}
		}
		return;
	}
	
	if(idx < n) {
		if(t === 0) {
			vertices[idx].v.setAttribute('class', '');
		}
		
		vertices[idx].p.setAttribute(
			'r', 
			V_RADIUS*(1.25 + sin(PULSE_F*t))
		);
	}
	
	t++;
	
	r_id = requestAnimationFrame(pulse);
};

var drawPolyLine = function() {
	if(abs(curr_off) < LEN_MOTION_SPEED) {
		curr_off = 0;
		cancelAnimationFrame(r_id);
		r_id = null;
		return;
	}
	
	curr_off -= LEN_MOTION_SPEED;
	p_el.setAttribute(
		'stroke-dashoffset', 
		curr_off
	);
	
	r_id = requestAnimationFrame(drawPolyLine);
};

init();

n_el.addEventListener('change', f, false);
n_el.addEventListener('input', f, false);

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.