如何调整大小然后用画布裁剪图像

时间:2014-09-24 11:13:38

标签: javascript html5-canvas

我已经知道如何

- >调整图像大小:

var image = document.getElementById('myImage'),
    canvas = document.createElement('canvas'),
    ctx = canvas.getContext('2d');
ctx.drawImage(image,0,0,400,300);

- >或裁剪图像:

var image = document.getElementById('myImage'),
    canvas = document.createElement('canvas'),
    ctx = canvas.getContext('2d');
ctx.drawImage(image,50,50,image.width,image.height,0,0,50,50);

但我不知道如何调整大小然后裁剪图像。我怎么能这样做?谢谢。

3 个答案:

答案 0 :(得分:58)

documentation开始,这些是drawImage的参数:

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

enter image description here

因此,要从源图像裁剪外部10个像素(假设它100 * 50),然后将其缩放到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)

示例:



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

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

image.onload = function(){
    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>
&#13;
&#13;
&#13;

答案 1 :(得分:2)

在绘制到画布上之前,使用canvas.width和canvas.height指定最终的画布大小,否则最终的总是300x150

答案 2 :(得分:1)

我以本教程为例http://tympanus.net/codrops/2014/10/30/resizing-cropping-images-canvas/,并在vanilla js中做了同样的事情。它可能需要重新整理,但可以正常工作(至少在我的Windows Labtop chrome中)

一个html文件:

<!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>
相关问题