Random lines

by Marc Malignan

HTML

<header>
  <div class="field">
    <label for="nb_lines">Nb lines <i>(1~10)</i></label>
    <input id="nb_lines" type="number" value="4" min="1" max="10" />
  </div>
  <div class="field">
    <label for="change_chance">Change chance <i>(0~1)</i></label>
    <input id="change_chance" type="number" value="0.15" step="0.05" min="0" max="1" />
  </div>
  <div class="field">
    <label for="color_range">Color range <i>(0~255)</i></label>
    <input id="color_range" type="number" value="20" min="0" max="255" />
  </div>
  <div class="field">
    <label for="thickness">Thickness <i>(1~10)</i></label>
    <input id="thickness" type="number" value="2" min="1" max="10" />
  </div>
</header>
<canvas id="canvas"></canvas>
<footer>
  <button id="start">START</button>
  <button id="pause">PAUSE</button>
  <button id="stop">STOP</button>
</footer>

SCSS

$color_text: #ccc;
$color_text_dark: #444;
$color_bg: linear-gradient(#2a2a2a, #222);
$color_canvas: #000;

* {
  box-sizing: border-box;
}

body, header, footer {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
}

body, header {
  flex-direction: column;
}

header, footer {
  padding: 10px;
}

body {
  height: 100vh;
  margin: 0;
  background: $color_bg;
  color: $color_text;
  font-family: Arial;
  font-size: 13px;
  
  & > * {
    flex-grow: 1;
    flex-basis: 0;
  }
}

canvas {
  flex-grow: 0;
  margin: 20px 0;
  background: $color_canvas;
  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
  border: 4px solid $color_text_dark;
}

.field {
  width: 270px;
  display: flex;
  align-items: center;
  justify-content: center;
}

label {
  flex-grow: 1;
  margin-right: 20px;
  cursor: pointer;
  
  i {
    color: $color_text_dark;
  }
}

input, button {
  background: none;
  border: 1px solid $color_text_dark;
  color: $color_text;
}

input:hover, input:focus,
button:hover, button:focus {
  border: 1px solid $color_text;
  outline: none;
}

input {
  width: 100px;
  margin: 2px 0;
  padding: 5px;
}

button {
  margin: 0 10px;
  padding: 10px 20px;
  cursor: pointer;
}

JavaScript

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const SIZE = 400;
canvas.width = SIZE;
canvas.height = SIZE;

const THICKNESS = 7;

const random = (min, max) =>
	Math.floor(Math.random() * (max - min)) + min;

const getNewDirection = (position, direction) => {
	let forbiddenDirections = [];
  if (position[0] === 0) forbiddenDirections.push(3);
  if (position[1] === 0) forbiddenDirections.push(0);
  if (position[0] === SIZE - 1) forbiddenDirections.push(1);
  if (position[1] === SIZE - 1) forbiddenDirections.push(2);
  
  const changeChance = parseFloat(document.getElementById('change_chance').value);
  
  if (
  	!forbiddenDirections.includes(direction) &&
    Math.random() > changeChance
  ) {
  	return direction;
  }
  
  let newDirection;
  while (
    newDirection === undefined ||
    direction === 0 && newDirection === 2 ||
    direction === 1 && newDirection === 3 ||
    direction === 2 && newDirection === 0 ||
    direction === 3 && newDirection === 1 ||
    forbiddenDirections.includes(newDirection)
  ) {
    newDirection = random(0, 4);
  }
  return newDirection;
}

const getNewPosition = (position, direction) => {
  switch(direction) {
		case 0: return [position[0], position[1] - 1];
    case 1: return [position[0] + 1, position[1]];
    case 2: return [position[0], position[1] + 1];
    case 3: return [position[0] - 1, position[1]];
    default: return position;
  }
}

const randomColor = (c) => {
	const colorRange = parseInt(document.getElementById('color_range').value);
  
  let lowest = Math.max(c - Math.round(colorRange / 2), 0);
  let highest = Math.min(c + Math.round(colorRange / 2), 255);
  
  if (lowest === 0) highest = colorRange;
  if (highest === 255) lowest = 255 - colorRange;
  
	return random(lowest, highest + 1);
}

const getNewColor = (color) => {
	const newColor = [...color];
  const modified = random(0, 3);
  newColor[modified] = randomColor(newColor[modified]);
	return newColor;
};

const...