logo
Published on

Make a little tool for my wife

Authors
  • avatar
    Name
    Hugh Zhao
    Twitter

Background

My wife is a special education teacher, and she often prints various images to teach children. She usually arranges several photos evenly on a Word document, typically placing six photos per page, leaving space around them while ensuring that each photo is scaled proportionally to cover 1/6 of the page. This is the suitable size she commonly uses for printing and laminating the photos into small cards.

When I saw how difficult it was for her to create such a Word document, I decided to build a tool to help her with this task.

Plan

Technology Stack

To implement this tool, I chose two core libraries:

  • docx.js: to generate Word documents
  • file-saver: to handle file saving

Implementation Approach

First, we need a simple interface that allows users to:

  • Upload multiple images
  • Clear selected images at any time and reselect them

Then, considering the different needs of various scenarios, I added some flexible configuration options:

  • Adjust how many rows of images per page
  • Set how many images per row
  • Adjust the spacing between images

When processing the images, I paid particular attention to the following:

  • Automatically calculate the maximum space available for each image
  • Maintain the aspect ratio of the images to avoid distortion
  • Ensure the images are centered in the grid

Finally, when generating the Word document:

  • Use landscape A4 paper layout
  • Remove page margins to maximize space
  • Use tables to evenly arrange the images
  • Automatically paginate based on the number of images

Key Technical Points

The most important part is the algorithm to maintain the image aspect ratio:

// Calculate the best size for the image in the given space
if (imgWidth > imgHeight) {
  if (imgWidth > maxWidth) {
    width = maxWidth
    height = width / ratio
  }
} else {
  if (imgHeight > maxHeight) {
    height = maxHeight
    width = height * ratio
  }
}

However, there is one point I haven't figured out yet. When setting the image size, I thought the unit type was DAX, but when I set it, it wasn't. Eventually, I figured out a value, but I still don't know why it requires dividing by 15. I hope to figure this out and update it later.

const maxWidth = (pageWidth - borderWidth - config.colNum * config.padding * 2) / 15 / config.colNum

Summary

Tonight, I'll let my wife use it and see how it goes. Once she gives me some feedback, I'll make further adjustments.