【问题标题】:Append canvas images to input array with JavaScript使用 JavaScript 将画布图像附加到输入数组
【发布时间】:2015-04-30 16:05:26
【问题描述】:

我正在尝试编写我的代码,但我没有成功。 基本上我想要的是将调整大小算法应用于用户选择的多个图像,使它们在 HTML5 Canvas 中,然后将每个字符串(DataURL)插入输入数组中以通过 POST 方法发送。

我的代码(客户端)index.html:

<html>
    <head>
    </head>
    <body>
        <input type="file" id="pictures" multiple><br>
        <form id="frm" action="save.php" method="POST">
            <input type="hidden" name="sizedpics[]" id="sizedpics">
            <button type="button" onclick="resize()">submit!</button>
        </form>
        <canvas style="display:none;" id="canvas" width="800"></canvas><br>
        <script>
            var pics=[];
            function resize()
            {
                var numpictures=pictures.files.length;
                var compresion=0.5;
                var dataurl;
                for (i=0;i<numpictures;i++)
                {
                    var canvas = document.getElementById("canvas");
                    var ctx = canvas.getContext("2d");

                    img = new Image();
                    img.onload = function () 
                    {
                        canvas.height = canvas.width * (img.height / img.width);

                        /// step 1
                        var oc = document.createElement('canvas'), octx = oc.getContext('2d');
                        oc.width = img.width * compresion;
                        oc.height = img.height * compresion;
                        octx.drawImage(img, 0, 0, oc.width, oc.height);

                        /// step 2
                        octx.drawImage(oc, 0, 0, oc.width * compresion, oc.height * compresion);

                        ctx.drawImage(oc, 0, 0, oc.width * compresion, oc.height * compresion, 0, 0, canvas.width, canvas.height);

                        // Step 3
                        dataurl = canvas.toDataURL("image/jpeg");
                        pics.push(dataurl);
                    }
                    img.src = window.URL.createObjectURL(pictures.files[i]);
                }
                document.getElementById("sizedpics").value=pics;
                document.forms["frm"].submit();
            }
        </script>
    </body>
</html>

我的代码(服务器)save.php

<?php
    print_r(count($_POST['sizedpics']));exit();
?>

我认为与 javascript 同步存在问题,但我不知道如何解决,我需要使用单个输入“sizedpics”将所有图像(base64 编码的 DataURL 字符串)发送到我的服务器。

你们中的一些人知道错误在哪里吗? 感谢您的阅读,请原谅我写英语的糟糕方式:-)

