Pompdoek

“Pump Towel”

On a visit to the Netherlands in April, I say a bartender with a kitchen towel with a cool geometric checker board design. The next day I saw the same towel in a shop window. I realized what I at first thought was a trendy designer textile was in fact a ubiquitous everyday item.

Source: https://www.tenkatetextiel.nl/pompdoek-blokdoek-dubbeldraads-dambord-blok

When I moved to the Netherlands a few weeks ago, I continued to see the same motif everywhere. I decided to dig in and doing little research on the design, but didn’t find any information that identified a designer or an original creator.

Upon a visit to the TextielMuseum Tilburg, I learned about the Thread by Thread project by textile artist Vera Roggli. In this project Roggli deconstructed common textiles to examine how they are made. Here I found out more about the history of the Pompdoek.

https://www.instagram.com/p/ClHwlHftSue/?img_index=3

I like the simplicity of the pattern and decided to recreate the pattern in p5.js as one of my daily sketches that I have been completing as part of sketch-a-day, adding an interactive slider that controls the fade timing.

https://awdriggs.github.io/sketchaday/d09052024/index.html

I decided it would be great to allow a user to fully control the entire design and felt like having a simple user interface would be important. So I set out to make a simple page dedicated to this simple, everyday towel.

Process

Design and Layout

Starting with wireframes, I wanted to make the layout as straightforward as possible.

Before getting to much into the page styling, I like to add the structure the page in html and add css to get the layouts set before doing too much work on aesthetics. I use bold background colors on every element to see how the structure is behaving. I start with the mobile layout because it is the simplest then move to a desktop layout.

Responsive Canvas

I realized that the canvas would also need to be responsive and always fill the main section but should stay in the 16:9 proportion of the screen.

In setup, I started by grabbing the parent div from the html. I sued the width of the div for the width of the canvas and calculated the height in proportion to the width.

function setup(){
  container = select('#canvas-wrapper');
  createCanvas(container.width, container.width * (9/16)); //keep hd proportions
}

Anytime the screen is resize, the canvas size would need to update too.

function windowResized() {
  container = select('#canvas-wrapper'); //regrab the container to get the new width
  resizeCanvas(container.width, container.width * (9/16)); //keep hd proportions
}

I wanted to test this and linking an HTML slider to an variable in p5 in a simple sketch. I linked the size of the circle to a slider for testing.

//in setup
 slider1 = select('#circ-size');

Then in draw I can set the circle size with the value from the slider.

//in draw
  let s = slider1.value();
  ellipse(width/2, height/2, s, s);

I wanted to give the user the option to download their Pompdoek design so I attached a mouse event to the button that would call the saveCanvas p5 function whenever it was clicked.

 //in setup
  saveButton = select('#save');
  saveButton.mousePressed(() => saveCanvas('pompdoek', 'png'));

Now anytime the save button is pressed the saveCanvas function is called. The syntax might look a little wonky. Here I’m using an arrow function to pass the saveCanvas function as a parameter to the mouse event.

Now I had a “minimal viable product” where the p5 sketch was living within the HTML layout and could be controlled by the input elements on the page.

Styling

I next added more styling and Incorporated the tiling sketch, all the sliders for user input and two HTML5 color inputs to allow a user to select a primary and secondary color.

One thing I had to consider was how the slider minimum and maximum values would need to change as the canvas was resized. I thought it would be cumbersome to rebuild the html for the sliders with each canvas resize and I wanted the simplest solution possible.

To that end I decided to make each slider go from 0 to 1, with a step size of 0.01. This is like treating the slider a percent.

<!-- example slider --> 
<input id="right-boundry" name="size" type="range" min="0" max="1.0" step="0.01" value="0.5" class="slider">

Then in p5 I could map the 0 to 1.0 value to the desired range for the current canvas size.

let rightDiv = map(rightBoundrySlider.value(), 0, 1, 1, width); 

I wanted to have specific slider values when the sketch starter, as well as the ability of the user to reset the sliders to their original state. I created this function that would get called in setup as well as anytime the reset button was pressed.

function resetControls() {
  console.log('reset');
  // slider1.elt.value = 0.2
  rightBoundrySlider.elt.value = 0.8;
  bottomBoundrySlider.elt.value = 0.66;
  mainW.elt.value = 0.2;
  cornerW.elt.value = 0.2;
  bottomW.elt.value = 0.7;
  bottomH.elt.value = 0.03;
  rightW.elt.value = 0.03;
  rightH.elt.value = 0.4;

  colorOneInput.elt.value = "#434f71"
  colorTwoInput.elt.value = "#FFFFFF"
}

See the live site here!

And here is the github repo with the code.