Essay - Published: 2023.08.13 | create | pts | tech | typescript |
DISCLOSURE: If you buy through affiliate links, I may earn a small commission. (disclosures)
I recently released TimeTick - a visualization of the passing of time. TimeTick's Time page uses a grid to visualize the passing of time in relation to expected time available. This required building a dynamic grid of squares in my visualization library of choice Pts.js.
In this post we'll explore how to build this:
Q: How can we build a dynamic grid of squares in Pts.js?
The solution will be generalized across:
The solution provided here builds a 4x5 grid of squares and draws it to the space (canvas).
Run this example yourself by copy / pasting the code below into the Pts.js Playground
In order to produce the grid in the demo above, our pseudo code needs to do something like this:
The core part of our solution is to create a grid of squares. I've isolated it out into its own function to try and make it as easy to understand as possible.
This function creates a grid of squares described as an array of Groups of pts (if this is confusing, Pts' Get Started guide may help). Note that this just creates the data equivalent of these squares - it does not actually draw these to the canvas.
The code below:
allRectangles that will be present in the gridconst buildCenteredGridOfRectangles = (
space : CanvasSpace,
rectangleCountPerRow : number,
rowCount : number,
rectangleSize : number) : Group[] => {
const allRectangles = Array(rectangleCountPerRow * rowCount)
.fill(0)
.map(i => Rectangle.from(
space.center,
rectangleSize
))
for(let i = 0; i < allRectangles.length; i++)
{
const currentRect = allRectangles[i]
const x = space.center[0] + ((i % rectangleCountPerRow) - (rectangleCountPerRow / 2)) * rectangleSize * 2
const y = space.center[1] + (Math.floor(i / rectangleCountPerRow) - (rowCount / 2)) * rectangleSize * 2
currentRect.moveTo(x, y)
}
return allRectangles
}
Below is the full sketch used to validate this approach. I recommend copy / pasting into the Pts.js Playground and playing around with the code.
Note: The playground doesn't seem to support TypeScript so the grid code here is the same as above, just with types stripped out.
(function() {
// Pts quick start mode.
var run = Pts.quickStart( "#pt", "#fff" );
const buildCenteredGridOfRectangles = (
space ,
rectangleCountPerRow ,
rowCount ,
rectangleSize ) => {
const allRectangles = Array(rectangleCountPerRow * rowCount)
.fill(0)
.map(i => Rectangle.from(
space.center,
rectangleSize
))
for(let i = 0; i < allRectangles.length; i++)
{
const currentRect = allRectangles[i]
const x = space.center[0] + ((i % rectangleCountPerRow) - (rectangleCountPerRow / 2)) * rectangleSize * 2
const y = space.center[1] + (Math.floor(i / rectangleCountPerRow) - (rowCount / 2)) * rectangleSize * 2
currentRect.moveTo(x, y)
}
return allRectangles
}
run( (time, ftime) => {
const allRectangles = buildCenteredGridOfRectangles(
space,
4,
5,
10
)
allRectangles
.forEach(r => {
form
.fill("#fff")
.stroke("#000")
.polygon(
Rectangle.corners(r)
)
})
});
})();
If you liked this, you might be interested in some related reads:
The best way to support my work is to like / comment / share for the algorithm and subscribe for future updates.