【问题讨论】:

    标签: javascript html canvas asynchronous html-input


    【解决方案1】:

    编辑:更新了答案中的 cmets 并更新了代码。

    有很多事情阻止了您的代码工作,唉,我累了,忘记记下它们,忘记了细节。 :(

    您可能希望查看以下代码。

    它使用 fileReader 和 .readAsDataURL 方法加载图像。然后在完成时触发用户提供的回调。然后,此回调方法尝试将 dataURL 作为图像加载。当(如果!)成功时,图像被绘制到缩放的画布上,然后检索该画布的 dataURL。将此 dataURL 添加到数组中,并将缩放图像的数量与所选图像的数量进行比较。当两个数字匹配时,它会在提交表单之前对数组进行 JSON 编码并将其填充到隐藏的输入中。

    在 php 端,我们获取提交的数据并进行 JSON 解码。然后我们显示这个数组中图片的数量,然后将每个元素输出为图片的src,以确认上传成功。

    我添加了代码,以确保所选文件是图像,然后再进行进一步处理。您可以选择文件的混合列表,并且只处理图像。 当所选文件是图像但尝试将其加载到 img 元素中失败时,我不处理这种情况。

    resizeAndUpload.html

    <html>
    <head>
    <script>
    function newEl(tagName){return document.createElement(tagName);}
    
    var nFiles, nSized, nPics, mPicArray;
    
    function myResizeAll()
    {
        nFiles = pictures.files.length;
        nSized = 0;
        nPics = 0;
        mPicArray = [];
    
        // work out how many of the chosen files are images
        for (var i=0; i<nFiles; i++)
        {
            if (pictures.files[i].type.indexOf("image") != -1)
                nPics++;
        }
    
        // now try to load the ones that are images
        for (var i=0; i<nFiles; i++)
        {
            if (pictures.files[i].type.indexOf("image") != -1)
                loadFileObject( pictures.files[i], onFileDataLoaded );
        }
    }
    
    // callback gets data via the .target.result field of the param passed to it.
    function loadFileObject(fileObj, loadedCallback)
    {
        var reader = new FileReader();
        reader.onload = loadedCallback;
        reader.readAsDataURL( fileObj );
    }
    
    function onFileDataLoaded(e)
    {
        var tmpImg = newEl('img');
        tmpImg.addEventListener('load', onImgElemLoaded, false);
        tmpImg.src = e.target.result;
    }
    
    function onImgElemLoaded(evt)
    {
        // create a canvas
        var can = newEl('canvas');
        var ctx = can.getContext('2d');
    
        // scale it
        var scale = 0.5;
        can.width = this.width * scale;
        can.height = this.height * scale;
    
        // draw scaled image
        ctx.drawImage(this, 0, 0, can.width, can.height);
    
        // get dataURL
        var resizedImgDataURL = can.toDataURL();
        mPicArray.push( resizedImgDataURL );
    
        nSized++;
    
        // when all image files have been loaded, then loaded as image elements and finally resized on a canvas,
        // submit the data.
        if (nSized == nPics)
        {
            document.getElementById("sizedpics").value= JSON.stringify(mPicArray);
            document.forms["frm"].submit();
        }
    }
    </script>
    </head>
    <body>
        <input type="file" id="pictures" multiple><br>
        <form id="frm" action="save.php" method="POST">
            <input type="hidden" name='sizedpics' id="sizedpics"/>
            <button type="button" onclick="myResizeAll()">submit!</button>
        </form>
        <canvas id="canvas" style='display:none' width="800"></canvas><br>
    </body>
    </html>
    

    save.php

    <?php
        $imgArray = json_decode( $_POST['sizedpics'] );
    
        print_r( count($imgArray) );
    
        $numPics = count($imgArray);
        for ($i=0; $i<$numPics; $i++)
        {
            printf("<img src='%s'/>\n", $imgArray[$i]);
        }
    ?>
    

    输出

    你的英语还不错,比很多以英语为母语的人都好。 ;)

    【讨论】:

    • 很好,谢谢,我有一个离题的问题:我在您的示例中看到的视频游戏机是什么?
    • 不客气。这是任天堂进入游戏世界的原创作品之一。事实上,我的理解是这是第一次。它被称为 Ball,于 1980 年发行,是 1980 年至 1991 年运行的系列“Game & Watch”的一部分。马里奥第一次出现在名为 Donkey Kong 的橙色 2 屏幕游戏中。哇,我们小时候曾经杀死过那个游戏。 :smiles: 你可以在这里开始阅读所有关于他们的信息:en.wikipedia.org/wiki/List_of_Game_%26_Watch_games
    • 有趣!谢谢。
    • 抱歉,我在调整图像大小时遇到​​了问题。我添加了以下代码: if (dataUrl.indexOf("data:image") == -1) { nPics--; } 后面 var dataUrl = e.target.result;但不知道将代码放在哪里我的代码以减少图像:\因为它们是DataURLs,我对javascript比较陌生:c
    • 没问题。我已更新代码以包含此步骤。就像我们必须使用回调来知道文件数据何时加载一样,我们必须使用另一个回调来知道该文件数据何时加载到 img 元素中。最后,请不要像之前那样编辑帖子。您 (a) 改变了帖子的意图,(b) 引入了新错误并错过了结束 body/html 标记,最后 (c ) 试图回复我。这样做会使答案没有用,实际上是错误的。不是每个人都会在编辑和修复它时注意到这样的错误。缩进变化是好的:)
    猜你喜欢
    • 2013-12-09
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    • 2016-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多