Example:
Before - 
After - 
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.