Skip to content

About the author of Daydream Drift

Tomasz Niezgoda (LinkedIn/tomaszniezgoda & GitHub/tniezg) is the author of this blog. It contains original content written with care.

Please link back to this website when referencing any of the materials.

Author:

Crop Images In A Website Using JavaScript Without Third Party Dependencies

Published

Example:

Before - Example image before cropping

After - Example image before cropping

The source code:

// in-browser-image-crop.js

// This file uses modern JavaScript. If you need to support older browsers, convert it using a tool like the Babel REPL (https://babeljs.io/repl/).

const cropImage = async (customOptions) => {
  const pixelDensity = window.devicePixelRatio

  const defaultOptions = {
    x: 100, // original image crop area
    y: 100, // original image crop area
    width: 100, // original image crop area
    height: 100, // original image crop area
    sourceUrl: null
  }

  const options = {
    ...defaultOptions,
    ...customOptions
  }

  if (typeof options.sourceUrl !== 'string') {
    throw new Error('sourceUrl is a required option.')
  }

  const imageLoaderElement = new Image()

  // Ensure the image is fully downloaded before cropping.
  await new Promise((resolve, reject) => {
    imageLoaderElement.onload = resolve

    imageLoaderElement.onerror = () => {
      reject(new Error("Couldn't load source image into memory."))
    }

    imageLoaderElement.src = options.sourceUrl
  })

  const canvas = document.createElement('canvas')

  canvas.width = options.width * pixelDensity
  canvas.height = options.height * pixelDensity

  const canvasContext = canvas.getContext('2d')

  const cutout = {
    x: options.x * pixelDensity,
    y: options.y * pixelDensity,
    width: options.width * pixelDensity,
    height: options.height * pixelDensity
  }

  const target = {
    x: 0,
    y: 0,
    width: options.width * pixelDensity,
    height: options.height * pixelDensity
  }

  // createImageBitmap may be a viable option to use over time as browsers add support.

  canvasContext.drawImage(
    imageLoaderElement,
    cutout.x,
    cutout.y,
    cutout.width,
    cutout.height,
    target.x,
    target.y,
    target.width,
    target.height
  )

  return canvas.toDataURL('image/png')
}

export default cropImage

How to use:

<!-- index.html -->

<!DOCTYPE html>
<html>
  <script src="./in-browser-image-crop.js"></script>
  <body>
    <script>
      cropImage({
        x: 287,
        y: 242,
        width: 50,
        height: 50,
        sourceUrl: './source.png' // Can also provide a data URL string.
      }).then((dataUrl) => {
        console.log('dataUrl: ', dataUrl)
      }, console.error)
    </script>
  </body>
</html>

If you receive a Tainted canvases may not be exported. error it means you're trying to load the source image from a untrusted location. Make sure the loaded image is within the same domain as the website cropping the image to a smaller size.