简体   繁体   中英

I can't crop an image from a blob URL using canvas

I'm building an application where users can upload a photo, and then that photo is resized and assigned as the src of a different image tag. I just can't get it to work, and I'm guessing it's because of the blob URL. Any help would be awesome.

Here's the live example .

HTML:

<!DOCTYPE html>
<html>
    <head>
        <meta name='viewport' content='width=device-width,initial-scale=1,minimum-scale=1'>

        <title>Test</title>

        <!-- styles -->
        <link rel="stylesheet" href="http://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css">

        <!-- scripts -->
        <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
        <script src='js/script.js'></script>
    </head>

    <body>
        <label for='existing'>Choose existing photo:</label>
            <input id="existing" type="file" accept="image/*">

        <div id="photo_container">
            <img id="photo" src="" width="640">
            <img id="new">
        </div>

        <canvas width="200"></canvas>
    </body>
</html>

JS:

$(document).ready(
    function()
    {   
        var showPicture = document.querySelector("#photo");
        var takePicture = document.querySelector("#existing");

        takePicture.onchange = function( event )
        {
            var files = event.target.files, file;

            if (files && files.length > 0) 
            {
                file = files[0];
            }

            try 
            {
                var URL = window.URL || window.webkitURL;
                var imgURL = URL.createObjectURL(file);

                showPicture.src = imgURL;

                var canvas = document.querySelector('canvas');
                var newImage = document.querySelector('img#new');
                var ctx = canvas.getContext('2d');
                var photoHeight = showPicture.height;
                var photoWidth = showPicture.width;

                canvas.width = photoWidth;
                canvas.height = photoHeight;

                ctx.drawImage(showPicture, photoWidth/2, photoHeight/2);

                newImage.src = canvas.toDataURL('image/jpeg');
            }

            catch(e) 
            {
                try 
                {
                    var fileReader = new FileReader();

                    fileReader.onload = function (event) 
                    {

                        showPicture.src = event.target.result;

                    };

                    fileReader.readAsDataURL(file);
                }

                catch(e) 
                {

                    var error = document.querySelector("#error");

                    if (error) 
                    {
                        error.innerHTML = "Neither createObjectURL or FileReader are supported";
                    }
                }
            }
        };
    }
);

Here's one way to load a CORS compliant image that has been selected by the user using FileReader.

BTW, remember that if the user loads an image with transparency (eg. .png) then the resulting .jpg will be black where the incoming image is transparent.

Example code and a Demo: http://jsfiddle.net/m1erickson/9e9LD/

My example uses drag/drop but you can substitute file-browse if you prefer.

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
    #dropzone{border:1px solid blue; width:300px;height:300px;}
</style>
<script>
$(function(){

    // dropzone event handlers
    var dropzone;
    dropzone = document.getElementById("dropzone");
    dropzone.addEventListener("dragenter", dragenter, false);
    dropzone.addEventListener("dragover", dragover, false);
    dropzone.addEventListener("drop", drop, false);

    //
    function dragenter(e) {
      e.stopPropagation();
      e.preventDefault();
    }
    //

    function dragover(e) {
      e.stopPropagation();
      e.preventDefault();
    }

    //
    function drop(e) {
      e.stopPropagation();
      e.preventDefault();

      var dt = e.dataTransfer;
      var files = dt.files;

      handleFiles(files);
    }

    //
    function handleFiles(files) {

        for (var i = 0; i < files.length; i++) {

          // get the next file that the user selected
          var file = files[i];
          var imageType = /image.*/;

          // don't try to process non-images
          if (!file.type.match(imageType)) {
            continue;
          }

          // a seed img element for the FileReader
          var img = document.createElement("img");
          img.classList.add("obj");
          img.file = file;

          // get an image file from the user
          // this uses drag/drop, but you could substitute file-browsing
          var reader=new FileReader();
          reader.onload=(function(aImg){
              return function(e) {
                  aImg.onload=function(){

                      // draw the aImg onto the canvas
                      var canvas=document.createElement("canvas");
                      var ctx=canvas.getContext("2d");
                      canvas.width=aImg.width;
                      canvas.height=aImg.height;

                      // I don't know your design requirements about clipping
                      // but you can use the extended form of drawImage to crop
                      // the image as your design requires.

                      ctx.drawImage(aImg,0,0);

                      // make the jpeg image
                      var newImg=new Image();
                      newImg.onload=function(){
                          newImg.id="newest";
                          document.body.appendChild(newImg);
                      }
                      newImg.src=canvas.toDataURL('image/jpeg');
                  }
                  // e.target.result is a dataURL for the image
                  aImg.src = e.target.result;
              }; 
          })(img);
          reader.readAsDataURL(file);

        } // end for

    } // end handleFiles

}); // end $(function(){});
</script>
</head>
<body>
    <h4>Drag an image from desktop to blue dropzone.</h4>
    <div id="dropzone"></div>
    <div id="preview"></div>
</body>
</html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM