How to resize then crop an image with canvas

I took this tutorial as an example http://tympanus.net/codrops/2014/10/30/resizing-cropping-images-canvas/ and did the same thing in vanilla js. It probably needs some refacturing but it is working (at least on my windows labtop in chrome)

One html file:

<!DOCTYPE html>
<html lang="en">
 <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }
    /* styles for resize container and image */
    .resize-container {
        position: relative;
        display: inline-block;
        cursor: move;
        margin: 0 auto;
        top: 0;
        left: 0;
    }

    .resize-container img {
        display: block
    }

    .resize-container:hover img,
    .resize-container:active img {
        outline: 2px dashed rgba(222,60,80,.9);
    }
    /* styles for resize handles */
    .resize-handle-ne,
    .resize-handle-se,
    .resize-handle-nw,
    .resize-handle-sw {
        position: absolute;
        display: block;
        width: 10px;
        height: 10px;
        background: rgba(222, 60, 80, .9);
        z-index: 999;
    }

    .resize-handle-nw {
        top: -5px;
        left: -5px;
        cursor: nw-resize;
    }

    .resize-handle-sw {
        bottom: -5px;
        left: -5px;
        cursor: sw-resize;
    }

    .resize-handle-ne {
        top: -5px;
        right: -5px;
        cursor: ne-resize;
    }

    .resize-handle-se {
        bottom: -5px;
        right: -5px;
        cursor: se-resize;
    }
    .overlay {
        position: absolute;
        left: 50%;
        top: 50%;
        margin-left: -100px;
        margin-top: -100px;
        z-index: 999;
        width: 200px;
        height: 200px;
        border: solid 2px rgba(222,60,80,.9);
        box-sizing: content-box;
        pointer-events: none;
    }

    .overlay:after,
    .overlay:before {
        content: '';
        position: absolute;
        display: block;
        width: 204px;
        height: 40px;
        border-left: dashed 2px rgba(222,60,80,.9);
        border-right: dashed 2px rgba(222,60,80,.9);
    }

    .overlay:before {
        top: 0;
        margin-left: -2px;
        margin-top: -40px;
    }

    .overlay:after {
        bottom: 0;
        margin-left: -2px;
        margin-bottom: -40px;
    }

    .overlay-inner:after,
    .overlay-inner:before {
        content: '';
        position: absolute;
        display: block;
        width: 40px;
        height: 204px;
        border-top: dashed 2px rgba(222,60,80,.9);
        border-bottom: dashed 2px rgba(222,60,80,.9);
    }

    .overlay-inner:before {
        left: 0;
        margin-left: -40px;
        margin-top: -2px;
    }

    .overlay-inner:after {
        right: 0;
        margin-right: -40px;
        margin-top: -2px;
    }

    .btn-crop {
        position: absolute;
        vertical-align: bottom;
        right: 5px;
        bottom: 5px;
        padding: 6px 10px;
        z-index: 999;
        background-color: rgb(222,60,80);
        border: none;
        border-radius: 5px;
        color: #FFF;
    }

    #result {
        position: absolute;
        top: 0;
        left: 0;
        width: 100vw;
        height: 150vh;
        z-index: -1;
        display: flex;
        align-items: flex-end;
    }
  </style>
 </head>
  <body>
 <div id="resize-container" class="resize-container">
    <span class="resize-handle resize-handle-nw"></span>
    <span class="resize-handle resize-handle-ne"></span>
    <span class="resize-handle resize-handle-sw"></span>
    <span class="resize-handle resize-handle-se"></span>
    <img id="img" class="resize-image" src="image.png" alt="Image" />
</div>
<div id="overlay" class="overlay">
    <div class="overlay-inner">
    </div>
</div>
<button id="js-crop" class="btn-crop">Crop</button>
<div id="result"></div>

