JavaScript required
We’re sorry, but Coda doesn’t work properly without JavaScript enabled.
Skip to content
Gallery
Spirographs in a doc
Spirographs in a doc
More
Share
Explore
Spirographs in a doc
Pack code
Here is the exact Pack code that creates these
Spirographs in a doc
:
// basic Pack import
import
*
as
coda
from
"@codahq/packs-sdk"
;
export
const
pack = coda.newPack();
pack.addFormula({
name:
"DrawSpirograph"
,
description:
"Draw a dynamic spirograph."
,
resultType: coda.
ValueType
.
String
,
codaType: coda.
ValueHintType
.
ImageReference
,
parameters: [
coda.makeParameter({
//largeRadius
type
: coda.
ParameterType
.
Number
,
name:
"largeRadius"
,
description:
"Radius of the large circle"
,
optional:
false
,
}),
coda.makeParameter({
//smallRadius
type
: coda.
ParameterType
.
Number
,
name:
"smallRadius"
,
description:
"Radius of the small circle."
,
optional:
false
,
}),
coda.makeParameter({
//width of the canvas
type
: coda.
ParameterType
.
Number
,
name:
"width"
,
description:
"Width of the canvas."
,
optional:
false
,
}),
coda.makeParameter({
//height of the canvas
type
: coda.
ParameterType
.
Number
,
name:
"height"
,
description:
"Height of the canvas."
,
optional:
false
,
}),
coda.makeParameter({
//color1
type
: coda.
ParameterType
.
String
,
name:
"color1"
,
description:
"enter a hex code color (with the #)"
,
optional:
false
,
}),
coda.makeParameter({
//color2
type
: coda.
ParameterType
.
String
,
name:
"color2"
,
description:
"enter a hex code color (with the #)"
,
optional:
false
,
}),
],
execute:
function
([largeRadius, smallRadius, width, height, color1, color2]) {
//create an array of objects with startX, startY, endX, endY
const
coordinateArray = [];
const
xStorage = [];
const
yStorage = [];
let
previousX =
NaN
;
let
previousY =
NaN
;
//do the math for all angles
for
(
let
i =
0
; i <=
360
; i++) {
let
startX = width /
2
;
let
startY = width /
2
;
//hypocycloid equation
let
xcoord = (largeRadius - smallRadius) *
Math
.cos(i) + smallRadius *
Math
.cos((largeRadius / smallRadius -
1
) * i);
let
ycoord = (largeRadius - smallRadius) *
Math
.sin(i) - smallRadius *
Math
.sin((largeRadius / smallRadius -
1
) * i);
if
(i >
0
) {
startX = previousX;
startY = previousY;
}
let
endX = startX + xcoord;
let
endY = startY + ycoord;
//change previousEnd values
previousX = endX;
previousY = endY;
//add a color for the line
let
color = color1;
if
(i >
90
) {
color = color2;
}
coordinateArray.push({
x1: startX,
y1: startY,
x2: endX,
y2: endY,
color: color,
});
xStorage.push(startX, endX);
yStorage.push(startY, endY);
}
const
origin = {
x: width /
2
,
y: height /
2
,
}
//get and store differences of max X and min X, max Y and min Y
let
maxX = xStorage.reduce((a, b) =>
Math
.max(a, b));
let
minX = xStorage.reduce((a, b) =>
Math
.min(a, b));
let
maxY = yStorage.reduce((a, b) =>
Math
.max(a, b));
let
minY = yStorage.reduce((a, b) =>
Math
.min(a, b));
let
xDiff = (maxX - minX) /
2
;
let
yDiff = (maxY - minY) /
2
;
let
spiroCenter = {
x: minX + xDiff,
y: minY + yDiff,
}
let
xFactor = spiroCenter.x - origin.x;
let
yFactor = spiroCenter.y - origin.y;
//apply differences to every X and every Y
for
(
let
i =
0
; i < coordinateArray.length; i++) {
coordinateArray[i].x1 = coordinateArray[i].x1 - xFactor;
coordinateArray[i].x2 = coordinateArray[i].x2 - xFactor;
coordinateArray[i].y1 = coordinateArray[i].y1 - yFactor;
coordinateArray[i].y2 = coordinateArray[i].y2 - yFactor;
}
//parse to the SVG string
let
svgArray = [];
for
(
let
i =
0
; i < coordinateArray.length; i++) {
let
startX = coordinateArray[i].x1;
let
startY = coordinateArray[i].y1;
let
endX = coordinateArray[i].x2;
let
endY = coordinateArray[i].y2;
let
color = coordinateArray[i].color;
svgArray.push(
`<line x1="
${startX}
" y1="
${startY}
" x2="
${endX}
" y2="
${endY}
" stroke="
${color}
" />`
);
}
//combine to make the SVG
const
svg =
`<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="
${width}
" height="
${height}
">
${svgArray.join(
''
)}
</svg>`
;
return
'data:image/svg+xml,'
+ encodeURIComponent(svg);
},
});
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
Ctrl
P
) instead.