使用javascript和车把在拖放中渲染图像

Render images on drag-and-drop, using javascript and handlebars

本文关键字:图像 拖放 javascript 使用      更新时间:2023-09-26

我正在尝试使用拖放技术在div中渲染多个图像。

但我没有得到预期的结果,无论我尝试什么,我都是重复图像,并覆盖namesizetype属性。

编辑好的,我意识到为什么我得到一个空的data数组。因为那时事件onload时间未完成,因此没有可用的数据。

但是现在我不知道如何解决在下面定义的问题评论,关于如何在加载所有文件时仅呈现一次模板。

任何人都可以提供一些关于这些数据应该如何准备稍后调用 Handlebars 的线索吗?

js/filedrop.js

(function(){
    "use strict";
    // define the drop zone
    var dropZone = document.getElementById("drop-zone");
    // add  a drag over event to the zone
    dropZone.addEventListener("dragover", function(e){
        e.preventDefault();
        // add a hover class so we can see it's working
        dropZone.setAttribute("class", "over");
    }, false);
    // on file drop grab all available image information
    dropZone.addEventListener("drop", function(e){
        "use strict";
        e.preventDefault();
        var
        reader,
        files = e.dataTransfer.files,
        fileCount = files.length,
        i;
        // get the Handlebars template
        var handlebarTemplate = document.getElementById("handlebar-template");
        var template = Handlebars.compile(handlebarTemplate.innerHTML);
        if(fileCount > 0){
            var data = [], currObj = {};
            for(i = 0; i < fileCount; i = i + 1){
                var file = files[i];
                reader = new FileReader();
                // remove the hover class
                dropZone.removeAttribute("class");
                reader.onload = function(e){
                    currObj = {
                        name : file.name,
                        size : file.size,
                        type : file.type,
                        source: e.target.result
                    };
                    data.push(currObj);
                    // PROBLEM, how to load template once all files are loaded
                    // because leaving it like this will load some files multiple times
                    // also name, size and type attributes will be overwritten so I will get
                    // same attributes for all loaded images.
                    dropZone.innerHTML += ( template(data) );
                };
                // render the image as a data url
                reader.readAsDataURL(file);
            } //end for loop
            //console.log(data); I got this! See above EDIT

        } //end if
    }, false); //end listener
})();

索引.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Chapter 12</title>
        <style type="text/css" media="screen">
            #drop-zone {
                min-height: 300px;
                max-width: 300px;
                padding: 15px;
                border: 4px dashed #999;
            }
            #drop-zone img {
                max-width: 100%;
                display: block;
            }
            .over {
                border-color: #333;
                background: #ddd;
            }
            ul {
                padding: 0;
                list-style: none;
                color: #333;
            }
        </style>
    </head>
    <body>
        <div id="drop-zone">
            <script id="handlebar-template" type="text/x-handlebars-temlate">
                <div class="img-slot">
                    {{#each this}}
                    <img src="{{source}}" alt="{{name}}">
                    <ul>
                        <li>{{name}}</li>
                        <li>{{type}}</li>
                        <li>{{size}}</li>
                    </ul>
                    {{/each}}
                </div>
            </script>
        </div><!-- /#drop-zone -->
        <script src="bower_components/handlebars/handlebars.min.js"></script>
        <script src="js/filedrop.js"></script>
    </body>
</html>

经过一番调整和思考,终于我做到了。请参阅文件内评论,了解我如何解决问题的说明。

(function(){
    "use strict";
    // define the drop zone
    var dropZone = document.getElementById("drop-zone");
    ...
    ...
    // on file drop grab all available image information
    dropZone.addEventListener("drop", function(e){
        "use strict";
        e.stopPropagation();
        e.preventDefault();
        // get the Handlebars template instance
        var handlebarTemplate = document.getElementById("handlebar-template"),
            template = Handlebars.compile(handlebarTemplate.innerHTML);
        // declare some variables
        var reader,
            files = e.dataTransfer.files,
            i;
        if(files.length > 0){
            var data = [], f;
            for(i = 0, f; f = files[i]; i++){
                reader = new FileReader();
                // have control over which file is being processed by
                // wrapping it all into another anonymous function and
                // passing `theFile` argument from loop iteration
                reader.onload = (function(theFile){
                    return function(e){
                        var imgObj = {
                            name: theFile.name,
                            type: theFile.type,
                            size: theFile.size,
                            source: e.target.result
                        };
                        data.push(imgObj);
                        // check if all files loaded, so we can then handover to Handlebars.js
                        if (data.length == files.length){
                            renderTemplate();
                        }
                    }
                })(f);
                // render the image as a data url
                reader.readAsDataURL(f);
            } //end for loop
        } //end if
        // Handover data to Handlebars.js
        function renderTemplate(){
            dropZone.innerHTML += ( template(data) );
        }
    }, false); //end listener
})();