-// App Config
-
-const kEntrypoint = "breadsticks";
-const kGap = 50;
-const kDrawDelay = 100;
-const kDarkDrawingColor = '#fff';
-const kLightDrawingColor = '#000';
-const kMaxVectorMagnitude = 150; // max size of a vector
-const kMagnitudeColorMultiplier = 2.5; // how large should the magnitude be before it's completely transparent
-
-/***********************************************
- * Breadstick generates a matrix of points
- * and assigns a vector to each entry
- * and then draws them
- ***********************************************/
-
-/*
- * Generate field of points in which to draw
- */
-
-// Updates the field object using a canvas
-
-const updateFieldFromCanvas = (field, canvas) => {
- updateFieldFromRect(field, canvas.getBoundingClientRect());
-
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
-
- window.addEventListener('resize', () => {
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- updateFieldFromRect(field, canvas.getBoundingClientRect());
- });
-};
-
-// Updates a field object using a rect
-
-const updateFieldFromRect = (field, rect) => {
- field.width = rect.width;
- field.height = rect.height;
-}
-
-/*
- * Generate the matrix of vectors
- */
-
-// Updates a matrix for a given field using the mouse
-
-
-const updateFieldMatrixFromMouse = (field, matrix, gap = 50) => {
- const mousePosition = {
- x: 0,
- y: 0
- };
-
- fillMatrix(matrix, mousePosition.x, mousePosition.y, field.width, field.height, gap);
-
- const updateMousePosition = document.addEventListener('mousemove', (event) => {
- mousePosition.x = event.clientX;
- mousePosition.y = event.clientY;
- fillMatrix(matrix, mousePosition.x, mousePosition.y, field.width, field.height, gap);
- });
-};
-
-// Gets a matrix by calculating the offset between position and field.
-
-const fillMatrix = (matrix, x, y, w, h, gap = 50) => {
- for (let i = 0; i < w / gap; ++i) {
- matrix[i] = [];
- for (let j = 0; j < h / gap; ++j) {
- let targetX = i * gap;
- let targetY = j * gap;
- matrix[i][j] = calculateOffsetVector(x, y, targetX, targetY, w, h);
- }
- }
-};
-
-// Calculates the offset vector of a point
-const calculateOffsetVector = (sourceX, sourceY, targetX, targetY, w, h) => {
- const xOffset = targetX - sourceX;
- const yOffset = targetY - sourceY;
-
- const calculatedMagnitude = Math.sqrt(Math.pow(xOffset, 2) + Math.pow(yOffset, 2));
-
- return {
- position: {
- x: targetX,
- y: targetY
- },
- color: getColor(calculatedMagnitude),
- angle: Math.atan2(xOffset, yOffset),
- magnitude: Math.min(calculatedMagnitude, kMaxVectorMagnitude)
- };
-};
-
-
-/*
- * Drawing
- */
-
-// draw a vector
-const drawVector = (context, i, j, vector) => {
- const x = vector.position.x - vector.magnitude * Math.sin(vector.angle);
- const y = vector.position.y - vector.magnitude * Math.cos(vector.angle);
- context.strokeStyle = vector.color;
- context.beginPath();
- context.moveTo(vector.position.x, vector.position.y);
- context.lineTo(Math.round(x), Math.round(y));
- context.stroke();
-};
-
-// Gets the color depending on the calculated magnitude
-// as well as the color scheme
-
-const getColor = (calculatedMagnitude) => {
-
- let colorValue = Math.round(calculatedMagnitude * 255 / (kMaxVectorMagnitude * kMagnitudeColorMultiplier)) % 255;
-
- if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
- colorValue = 255 - colorValue % 255;
- }
-
- // Initialize an array with the value, converts it to a hex string and joins it.
- return `#${Array(3).fill(colorValue.toString(16)).join('')}`;
-};
-
-
-// Draws field on canvas
-
-const drawFieldMatrixOnCanvas = (matrix, context) => {
-
- context.setLineDash([25, 10])
- context.clearRect(0, 0, context.canvas.width, context.canvas.height);
-
- for (let i = 0; i < matrix.length; ++i) {
- const row = matrix[i];
- for (let j = 0; j < row.length; ++j) {
- const vector = row[j]
-
- if (vector) {
- drawVector(context, i, j, vector);
- }
- }
- }
-};
-
-/*
- * Entrypoint
- */
-
-const run = () => {
-
- const field = {
- width: 0,
- height: 0
- };
- const canvas = document.getElementById(kEntrypoint);
-
- updateFieldFromCanvas(field, canvas);
-
- const matrix = [[]];
- updateFieldMatrixFromMouse(field, matrix, kGap);
-
- const context = canvas.getContext('2d');
- const drawFunction = () => {
- drawFieldMatrixOnCanvas(matrix, context);
- setTimeout(drawFunction, kDrawDelay);
- }
-
- setTimeout(drawFunction, 0);
-};
-
-window.addEventListener('load', run);