<script>
    const resizeableImage = image_target => {
        // defining the variables 
        let constrain = false

        const overlay = document.getElementById('overlay')
        const cropBtn = document.getElementById('js-crop')
        const container = document.getElementById('resize-container')
        const orig_src = new Image()
        const event_state = {}
        const min_width = 60
        const min_height = 60
        const max_width = 800
        const max_height = 900
        
        const resize_canvas = document.createElement('canvas')

        const resizeImage = (width, height) => {
            resize_canvas.width = width 
            resize_canvas.height = height 
            resize_canvas.getContext('2d').drawImage(orig_src, 0, 0, width, height)
            image_target.src = resize_canvas.toDataURL("image/png")
        }

        // the resizing function is where most of the action happens. This function is contansly invoked 
        // while the user is dragging one of the resize handles. Every time this function is called we
        // work out the new with and height by taking the current position of the mouse relative to the
        // initial position of the corner we are dragging
        const resizing = e => {
            let width, height, left, top 

            const rec = container.getBoundingClientRect()
            const offset = {
                top: rec.top + window.scrollY,
                left: rec.left + window.scrollX
            }
            const mouse = {
                x: (e.clientX || e.pageX || e.originalEvent.touches[0].clientX) + window.screenLeft,
                y: (e.clientY || e.pageY || e.originalEvent.touches[0].clientY) + window.screenTop
            }

            const eTargetClass = event_state.evnt.target.classList[1]
            // if statements for being able to resize from each corner
            if (eTargetClass === 'resize-handle-se') { // south-east (bottom-right)
                width = mouse.x - event_state.container_left
                height = mouse.y  - event_state.container_top
                left = event_state.container_left
                top = event_state.container_top
            } else if (eTargetClass === 'resize-handle-sw') { // south-west (bottom-left)
                width = event_state.container_width - (mouse.x - event_state.container_left)
                height = mouse.y  - event_state.container_top
                left = mouse.x
                top = event_state.container_top
            } else if (eTargetClass === 'resize-handle-ne') { // north-east (top-right)
                width = mouse.x - event_state.container_left
                height = event_state.container_height - (mouse.y - event_state.container_top)
                left = event_state.container_left
                top = mouse.y

                if(constrain || e.shiftKey){
                    top = mouse.y - ((width / orig_src.width * orig_src.height) - height)
                }
            } else if (eTargetClass === 'resize-handle-nw') { // north-west (top-left)
                width = event_state.container_width - (mouse.x - event_state.container_left)
                height = event_state.container_height - (mouse.y - event_state.container_top)
                left = mouse.x
                top = mouse.y

                if(constrain || e.shiftKey){
                    top = mouse.y - ((width / orig_src.width * orig_src.height) - height)
                }
            }


            if (constrain || e.shiftKey) {
                height = width / orig_src.width * orig_src.height 
            }

            if (width > min_width && height > min_height && width < max_width && height < max_height) {
                container.style.top = `${top}px`
                container.style.left = `${left}px`
                resizeImage(width, height)
            }
        }

        // before we start tracking the mouse position we want to take
        // a snapshot of the container dimensions and other key data
        // points. We store these in a variable named event_state and
        // use them later as a point of reference while resizing to
        // work out the change in height and width
        const saveEventState = e => {
            event_state.container_width = container.getBoundingClientRect().width 
            event_state.container_height = container.getBoundingClientRect().height 
            event_state.container_left = container.offsetLeft
            event_state.container_top = container.offsetTop 
            // mouse coordinates
            event_state.mouse_x = (e.clientX || e.pageX || e.originalEvent.touches[0].clientX) + window.screenLeft,
            event_state.mouse_y = (e.clientY || e.pageY || e.originalEvent.touches[0].clientY) + window.screenTop,

            event_state.evnt = e
        }

        // this two functions do very little other that tell the 
        // browser to start paying attention to where the mouse
        // is moving and when to stop paying attention
        const startResize = e => {
            e.preventDefault()
            e.stopPropagation()
            saveEventState(e)
            
            document.addEventListener('mousemove', resizing)
            document.addEventListener('mouseup', endResize)
        }

        const endResize = e => {
            e.preventDefault()
            //  The touchend event fires when one or more touch points are
            // removed from the touch surface.
            document.removeEventListener('mousemove', resizing)
            document.removeEventListener('touchend', resizing)
            document.removeEventListener('mouseup', endResize)
            document.removeEventListener('touchmove', endResize)
        }

        // in this function we need to work out the new position of the top left edge of the 
        // container. This will be equal to the current position of the mouse, offset by the
        // distance the mouse was from the top left corner when we started dragging the image
        const moving = e => {
            const mouse = {
                x: (e.clientX || e.pageX) + window.screenLeft,
                y: (e.clientY || e.pageY) + window.screenTop
            }

            container.style.left = `${mouse.x - (event_state.mouse_y - event_state.container_top)}px`
            container.style.top = `${mouse.y - (event_state.mouse_y - event_state.container_top)}px`
        }

        // function for moving the image around
        const startMoving = e => {
            e.preventDefault()
            e.stopPropagation()
            saveEventState(e)

            document.addEventListener('mousemove', moving)
            document.addEventListener('mouseup', endMoving)
        }

        const endMoving = e => {
            e.preventDefault()

            document.removeEventListener('mouseup', endMoving)
            document.removeEventListener('mousemove', moving)
        }

        const crop = e => {
            const left = overlay.offsetLeft - container.offsetLeft 
            const top = overlay.offsetTop - container.offsetTop 
            const width = overlay.getBoundingClientRect().width
            const height = overlay.getBoundingClientRect().height

            const crop_canvas = document.createElement('canvas')
            crop_canvas.width = width 
            crop_canvas.height = height 

            crop_canvas.getContext('2d').drawImage(image_target, left, top, width, height, 0, 0, width, height)

            const croppedImage = document.createElement('img')
            croppedImage.src = crop_canvas.toDataURL("image/png")
            document.querySelector('#result').appendChild(croppedImage)
        }

        // this function is called immediately and makes a copy of the
        // original image used for resizing
        const init = () => {
            // create a new image with a copy of the original src
            // When resizing, we will always use this original copy
            // as the base
            orig_src.src = image_target.src

            // add events
            container.addEventListener('mousedown', startResize)
            image_target.addEventListener('mousedown', startMoving)
            cropBtn.addEventListener('click', crop)
        }

        init()
    }

    // initializing the canvas and the target image
    const image = document.getElementById('img')
    resizeableImage(image)
