How to access the image data after dropping an image from the html-part of a webpage onto a canvas?

风格不统一 提交于 2019-12-31 04:29:25

问题


This is a follow up question to How to drop texts and images on a canvas? (Firefox 41.0.1)

I simply can't find out how to access the image data of the image I dropped onto the canvas. I tried things like data = event.dataTransfer.getData("image"), but that all doesn't work.

function addDragNDropToCanvas() {
    document.getElementById('canvas').addEventListener("dragover", function(event) { event.preventDefault();}, false);
    //handle the drop
    document.getElementById('canvas').addEventListener("drop", function(event) {
        event.preventDefault();
        console.log('something is dropped on the object with id: ' + event.target.id);
        // var directData=event.dataTransfer.getData("image");
        console.log(event);
        }, false);

 }

There surely is the image-data somewhere incorporated in the drop-event data? Isn't it??? (The image doesn't have an own id-attribute.)


回答1:


Your user might do one (or both) of these two drags:

  • Drag an img element from your webpage onto the canvas, or
  • Drag an image file from your local drive onto the canvas.

If the image is being dragged from your webpage:

  1. Listen for the dragover, drop, and optionally the dragenter events.
  2. When handling all 3 events, tell the browser you're handling the event with event.preventDefault and optionally event.stopPropagation.
  3. In the drop handler, get event.dataTransfer.getData('text/plain') which fetches the.src` of the image that was dropped.
  4. Create a new Image() object using the .src and drawImage to the canvas.

If the image is being dragged from your local drive:

1 & 2. Listen & handle the same events as in the webpage code.

  1. Fetch the local image file(s) that the user dropped which have been placed in event.dataTransfer.files.

  2. Create a FileReader and read each image file. The FileReader.readAsDataURL method will return an image URL that you can use as a .src for an Image object.

  3. drawImage each new image to the canvas.

Here's example code that allows both:

<!doctype html>
<html>
<head>
<style>
    body{ background-color: ivory; }
    #canvas{border:1px solid red; margin:0 auto; }
</style>
<script>
window.onload=function(){

    // canvas related vars
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    // dropZone event handlers
    var dropZone=document.getElementById("canvas");
    dropZone.addEventListener("dragenter", handleDragEnter, false);
    dropZone.addEventListener("dragover", handleDragOver, false);
    dropZone.addEventListener("drop", handleDrop, false);
    //
    function handleDragEnter(e){e.stopPropagation(); e.preventDefault();}
    //
    function handleDragOver(e){e.stopPropagation(); e.preventDefault();}
    //
    function handleDrop(e){
        e.stopPropagation();
        e.preventDefault();
        //
        var url=e.dataTransfer.getData('text/plain');
        // for img elements, url is the img src so 
        // create an Image Object & draw to canvas
        if(url){
            var img=new Image();
            img.onload=function(){ctx.drawImage(this,0,0);}
            img.src=url;
        // for img file(s), read the file & draw to canvas
        }else{
            handleFiles(e.dataTransfer.files);
        }
    }
    // read & create an image from the image file
    function handleFiles(files) {
        for (var i=0;i<files.length;i++) {
          var file = files[i];
          var imageType = /image.*/;
          if (!file.type.match(imageType)){continue;}
          var img = document.createElement("img");
          img.classList.add("obj");
          img.file = file;
          var reader=new FileReader();
          reader.onload=(function(aImg){
              return function(e) {
                  aImg.onload=function(){
                      ctx.drawImage(aImg,0,0);
                  }
                  // 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 below onto the canvas, or<br>Drag an image file from your desktop onto the canvas.</h4>
    <canvas id="canvas" width=300 height=300></canvas>
    <br><img id='sunny' src='https://dl.dropboxusercontent.com/u/139992952/multple/sunny.png'>
    <img id='rainy' src='https://dl.dropboxusercontent.com/u/139992952/multple/rainy.png'>
    <img id='stars' src='https://dl.dropboxusercontent.com/u/139992952/multple/stars.png'>
</body>
</html>



回答2:


Here is a set of (stripped down) tools I use to play with images

var imageTools = (function () {
    var tools = {
        canvas : function (width, height) {  // create a blank image (canvas)
            var c = document.createElement("canvas");
            c.width = width;
            c.height = height;
            return c;
        },
        createImage : function (width, height) {
            var image = this.canvas(width, height);
            image.ctx = image.getContext("2d");
            return image;
        },
        loadImage : function (url, callback) {
            var image = new Image();
            image.src = url;
            image.addEventListener('load', cb);
            image.addEventListener('error', cb);
            return image;
        },
        image2Canvas : function (img) {
            var image = this.canvas(img.width, img.height);
            image.ctx = image.getContext("2d");
            image.drawImage(ig, 0, 0);
            return image;
        },
        getImageData : function (image) {
            return (image.ctx || (this.image2Canvas(image).ctx)).getImageData(0, 0, image.width, image.height).data;
        },
    };
    return tools;
})();

After it is parsed you will have the global variable imageTools

To load and get the image data you will have to wait for the image load callback.

var image;
var imageData;
function loaded(event){
    if(event.type === "load"){
        image = imageTools.image2Canvas(this);
        imageData = imageTools.getImageData(image);
        // image data is now in the typed array
        // imageData.data
        // with imageData.width and imageData.height holding the size
        // there are 4 bytes per pixel in the form RGBA
    }
}
imageTools.loadImage(imageURL,loaded);

To put the data back into the image after using the imageTools

// image.ctx is non standard and is a result of the imageTools adding the 
// attribute ctx
image.ctx.putImageData(imageData,0,0);

To get the URL from the drop event which may be more than one image

var fileList = []; // a list of dropped images
// function called when images dropped
var imagesDropped = function(){
    fileList.forEach(function(image){
        // image.name is the image URL
        // image.type is the mime type    
    });
    fileList = []; // clear the file list
}
var dropEvent = function (event) {
    var i,j, imagesFound;
    imagesFound = false;
    event.preventDefault();
    dt = event.dataTransfer;
    for (i = 0; i < dt.types.length; i++) {  // for each dropped item
        if (dt.types[i] === "Files") { // content from the file system
            for (var j = 0; j < dt.files.length; j++) {
                // check the mime type for the image prefix
                if (dt.files[j].type.indexOf("image/") > -1){
                    fileList.push({  // add to image list
                        name : dt.files[j].name,
                        type : dt.files[j].type,
                    });
                    imagesFound = true;  // flag images found
                }
            }
        }
    }
    if(imagesFound){ // if images dropped call the handling function
        imagesDropped();
    }
}

Please note this is an example only and is not a cross browser solution. You will have to implement a variety of drop managers t cover all the browsers. This works on Chrome so covers the majority of users.



来源:https://stackoverflow.com/questions/34816849/how-to-access-the-image-data-after-dropping-an-image-from-the-html-part-of-a-web

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!