overbrowsing / pruner

✂️ A plugin to stitch multiple images into a single canvas.
http://overbrowsing.com/pruner/
MIT License
0 stars 0 forks source link

pruner.js

NPM version npm PRs Welcome

Overview

pruner.js is a JavaScript utility that enhances image handling by stitching multiple images into a single canvas. It works by dividing large images into smaller tiles and only loading the necessary tiles based on the viewport size. This approach not only reduces the total amount of data transferred but also improves performance by ensuring that only visible parts of the image are processed. By minimising data transfer and leveraging efficient image management, pruner.js accelerates loading times and supports sustainable web design practices.

Install

You can include pruner.js in your project either by downloading the files or using a CDN.

Download

CDN

Link directly to the minified version using Unpkg (we recommend downloading the file to reduce HTTP requests):

<script async src="https://unpkg.com/prunerjs@1.0.4/dist/pruner.min.js"></script>

Package Managers

You can also install pruner.js using npm:

npm install pruner --save

How It Works

Image and Attribute Requirements

  1. Attribute (data-pruner)

    • Purpose: This attribute holds the configuration for each image element in JSON format.
    • Parameters:
    • imageName: The base name of the images used in conjunction with the image (string).
    • cols: Number of columns (integer).
    • rows: Number of rows (integer).
    • tileWidth: Width of each tile in pixels (integer).
    • tileHeight: Height of each tile in pixels (integer).
    • mobileBreakpoint: The screen width in pixels below which the mobile image is loaded (integer).
    • mobileScale: Scale factor for mobile view (optional, numeric).
    • imagePath: Path to the directory where images are stored (string).
  2. Images

    • Name: Ensure that imageName matches the base name used for the pruner tile images. For instance, if imageName is landscape, the images should be named landscape 1.webp, landscape 2.webp, and so on.
    • File: All image formats are supported; however, using a modern image format like WebP is recommended for further optimisation.
    • Making Tiles: For processing images into tiles, consider using an online tool such as Split Image.

Initialize

You can initialize pruner.js using vanilla JavaScript or by setting attributes in your HTML.

With Vanilla JavaScript

window.onload = () => {
  new Pruner('data-pruner');
};

Example HTML Setup

You can use the data-pruner attribute to configure how the image is processed.

<img data-pruner='{"imageName": "landscape", "cols": 5, "rows": 5, "tileWidth": 300, "tileHeight": 200, "mobileBreakpoint": 768, "mobileScale":1.4, "imagePath": "assets/"}' alt="Landscape photography of mountains in New Zealand by Tobias Keller" loading="lazy">

Usage

  1. Include pruner.js in your HTML file:

    <script src="https://github.com/overbrowsing/pruner/raw/main/path/to/pruner.js"></script>
  2. Set Up Images:

    • Ensure that imageName matches the base name used for the pruner tile images. For instance, if imageName is landscape, the images should be named landscape 1.webp, landscape 2.webp, and so on.
    • Add the data-pruner attributes to the image, specifying the name of the image, the number of columns, rows, tile width, tile height, mobile breakpoint, mobile scale factor, and image path.

Mobile Optimization

On mobile devices (below the mobileBreakpoint), only the central tiles of the grid are loaded for improved performance. This is determined by the mobileScale parameter, which adjusts the scaling of the tiles based on the device’s screen size. For larger screens, the entire tiled image grid is constructed and displayed on a canvas.

Performance

Methodology

To evaluate the performance improvements from using pruner.js compared to loading two full images for desktop and mobile, tests were conducted using the Example HTML Setup. The test image (1500 x 1000px) was split into a 5x5 grid, with each tile measuring 300 x 200px. All image assets are available in the /assets folder. The original image was sourced from T. Keller on Unsplash.

Example HTML Setup Test

This experiment compared two approaches to image loading:

To ensure consistent and accurate results, the following factors were considered:

To Note:

Objectives
  1. Measure the number of visible tiles when using pruner.js across different viewport sizes (mobile, medium desktop, large desktop).
  2. Compare the total data transferred before and after implementing pruner.js across each viewport size.
  3. Evaluate the total file size reduction by comparing the conventional approach of using separate images for different viewport sizes with the tile-based approach using pruner.js, including the size of the minified script itself.
  4. Estimate CO₂ emissions before and after optimisation.

Results

📱 Small 650px 💻 Medium 1100px 🖥️ Large 1680px 📁 All Assets
Before
📁 Size (KB) 50 KB 194 KB 194 KB 244 KB (2 Images)
🌱 CO₂e (g) 0.013 g 0.053 g 0.053 g 0.067 g
After
🧩 Tiles 6 16 20 25
📁 Size (KB) 26 KB 83 KB 105 KB 156 KB
🌱 CO₂e (g) 0.007 g 0.022 g 0.029 g 0.043 g
Savings
📁 ∆ Size (KB) -24 KB -111 KB -89 KB -88 KB
🌱 ∆ CO₂e (g) -0.006 g -0.031 g -0.024 g -0.024 g
✂️ Reduction (%) 46 % 57.1 % 45.4 % 36.1 %

Ongoing testing is being conducted to expand the sample size and further verify the results.

Visualisation

Graph Example

There is also a Python visualisation tool designed to determine the optimal combination of tile count, row height, and tile size, and mobile scaling. This tool ensures efficient asset usage and performance across various common viewport dimensions.

For more information on installation and usage instructions, please refer to this document.
The application can also be found in this directory.

License

pruner.js is released under the MIT license. Feel free to use and modify it as needed.