</script>

From the documentation, these are the parameters for drawImage:

drawImage(image,
    sx, sy, sw, sh,
    dx, dy, dw, dh);

enter image description here

So, to crop the outer 10 pixels from the source image (Assuming it's 100 * 50), and then to scale that up to 160*60:

ctx.drawImage(image,
    10, 10,   // Start at 10 pixels from the left and the top of the image (crop),
    80, 30,   // "Get" a `80 * 30` (w * h) area from the source image (crop),
    0, 0,     // Place the result at 0, 0 in the canvas,
    160, 60); // With as width / height: 160 * 60 (scale)

Example:

const image = new Image(),
      canvas = document.getElementById('canvas'),
      ctx = canvas.getContext('2d');

image.src = 'https://i.stack.imgur.com/I4jXc.png';

image.addEventListener('load', () => {
    ctx.drawImage(image,
        70, 20,   // Start at 70/20 pixels from the left and the top of the image (crop),
        50, 50,   // "Get" a `50 * 50` (w * h) area from the source image (crop),
        0, 0,     // Place the result at 0, 0 in the canvas,
        100, 100); // With as width / height: 100 * 100 (scale)
});
Image: <br/>
<img src="https://i.stack.imgur.com/I4jXc.png" /><br/>
Canvas: <br/>
<canvas id="canvas" width="275px" height="95px"></canvas>

Before drawing onto the canvas, specify the final canvas size with canvas.width and canvas.height otherwise the final will always be 300x150