Cardioid / Nephroid

by PhilQ

HTML

<div id="drawing"></div>

SCSS

*, ::before, ::after { margin: 0; padding: 0; box-sizing: border-box; }

body {
	background: #1f2227;
}

#drawing {
	display: block;
}

svg, canvas {
	display: block;
	margin: 50px auto 0;
	background: #1a1d21;
	// background: #fff;
	// background: transparent;
}

JavaScript

var cnv,
	ctx,
	width = 600,
	height = 600,
	size = 580,
	points = 360,
	factor = 7, // 2 = cardioid, 3 = nephroid
	gradient,
	gradient_angle_offset = 0
;

const radians = (degrees) => (Math.PI / 180) * degrees;
const degrees = (radians) => radians * (180 / Math.PI);

function initCanvas() {
	let div = document.getElementById('drawing');
	cnv = document.createElement('canvas');
	cnv.setAttribute('id', 'canvas1');
	div.appendChild(cnv);
	ctx = cnv.getContext('2d');

	cnv.width = width;
	cnv.height = height;

	ctx.translate(Math.floor(width / 2), Math.floor(height / 2));
	ctx.clearRect(-Math.floor(width / 2), -Math.floor(height / 2), width, height);
	// ctx.clearRect(0, 0, width, height);


	/*
	let dl = document.getElementById('download');
	dl.addEventListener('click', () => {
		var link = document.createElement('a');
		link.download = 'image.png';
		link.href = cnv.toDataURL();
		link.click();
	}, false);
	*/

	/*
	window.addEventListener('keydown', (e) => {
		if (e.code == 'Space') { // e.key == ' '
		} else if (e.code == 'ArrowLeft') {
		} else if (e.code == 'ArrowRight') {
		}
	}, false);
	*/
}

function drawCardioid() {
	// See: https://en.wikipedia.org/wiki/Cardioid#Cardioid_as_envelope_of_a_pencil_of_lines

	// ctx.rotate(Math.PI);
	// gradient_angle_offset = 1 / 12;
	ctx.fillStyle = '#fff';
	ctx.strokeStyle = '#fff';
	ctx.lineWidth = 1;

	let n, x, y, x2, y2;
	for (let i = 0; i < points; i++) {
		n = (factor * i) % points;
		x = 0.5 * size * Math.cos((i / points) * 2 * Math.PI);
		y = 0.5 * size * Math.sin((i / points) * 2 * Math.PI);
		x2 = 0.5 * size * Math.cos((n / points) * 2 * Math.PI);
		y2 = 0.5 * size * Math.sin((n / points) * 2 * Math.PI);

		// Circle at starting point
		/*
		ctx.beginPath();
		ctx.arc(
			x,
			y,
			0.005 * size,
			0, 2 * Math.PI
		);
		ctx.closePath();
		// ctx.fillStyle = 'rgba(255, 255, 255, 1)';
		ctx.fillStyle = 'hsl(' + String((gradient_angle_offset + (i / points)) * 2 * Math.PI) + 'rad, 100%,...