首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >通过javascript循环上载多个画布图像

通过javascript循环上载多个画布图像
EN

Stack Overflow用户
提问于 2015-02-11 15:26:21
回答 3查看 2.4K关注 0票数 0

我正在尝试制作一个上传脚本,它在saveimage.php处理多个图像客户端之前调整它们的大小。之所以如此,是因为它们将被上传到一个外部位置,在那里可能会有非常缓慢的互联网。

我在这里找到了一些代码,这些代码帮助我把它们组合在一起。我只是一个初学者,所以这可能是非常混乱!

它目前所做的是在“file_input”字段中输入文件时进行检查。然后查看文件的数量,并循环遍历它们,直到每个文件都放在画布中,并在文件处于其中时上传。

然而,的问题是:当我不为每个文件添加警报时,循环速度太快,只处理10幅图像中的1或2。因为上传脚本的速度将超过画布可以用新图像更新的速度。

这是我当前的页面,简化为核心:

代码语言:javascript
运行
复制
<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
</head>
<body>

<form>
    <input id="file_input" type='file' multiple />
</form>

<div id="preview">
    <canvas id="canvas"></canvas>
</div>

<script>

    var input = document.getElementById('file_input');
    input.addEventListener('change', handleFiles);

    function handleFiles(e) {

        var files = input.files;
        alert(files.length +" files are being uploaded!"); // display amount of files for testing purpose

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

            alert("Upload file number: "+i); // display file # for testing purpose, when this is removed the script will go too fast

            var MAX_HEIGHT = 1000;
            var ctx = document.getElementById('canvas').getContext('2d');
            var img = new Image;

            img.onload = function(){
                if(img.height > MAX_HEIGHT) {
                    img.width *= MAX_HEIGHT / img.height;
                    img.height = MAX_HEIGHT;
                }
                var ctx = canvas.getContext("2d");
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                preview.style.width = img.width + "px";
                preview.style.height = img.height + "px";
                canvas.width = img.width;
                canvas.height = img.height;
                ctx.drawImage(img, 0, 0, img.width, img.height);

                // the canvas should contain an image now and this will send it through saveimage.php
                var myDrawing = document.getElementById("canvas");
                var drawingString = myDrawing.toDataURL("image/jpeg", 0.5);
                var postData = "canvasData="+drawingString;
                var ajax = new XMLHttpRequest();
                ajax.open("POST",'saveimage.php',true);
                ajax.setRequestHeader('Content-Type', 'canvas/upload');
                ajax.onreadystatechange=function()
                    {
                        if (ajax.readyState == 4);
                    }
                    ajax.send(postData);
            };

            img.src = URL.createObjectURL(e.target.files[i]);
        }
    }

</script>

</body>
</html>

这是我的saveimage.php,它工作得很好,但只用于完整的概述:

代码语言:javascript
运行
复制
<?php

if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
    $rawImage=$GLOBALS['HTTP_RAW_POST_DATA'];
    $removeHeaders=substr($rawImage, strpos($rawImage, ",")+1);
    $decode=base64_decode($removeHeaders);

    // check if the file already exists and keep adding +1 intil it's unique
    $i = 1;
    while(file_exists('uploads/image'.$i.'.jpg')) {           
        $i++;
    }

    $fopen = fopen( 'uploads/image'.$i.'.jpg', 'wb' );
    fwrite( $fopen, $decode);
    fclose( $fopen );

}

?>

一个额外的信息:

  • 我添加了画布,因为据我所知,这是调整图像客户端大小的唯一方法。在最后的脚本中,它将被设置为隐藏。
  • 如果可以跳过画布并立即将数据发送到saveimage.php,那么我认为这也可以解决问题。
  • 正如我说过的,我对javascript不是很有经验,所以如果有更简单的方法来实现这个目标的话。请让我知道!

提前感谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-11 16:44:16

JavaScript异步加载映像。这意味着一旦它被分配给一个新图像的.src,它将开始加载图像,但同时将在.src之后继续处理javascript,而该图像需要时间加载。

在for循环中使用相同的图像变量(var img)。因此,每次通过循环,您都要在前一个映像被完全加载之前覆盖前一个img。

下面是一个图像加载器,它完全加载所有图像,然后调用start()函数,您可以在其中进行处理:

代码语言:javascript
运行
复制
// image loader

// put the paths to your images in imageURLs[]
var imageURLs=[];  
imageURLs.push("myImage1.png");
imageURLs.push("myImage2.png");
// etc, etc.

// the loaded images will be placed in imgs[]
var imgs=[];

var imagesOK=0;
loadAllImages(start);

function loadAllImages(callback){
    for (var i=0; i<imageURLs.length; i++) {
        var img = new Image();
        imgs.push(img);
        img.onload = function(){ 
            imagesOK++; 
            if (imagesOK>=imageURLs.length ) {
                callback();
            }
        };
        img.onerror=function(){alert("image load failed");} 
        img.crossOrigin="anonymous";
        img.src = imageURLs[i];
    }      
}

function start(){

    // the imgs[] array now holds fully loaded images
    // the imgs[] are in the same order as imageURLs[]

}
票数 1
EN

Stack Overflow用户

发布于 2015-02-11 16:23:52

在onload回调中,使用this关键字(而不是img)来处理当前映像,在回调触发之前,img可能/将被覆盖在for循环中。

img.height --> this.height

另外,您使用自定义内容类型而不是application/x-www-form-urlencoded是否有原因?

Url编码的表单数据更容易处理。

票数 0
EN

Stack Overflow用户

发布于 2016-12-18 07:17:18

我已经为同样的问题挣扎了一段时间,但我终于找到了另一个解决方案,使用了其他人的一些代码,这些代码已经解决了这个问题,而且很有效。这可能不是十全十美,我欢迎任何改进建议。概念是,您有两个Javascript函数,它们名为Resize0和Resize1,它们相互调用,直到所有照片都被调整大小,然后调整最后一个图像的大小的函数提交表单。这两个函数相互传递参数,以便其中一个函数知道何时提交表单。其中两个参数是Number_Of_Images和current Image_Number。您还可以从http://www.wantitconsulting.co.nz/ExampleResizeUpload.zip下载一个工作示例网页。您需要在测试网站的基本目录中创建一个文件夹,以便图片进入。它的名字是TestResizeUpload。服务器端使用php。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28458052

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档