Public
Edited
Dec 12, 2023
1 fork
Insert cell
Insert cell
height = 300;
Insert cell
branchCount = 6;
Insert cell
chart = {
const canvasWidth = 700;
const canvasHeight = 700;
// Create a canvas element
const canvas = document.createElement("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;

// Get the 2D rendering context
const context = canvas.getContext('2d');

// Set the parameters
const height = 400; // plot height
const branchWidth = 2; // line thickness
const branchCount = 6; // sub branch count
const sectionLength = 40; // Length of each section
const sepalLength = 100; // Length of each sepal
const sepalAngle = 0.8; // Sepal angle

// Set the background and basic parameters
context.fillStyle = "#162D50";
context.fillRect(0, 0, canvasWidth, canvasHeight);
context.lineCap = 'round';
context.strokeStyle = "#FFFFFF";
context.lineWidth = branchWidth;

// Draw the circle
context.save();
drawCircle(context, canvasWidth, canvasHeight, 20);
context.restore();
//context.translate(canvasWidth / 2, canvasHeight / 2);
drawSnowflake(context, sepalLength, 6);
return context.canvas;
}
Insert cell
/**
* Draw the snowflake.
* @param {CanvasRenderingContext2D} context - The 2D rendering context.
* @param {number} sepalLength - The length of the branches.
* @param {number} segmentCount - The number of segments.
*/
function drawSnowflake(context, sepalLength, segmentCount) {
const segmentAngle = (2 * Math.PI) / segmentCount;

for (let i = 0; i < segmentCount; i++) {
drawSegment(context, sepalLength);
context.rotate(segmentAngle);
}
}
Insert cell
/**
* Draw a branch in a given direction.
* @param {CanvasRenderingContext2D} context - The 2D rendering context.
* @param {number} branchLength - The length of the branch.
* @param {number} direction - The direction of the branch.
*/
function drawBranch(context, branchLength, direction) {
context.save();
context.rotate(direction * (Math.PI / 3));
context.moveTo(0, 0);
context.lineTo(branchLength, 0);
context.stroke();
context.restore();
}

Insert cell
/**
* Draw a segment with branches.
* @param {CanvasRenderingContext2D} context - The 2D rendering context.
* @param {number} branchLength - The length of the branches.
*/
function drawSegment(context, branchLength) {
context.beginPath();
context.moveTo(0, 0);
context.lineTo(branchLength, 0);
context.stroke();
context.translate(branchLength, 0);
if (branchLength > 0) {
for (let i = 0; i < branchCount; i++) {
drawBranch(context, branchLength, i * (2 * Math.PI) / branchCount);
}
}
}
Insert cell
drawing = {
const canvasWidth = 400;
const canvasHeight = 400;
// Create a canvas element
const canvas = document.createElement("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;

// Get the 2D rendering context
const ctx = canvas.getContext('2d');
drawCircle(ctx, canvasWidth, canvasHeight, 100);
drawLines(ctx, canvasWidth, canvasHeight);
return canvas;

}
Insert cell
drawCircle = (ctx, canvasWidth, canvasHeight, circleRadius) => {

// Set the fill style for the circle
ctx.fillStyle = 'red';

// Set the line width
ctx.lineWidth = 2;

// Draw a circle in the middle
const centerX = canvasWidth / 2;
const centerY = canvasHeight / 2;
ctx.beginPath();
ctx.arc(centerX, centerY, circleRadius, 0, 2 * Math.PI);
// Fill the circle
ctx.fill();

// Move to the starting point of the line
ctx.moveTo(50, canvasHeight / 2);

// Stroke the circle
ctx.stroke();
};

Insert cell
drawLines = (ctx, canvasWidth, canvasHeight) => {
ctx.strokeStyle = 'blue';
ctx.lineWidth = 2;
ctx.moveTo(0, canvasHeight / 2);
ctx.lineTo(canvasWidth, canvasHeight / 2);
ctx.stroke();
};
Insert cell
testSpikes = {

let sides = 6;
let slice_offset = toRadians(180 / sides);
const side_size = 400 // = iwidth;

}
Insert cell
function drawSpikes(side_size, slice_offset, iwidth, iheight) {
let spikes = [];
let spike_num = Math.floor(2 + Math.random() * 10);
let spike_step = side_size / 2 / spike_num;
for (let i = 1; i < spike_num + 1; i++) {
let distance = i * spike_step;
let offdist = distance - distance * 0.2;

let spike_opposite = Math.sin(slice_offset) * distance;
let spike_adjacent = Math.cos(slice_offset) * distance;
let off_opposite = Math.sin(slice_offset) * offdist;
let off_adjacent = Math.cos(slice_offset) * offdist;


let jitter = Math.random();
let x_dist = spike_adjacent - off_adjacent;
let y_dist = spike_opposite;
let new_x = iwidth / 2 + off_adjacent + x_dist * jitter;
let new_y = iheight / 2 + y_dist * jitter;
let new_other_y = iheight / 2 - y_dist * jitter;

spikes.push([
[new_x, new_y],
[iwidth / 2 + off_adjacent, iheight / 2],
[new_x, new_other_y]
]);
}
}
Insert cell
createGrid = () => {
let columns = 1;
let rows = 1;
let iwidth = 150;
let iheight = 150;
let width = iwidth * columns;
let height = iheight * rows;
let canvas = document.createElement("canvas");
let dpr = window.devicePixelRatio || 1;
canvas.width = width * dpr;
canvas.height = height * dpr;
canvas.style.width = width + "px";
canvas.style.height = height + "px";
let ctx = canvas.getContext("2d");
ctx.scale(dpr, dpr);
createSnowFlake(0, 0, iwidth, iheight, ctx);
ctx.strokeStyle = "black";
ctx.fillStyle = "black";
ctx.lineWidth = 1;
}
Insert cell
createSnowFlake = (cx, cy, iwidth, iheight, ctx) => {
ctx.fillStyle = "lightblue";
ctx.strokeStyle = "lightblue";
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(cx, cy, 14, 0, 2 * Math.PI, false);
ctx.fill();
ctx.beginPath();
ctx.moveTo(cx, cy);
let next_x = cx * iwidth + iwidth / 2;
let next_y = cy + iheight;
ctx.lineTo(next_x, next_y);
ctx.stroke();
ctx.save();
}
Insert cell
debug = {
let columns = 1;
let rows = 1;
let iwidth = 150;
let iheight = 150;
let width = iwidth * columns;
let height = iheight * rows;
let canvas = document.createElement("canvas");
let dpr = window.devicePixelRatio || 1;
canvas.width = width * dpr;
canvas.height = height * dpr;
canvas.style.width = width + "px";
canvas.style.height = height + "px";
let ctx = canvas.getContext("2d");
ctx.scale(dpr, dpr);

// Create grid cells
let cells = [];
for (let r = 0; r < rows; r++) {
for (let c = 0; c < columns; c++) {
cells.push([c, r]);
}
}

// Create snowflake for each cell
for (let f = 0; f < cells.length; f++) {
let cell = cells[f];
let cx = cells[f][0] * iwidth + iwidth / 2;
let cy = cells[f][1] * iheight + iheight / 2;
ctx.fillStyle = "lightblue";
ctx.strokeStyle = "lightblue";
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(cx, cy, 14, 0, 2 * Math.PI, false);
ctx.fill();
if (cell[1] < rows - 1) {
ctx.beginPath();
let next_y = cy + iheight;
for (let c = 0; c < columns; c++) {
ctx.moveTo(cx, cy);
let next_x = c * iwidth + iwidth / 2;
ctx.lineTo(next_x, next_y);
}
ctx.stroke();
}
}

ctx.strokeStyle = "black";
ctx.fillStyle = "black";
ctx.lineWidth = 1;

for (let f = 0; f < cells.length; f++) {
let offset_x = cells[f][0] * iwidth;
let offset_y = cells[f][1] * iheight;

// ctx.translate(iwidth / 2 + offset_x, iheight / 2 + offset_y);
// ctx.rotate(toRadians(90));
// ctx.translate(-iwidth / 2 + offset_x, -iheight / 2 + offset_y);

let sides = 6;

let slice_offset = toRadians(180 / sides);

let side_size = (0.5 + Math.random() * 0.5) * iwidth;
side_size = iwidth;

let opposite = (Math.sin(slice_offset) * side_size) / 2;
let adjacent = (Math.cos(slice_offset) * side_size) / 2;

ctx.lineWidth = 2;

// spike
let spikes = [];
let spike_num = Math.floor(2 + Math.random() * 10);
// spike_num = Math.ceil(Math.random() * cells.length);
let spike_step = side_size / 2 / spike_num;
for (let i = 1; i < spike_num + 1; i++) {
let distance = i * spike_step;
let offdist = distance - distance * 0.2;
// let offdist = distance - distance * 0;
let spike_opposite = Math.sin(slice_offset) * distance;
let spike_adjacent = Math.cos(slice_offset) * distance;
let off_opposite = Math.sin(slice_offset) * offdist;
let off_adjacent = Math.cos(slice_offset) * offdist;

// point.x = start.x + (final.x - start.x) * progress;
// point.y = start.y + (final.y - start.y) * progress;
let jitter = Math.random();
let x_dist = spike_adjacent - off_adjacent;
let y_dist = spike_opposite;
let new_x = iwidth / 2 + off_adjacent + x_dist * jitter;
let new_y = iheight / 2 + y_dist * jitter;
let new_other_y = iheight / 2 - y_dist * jitter;

spikes.push([
[new_x, new_y],
[iwidth / 2 + off_adjacent, iheight / 2],
[new_x, new_other_y]
]);
}

for (let i = 0; i < sides; i++) {
ctx.save();
ctx.translate(iwidth / 2 + offset_x, iheight / 2 + offset_y);
ctx.rotate((i / sides) * toRadians(360) + toRadians(90));
ctx.translate(-iwidth / 2, -iheight / 2);

ctx.beginPath();
ctx.moveTo(iwidth / 2, iheight / 2);
ctx.lineTo(iwidth / 2 + adjacent - adjacent * 0.2, iheight / 2);

for (let s = 0; s < spikes.length; s++) {
let spike = spikes[s];
ctx.moveTo(...spike[0]);
ctx.lineTo(...spike[1]);
ctx.lineTo(...spike[2]);
}

ctx.stroke();
ctx.restore();
}
}
return canvas;
}

Insert cell
import {} from "@anaclarapaniago/snowflake"
Insert cell
import {toRadians} from "@grantcuster/generative-snowflake-card-explorations"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more