- Published on
Make a little tool for my wife
- Authors
- Name
- Hugh Zhao
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.