mirror of
https://github.com/SamEyeBam/animate.git
synced 2026-02-04 01:14:15 +00:00
Shape variable fixes
This commit is contained in:
@@ -51,9 +51,10 @@
|
|||||||
<!-- Shape definitions -->
|
<!-- Shape definitions -->
|
||||||
<script src="./js/shapes/PolyTwistColourWidth.js" type="text/javascript"></script>
|
<script src="./js/shapes/PolyTwistColourWidth.js" type="text/javascript"></script>
|
||||||
<script src="./js/shapes/FloralPhyllo.js" type="text/javascript"></script>
|
<script src="./js/shapes/FloralPhyllo.js" type="text/javascript"></script>
|
||||||
<script src="./js/shapes/Spiral1.js" type="text/javascript"></script>
|
<script src="./js/shapes/SpiralWormhole.js" type="text/javascript"></script>
|
||||||
<script src="./js/shapes/FloralAccident.js" type="text/javascript"></script>
|
<script src="./js/shapes/FloralAccident.js" type="text/javascript"></script>
|
||||||
<script src="./js/shapes/FloralPhyllo_Accident.js" type="text/javascript"></script>
|
<script src="./js/shapes/FloralPhyllo_Accident.js" type="text/javascript"></script>
|
||||||
|
<script src="./js/shapes/Nodal.js" type="text/javascript"></script>
|
||||||
<script src="./js/shapes/Nodal_expanding.js" type="text/javascript"></script>
|
<script src="./js/shapes/Nodal_expanding.js" type="text/javascript"></script>
|
||||||
<script src="./js/shapes/Phyllotaxis.js" type="text/javascript"></script>
|
<script src="./js/shapes/Phyllotaxis.js" type="text/javascript"></script>
|
||||||
<script src="./js/shapes/PhylloCone.js" type="text/javascript"></script>
|
<script src="./js/shapes/PhylloCone.js" type="text/javascript"></script>
|
||||||
|
|||||||
@@ -7,52 +7,71 @@
|
|||||||
const BUILT_IN_PRESETS = [
|
const BUILT_IN_PRESETS = [
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "Poly Twist Rainbow",
|
name: "Minds Eye is Full Of Flowers",
|
||||||
description: "hexagon bby",
|
description: "Look at me",
|
||||||
builtIn: true,
|
builtIn: true,
|
||||||
data: {
|
data: {
|
||||||
version: 1,
|
version: 1,
|
||||||
layers: [
|
layers: [
|
||||||
{
|
{
|
||||||
name: "PolyTwistColourWidth",
|
name: "FloralPhyllo",
|
||||||
visible: true,
|
|
||||||
paused: false,
|
|
||||||
collapsed: true,
|
|
||||||
values: {
|
|
||||||
sides: 6,
|
|
||||||
width: 500,
|
|
||||||
line_width: 2,
|
|
||||||
depth: 80,
|
|
||||||
rotation: 0,
|
|
||||||
colour1: "#ff0066",
|
|
||||||
colour2: "#00ffff"
|
|
||||||
},
|
|
||||||
filters: {}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Expanding Nodes",
|
|
||||||
description: "Pulsing nodal pattern",
|
|
||||||
builtIn: true,
|
|
||||||
data: {
|
|
||||||
version: 1,
|
|
||||||
layers: [
|
|
||||||
{
|
|
||||||
name: "Nodal_expanding",
|
|
||||||
visible: true,
|
visible: true,
|
||||||
paused: false,
|
paused: false,
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
values: {
|
values: {
|
||||||
expand: 2,
|
width_start: 30,
|
||||||
points: 550,
|
width_scale: 333,
|
||||||
start: 0,
|
depth: 200,
|
||||||
line_width: 4,
|
start: 625,
|
||||||
colour1: "#ffffff",
|
colour1: [
|
||||||
colour2: "#4a9eff",
|
66,
|
||||||
colour_change: 3,
|
135,
|
||||||
speedMultiplier: 535
|
245
|
||||||
|
],
|
||||||
|
colour2: [
|
||||||
|
252,
|
||||||
|
3,
|
||||||
|
98
|
||||||
|
],
|
||||||
|
speedMultiplier: 500
|
||||||
|
},
|
||||||
|
filters: {},
|
||||||
|
controlBounds: {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "EyePrototype",
|
||||||
|
visible: true,
|
||||||
|
paused: false,
|
||||||
|
collapsed: false,
|
||||||
|
values: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
rotate: 0,
|
||||||
|
flip: 0,
|
||||||
|
width: 531,
|
||||||
|
blink_speed: 27,
|
||||||
|
draw_spiral: 0,
|
||||||
|
spiral_full: 1,
|
||||||
|
draw_pupil: 0,
|
||||||
|
draw_expand: 0,
|
||||||
|
draw_hypno: 1,
|
||||||
|
line_width: 1,
|
||||||
|
colourPupil: [
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
251
|
||||||
|
],
|
||||||
|
colourSpiral: [
|
||||||
|
255,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
colourExpand: [
|
||||||
|
0,
|
||||||
|
255,
|
||||||
|
251
|
||||||
|
],
|
||||||
|
speedMultiplier: 100
|
||||||
},
|
},
|
||||||
filters: {},
|
filters: {},
|
||||||
controlBounds: {}
|
controlBounds: {}
|
||||||
|
|||||||
@@ -3,25 +3,30 @@
|
|||||||
*/
|
*/
|
||||||
class EyePrototype extends BaseShape {
|
class EyePrototype extends BaseShape {
|
||||||
static config = [
|
static config = [
|
||||||
|
{ type: 'header', text: '---Position---' },
|
||||||
{ type: 'range', min: -400, max: 400, defaultValue: 0, property: 'x' },
|
{ type: 'range', min: -400, max: 400, defaultValue: 0, property: 'x' },
|
||||||
{ type: 'range', min: -400, max: 400, defaultValue: 0, property: 'y' },
|
{ type: 'range', min: -400, max: 400, defaultValue: 0, property: 'y' },
|
||||||
{ type: 'range', min: -180, max: 180, defaultValue: 0, property: 'rotate' },
|
{ type: 'range', min: -180, max: 180, defaultValue: 0, property: 'rotate' },
|
||||||
{ type: 'range', min: 0, max: 1, defaultValue: 1, property: 'flip' },
|
{ type: 'checkbox', defaultValue: false, property: 'flip' },
|
||||||
|
{ type: 'header', text: '--General---' },
|
||||||
{ type: 'range', min: 1, max: 800, defaultValue: 400, property: 'width' },
|
{ type: 'range', min: 1, max: 800, defaultValue: 400, property: 'width' },
|
||||||
{ type: 'range', min: 1, max: 100, defaultValue: 5, property: 'blink_speed' },
|
{ type: 'range', min: 1, max: 100, defaultValue: 30, property: 'blink_speed' },
|
||||||
{ type: 'range', min: 0, max: 1, defaultValue: 0, property: 'draw_spiral' },
|
{ type: 'range', min: 1, max: 10, defaultValue: 5, property: 'line_width' },
|
||||||
{ type: 'range', min: 0, max: 1, defaultValue: 1, property: 'spiral_full' },
|
{ type: 'color', defaultValue: [66, 135, 245], property: 'outline_colour' },
|
||||||
{ type: 'range', min: 0, max: 1, defaultValue: 0, property: 'draw_pupil' },
|
{ type: 'checkbox', defaultValue: true, property: 'draw_eyelid' },
|
||||||
{ type: 'range', min: 0, max: 1, defaultValue: 0, property: 'draw_expand' },
|
{ type: 'header', text: '--Effects---' },
|
||||||
{ type: 'range', min: 0, max: 1, defaultValue: 1, property: 'draw_hypno' },
|
{ type: 'checkbox', defaultValue: false, property: 'draw_spiral' },
|
||||||
{ type: 'range', min: 1, max: 10, defaultValue: 1, property: 'line_width' },
|
{ type: 'checkbox', defaultValue: true, property: 'spiral_full' },
|
||||||
|
{ type: 'checkbox', defaultValue: false, property: 'draw_pupil' },
|
||||||
|
{ type: 'checkbox', defaultValue: false, property: 'draw_expand' },
|
||||||
|
{ type: 'checkbox', defaultValue: false, property: 'draw_hypno' },
|
||||||
|
{ type: 'checkbox', defaultValue: true, property: 'draw_wormhole' },
|
||||||
{ type: 'color', defaultValue: [0, 255, 251], property: 'colourPupil' },
|
{ type: 'color', defaultValue: [0, 255, 251], property: 'colourPupil' },
|
||||||
{ type: 'color', defaultValue: [255, 0, 0], property: 'colourSpiral' },
|
{ type: 'color', defaultValue: [255, 0, 0], property: 'colourSpiral' },
|
||||||
{ type: 'color', defaultValue: [0, 255, 251], property: 'colourExpand' },
|
{ type: 'color', defaultValue: [0, 255, 251], property: 'colourExpand' },
|
||||||
{ type: 'range', min: 0, max: 1, defaultValue: 1, property: 'draw_eyelid' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
constructor(x, y, rotate, flip, width, blink_speed, draw_spiral, spiral_full, draw_pupil, draw_expand, draw_hypno, line_width, colourPupil, colourSpiral, colourExpand) {
|
constructor(x, y, rotate, flip, width, blink_speed, line_width, outline_colour, draw_eyelid, draw_spiral, spiral_full, draw_pupil, draw_expand, draw_hypno, draw_wormhole, colourPupil, colourSpiral, colourExpand) {
|
||||||
super();
|
super();
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
@@ -30,27 +35,32 @@ class EyePrototype extends BaseShape {
|
|||||||
this.width = width;
|
this.width = width;
|
||||||
this.blink_speed = blink_speed;
|
this.blink_speed = blink_speed;
|
||||||
this.line_width = line_width;
|
this.line_width = line_width;
|
||||||
this.step = 0;
|
this.outline_colour = outline_colour;
|
||||||
this.opening = true;
|
this.draw_eyelid = draw_eyelid;
|
||||||
this.counter = 0;
|
|
||||||
this.cooldown = 0;
|
|
||||||
this.draw_spiral = draw_spiral;
|
this.draw_spiral = draw_spiral;
|
||||||
this.spiral_full = spiral_full;
|
this.spiral_full = spiral_full;
|
||||||
this.draw_pupil = draw_pupil;
|
this.draw_pupil = draw_pupil;
|
||||||
this.draw_expand = draw_expand;
|
this.draw_expand = draw_expand;
|
||||||
this.draw_hypno = draw_hypno;
|
this.draw_hypno = draw_hypno;
|
||||||
|
this.draw_wormhole = draw_wormhole;
|
||||||
this.colourPupil = colourPupil;
|
this.colourPupil = colourPupil;
|
||||||
this.colourSpiral = colourSpiral;
|
this.colourSpiral = colourSpiral;
|
||||||
this.colourExpand = colourExpand;
|
this.colourExpand = colourExpand;
|
||||||
|
this.step = 0;
|
||||||
|
this.opening = true;
|
||||||
|
this.counter = 0;
|
||||||
|
this.cooldown = 0;
|
||||||
this.centerPulse = new CircleExpand(10, 30, 1, 0, [45, 129, 252], [252, 3, 98]);
|
this.centerPulse = new CircleExpand(10, 30, 1, 0, [45, 129, 252], [252, 3, 98]);
|
||||||
|
this.wormhole = new SpiralWormhole(20, 120, [66, 135, 245]);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawEyelid(rotation) {
|
drawEyelid(rotation, lineWidth) {
|
||||||
ctx.strokeStyle = "orange";
|
ctx.strokeStyle = "black";
|
||||||
const relCenterX = centerX + this.x;
|
const relCenterX = centerX + this.x;
|
||||||
const relCenterY = centerY + this.y;
|
const relCenterY = centerY + this.y;
|
||||||
rotation *= (this.speedMultiplier / 100);
|
rotation *= (this.speedMultiplier / 100);
|
||||||
ctx.lineWidth = 1;
|
ctx.lineWidth = lineWidth;
|
||||||
|
ctx.strokeStyle = colourToText(this.outline_colour);
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
let newPoint = 0;
|
let newPoint = 0;
|
||||||
let newPoint1 = 0;
|
let newPoint1 = 0;
|
||||||
@@ -160,7 +170,7 @@ class EyePrototype extends BaseShape {
|
|||||||
|
|
||||||
ctx.fillStyle = "black";
|
ctx.fillStyle = "black";
|
||||||
ctx.save();
|
ctx.save();
|
||||||
this.drawEyelid(outputRotation);
|
this.drawEyelid(outputRotation, this.line_width);
|
||||||
this.eyelidCut(outputRotation);
|
this.eyelidCut(outputRotation);
|
||||||
|
|
||||||
if (Math.floor(this.counter % (this.width / 4)) === 0) {
|
if (Math.floor(this.counter % (this.width / 4)) === 0) {
|
||||||
@@ -170,13 +180,16 @@ class EyePrototype extends BaseShape {
|
|||||||
ctx.fillStyle = "black";
|
ctx.fillStyle = "black";
|
||||||
ctx.fillRect(this.x - this.width / 2 + centerX, 0, this.width, ctx.canvas.height);
|
ctx.fillRect(this.x - this.width / 2 + centerX, 0, this.width, ctx.canvas.height);
|
||||||
|
|
||||||
if (this.draw_expand) {
|
|
||||||
this.drawGrowEye(this.width / 4 + this.counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.draw_hypno) {
|
if (this.draw_hypno) {
|
||||||
this.centerPulse.draw(elapsed);
|
this.centerPulse.draw(elapsed);
|
||||||
}
|
}
|
||||||
|
if (this.draw_wormhole) {
|
||||||
|
this.wormhole.draw(elapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.draw_expand) {
|
||||||
|
this.drawGrowEye(this.width / 4 + this.counter);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.draw_spiral) {
|
if (this.draw_spiral) {
|
||||||
this.drawSpiral(elapsed);
|
this.drawSpiral(elapsed);
|
||||||
|
|||||||
@@ -3,16 +3,18 @@
|
|||||||
*/
|
*/
|
||||||
class FloralPhyllo extends BaseShape {
|
class FloralPhyllo extends BaseShape {
|
||||||
static config = [
|
static config = [
|
||||||
{ type: 'range', min: 1, max: 600, defaultValue: 300, property: 'width' },
|
{ type: 'range', min: 1, max: 100, defaultValue: 60, property: 'width_start' },
|
||||||
{ type: 'range', min: 1, max: 300, defaultValue: 150, property: 'depth' },
|
{ type: 'range', min: 1, max: 1000, defaultValue: 650, property: 'width_scale' },
|
||||||
|
{ type: 'range', min: 1, max: 1000, defaultValue: 200, property: 'depth' },
|
||||||
{ type: 'range', min: 0, max: 3141, defaultValue: 0, property: 'start' },
|
{ type: 'range', min: 0, max: 3141, defaultValue: 0, property: 'start' },
|
||||||
{ type: 'color', defaultValue: [66, 135, 245], property: 'colour1' },
|
{ type: 'color', defaultValue: [66, 135, 245], property: 'colour1' },
|
||||||
{ type: 'color', defaultValue: [252, 3, 98], property: 'colour2' },
|
{ type: 'color', defaultValue: [252, 3, 98], property: 'colour2' },
|
||||||
];
|
];
|
||||||
|
|
||||||
constructor(width, depth, start, colour1, colour2) {
|
constructor(width_start,width_scale, depth, start, colour1, colour2) {
|
||||||
super();
|
super();
|
||||||
this.width = width;
|
this.width_start = width_start;
|
||||||
|
this.width_scale = width_scale;
|
||||||
this.depth = depth;
|
this.depth = depth;
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.colour1 = colour1;
|
this.colour1 = colour1;
|
||||||
@@ -32,7 +34,7 @@ class FloralPhyllo extends BaseShape {
|
|||||||
const x = r * Math.cos(a) + centerX;
|
const x = r * Math.cos(a) + centerX;
|
||||||
const y = r * Math.sin(a) + centerY;
|
const y = r * Math.sin(a) + centerY;
|
||||||
|
|
||||||
drawEyelid(n * 2.4 + 40, x, y, ncolour);
|
drawPetal(n * this.width_scale/100 + this.width_start, x, y, ncolour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
56
docs/js/shapes/Nodal.js
Normal file
56
docs/js/shapes/Nodal.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
|
||||||
|
class Nodal extends BaseShape {
|
||||||
|
static config = [
|
||||||
|
{ type: 'range', min: 0, max: 360, defaultValue: 0, property: 'shift' },
|
||||||
|
{ type: 'range', min: 10, max: 800, defaultValue: 400, property: 'radius' },
|
||||||
|
{ type: 'range', min: 3, max: 500, defaultValue: 100, property: 'points' },
|
||||||
|
{ type: 'range', min: 1, max: 250, defaultValue: 41, property: 'step' },
|
||||||
|
{ type: 'range', min: 1, max: 20, defaultValue: 2, property: 'lineWidth' },
|
||||||
|
{ type: 'color', defaultValue: [64, 199, 119], property: 'colour' },
|
||||||
|
];
|
||||||
|
|
||||||
|
constructor(shift, radius, points, step, lineWidth, colour) {
|
||||||
|
super();
|
||||||
|
this.shift = shift;
|
||||||
|
this.radius = radius;
|
||||||
|
this.points = points;
|
||||||
|
this.step = step;
|
||||||
|
this.lineWidth = lineWidth;
|
||||||
|
this.colour = colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(elapsed) {
|
||||||
|
const rotation = elapsed * (this.speedMultiplier / 100) + this.shift;
|
||||||
|
const angle = 360 / this.points * this.step;
|
||||||
|
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(
|
||||||
|
centerX + Math.cos(this.rad(angle + rotation)) * this.radius,
|
||||||
|
centerY + Math.sin(this.rad(angle + rotation)) * this.radius
|
||||||
|
);
|
||||||
|
|
||||||
|
let totalMoves = 1;
|
||||||
|
while ((totalMoves * this.step) % this.points !== 0) {
|
||||||
|
totalMoves++;
|
||||||
|
}
|
||||||
|
totalMoves++;
|
||||||
|
|
||||||
|
for (let z = 1; z <= totalMoves; z++) {
|
||||||
|
ctx.lineTo(
|
||||||
|
centerX + Math.cos(this.rad(angle * z + rotation)) * this.radius,
|
||||||
|
centerY + Math.sin(this.rad(angle * z + rotation)) * this.radius
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.strokeStyle = colourToText(this.colour);
|
||||||
|
ctx.lineWidth = this.lineWidth;
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
rad(degrees) {
|
||||||
|
return degrees * (Math.PI / 180);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('Nodal shape loaded');
|
||||||
|
shapeRegistry.register('Nodal', Nodal);
|
||||||
@@ -3,16 +3,15 @@
|
|||||||
*/
|
*/
|
||||||
class Nodal_expanding extends BaseShape {
|
class Nodal_expanding extends BaseShape {
|
||||||
static config = [
|
static config = [
|
||||||
{ type: 'range', min: 0, max: 100, defaultValue: 0.1, property: 'expand' },
|
{ type: 'range', min: 0, max: 100, defaultValue: 1, property: 'expand' },
|
||||||
{ type: 'range', min: 1, max: 1000, defaultValue: 150, property: 'points' },
|
{ type: 'range', min: 1, max: 10000, defaultValue: 1000, property: 'points' },
|
||||||
{ type: 'range', min: 1, max: 360, defaultValue: 0, property: 'start' },
|
{ type: 'range', min: 1, max: 360, defaultValue: 32, property: 'start' },
|
||||||
{ type: 'range', min: 1, max: 10, defaultValue: 6, property: 'line_width' },
|
{ type: 'range', min: 1, max: 10, defaultValue: 6, property: 'line_width' },
|
||||||
{ type: 'color', defaultValue: [45, 129, 252], property: 'colour1' },
|
{ type: 'color', defaultValue: [45, 129, 252], property: 'colour1' },
|
||||||
{ type: 'color', defaultValue: [252, 3, 98], property: 'colour2' },
|
{ type: 'color', defaultValue: [252, 3, 98], property: 'colour2' },
|
||||||
{ type: 'range', min: 0, max: 10, defaultValue: 5, property: 'colour_change' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
constructor(expand, points, start, line_width, colour1, colour2, colour_change) {
|
constructor(expand, points, start, line_width, colour1, colour2) {
|
||||||
super();
|
super();
|
||||||
this.expand = expand;
|
this.expand = expand;
|
||||||
this.points = points;
|
this.points = points;
|
||||||
@@ -20,7 +19,6 @@ class Nodal_expanding extends BaseShape {
|
|||||||
this.line_width = line_width;
|
this.line_width = line_width;
|
||||||
this.colour1 = colour1;
|
this.colour1 = colour1;
|
||||||
this.colour2 = colour2;
|
this.colour2 = colour2;
|
||||||
this.colour_change = colour_change;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(elapsed) {
|
draw(elapsed) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Spiral1 - Dual-direction spiral pattern
|
* Spiral1 - Dual-direction spiral pattern
|
||||||
*/
|
*/
|
||||||
class Spiral1 extends BaseShape {
|
class SpiralWormhole extends BaseShape {
|
||||||
static config = [
|
static config = [
|
||||||
{ type: 'range', min: 1, max: 50, defaultValue: 20, property: 'sides' },
|
{ type: 'range', min: 1, max: 50, defaultValue: 20, property: 'sides' },
|
||||||
{ type: 'range', min: 1, max: 600, defaultValue: 240, property: 'width' },
|
{ type: 'range', min: 1, max: 600, defaultValue: 240, property: 'width' },
|
||||||
@@ -16,6 +16,7 @@ class Spiral1 extends BaseShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
draw(elapsed) {
|
draw(elapsed) {
|
||||||
|
elapsed *= 10
|
||||||
this.updateFilters(elapsed);
|
this.updateFilters(elapsed);
|
||||||
const rotation = elapsed * (this.speedMultiplier / 100);
|
const rotation = elapsed * (this.speedMultiplier / 100);
|
||||||
const rot = Math.round((this.sides - 2) * 180 / this.sides * 2);
|
const rot = Math.round((this.sides - 2) * 180 / this.sides * 2);
|
||||||
@@ -57,4 +58,4 @@ class Spiral1 extends BaseShape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shapeRegistry.register('Spiral1', Spiral1);
|
shapeRegistry.register('SpiralWormhole', SpiralWormhole);
|
||||||
@@ -53,6 +53,74 @@ function rgbArrayToHex(rgb) {
|
|||||||
return "#" + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1);
|
return "#" + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached petal path for efficient reuse (created once, transformed many times)
|
||||||
|
* @type {Path2D|null}
|
||||||
|
*/
|
||||||
|
let _petalPathCache = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get or create the cached petal path (unit size, pointing right from origin)
|
||||||
|
* @returns {Path2D}
|
||||||
|
*/
|
||||||
|
function getPetalPath() {
|
||||||
|
if (!_petalPathCache) {
|
||||||
|
_petalPathCache = new Path2D();
|
||||||
|
_petalPathCache.moveTo(0, 0);
|
||||||
|
_petalPathCache.quadraticCurveTo(0.5, 0.5, 1, 0);
|
||||||
|
_petalPathCache.quadraticCurveTo(0.5, -0.5, 0, 0);
|
||||||
|
}
|
||||||
|
return _petalPathCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a petal shape efficiently using canvas transforms
|
||||||
|
* Much faster than drawEyelid - uses cached path and transforms
|
||||||
|
* @param {number} width - Width/length of the petal
|
||||||
|
* @param {number} x - X position
|
||||||
|
* @param {number} y - Y position
|
||||||
|
* @param {string} colour - Fill color (CSS string)
|
||||||
|
*/
|
||||||
|
function drawPetal(width, x, y, colour, line_width = 2) {
|
||||||
|
const angle = Math.atan2(y - centerY, x - centerX);
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(x, y);
|
||||||
|
ctx.rotate(angle);
|
||||||
|
ctx.scale(width, width);
|
||||||
|
|
||||||
|
ctx.fillStyle = colour;
|
||||||
|
ctx.fill(getPetalPath());
|
||||||
|
|
||||||
|
ctx.lineWidth = 2 / width; // Scale line width inversely so it stays consistent
|
||||||
|
ctx.strokeStyle = "black";
|
||||||
|
ctx.stroke(getPetalPath());
|
||||||
|
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw multiple petals efficiently by batching transforms
|
||||||
|
* Even faster for large numbers - minimizes state changes
|
||||||
|
* @param {Array<{width: number, x: number, y: number, colour: string}>} petals
|
||||||
|
*/
|
||||||
|
function drawPetalsBatch(petals) {
|
||||||
|
const path = getPetalPath();
|
||||||
|
|
||||||
|
for (let i = 0; i < petals.length; i++) {
|
||||||
|
const p = petals[i];
|
||||||
|
const angle = Math.atan2(p.y - centerY, p.x - centerX);
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(p.x, p.y);
|
||||||
|
ctx.rotate(angle);
|
||||||
|
ctx.scale(p.width, p.width);
|
||||||
|
ctx.fillStyle = p.colour;
|
||||||
|
ctx.fill(path);
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Linear interpolation between two hex colors
|
* Linear interpolation between two hex colors
|
||||||
* @param {string} a - Start hex color
|
* @param {string} a - Start hex color
|
||||||
|
|||||||
Reference in New Issue
Block a user