【问题标题】:preloading images in html5/javascript在 html5/javascript 中预加载图像
【发布时间】:2012-02-17 19:21:38
【问题描述】:

我见过使用多张图片进行预加载的示例,但是我不知道如何将它们应用到我只有一张图片并且使用 src 换出帧的情况。

我正在制作一个精灵动画,但是由于我要使用的图像太多,所以我必须在开始之前加载它们。

我知道每次切换和加载 src 时都会触发 onload。

如何在运行计时器之前预加载图像?如果我使用“img”onload 进行预加载,是否必须使用另一个 Image 对象才能实际显示?

<script type="text/javascript">
function init(){
    var numLabel;
    var imgNumber = 1;
    var lastImgNumber = 668;
    var canvas = document.getElementById("mycanvas");
    var context = canvas.getContext("2d");
    var img = new Image;

    img.onload = function(){
        context.clearRect(0,0,context.canvas.width,context.canvas.height);
        context.drawImage(img,0,0);
    };
    var timer = setInterval(function(){
        if(imgNumber>lastImgNumber){
        clearInterval(timer);
        }else{
        numLabel = padNum(imgNumber++,5);
        img.src = "sprite images/opt/movie"+numLabel+".jpg";
        }
    }, 1000/24);
}
function padNum(num, digits){ 
    var str = num + ""; 
    return num.length >= digits? str: padNum("0" + str, digits);
}
</script>

编辑:

我最终得到了以下代码。但是,我想我要看看下面提到的精灵表方法。

我基本上尝试用短片制作全屏视频,因为我一直在阅读 html5 中的视频,但全屏仍然存在问题。另外,我认为我可以得到更好的质量。

<script type="text/javascript">
        var imageArray = new Array();
        var loadedImages = new Array();

        function init(){

            buildImageArray(); //Execute the function to create the array of images
            var total = imageArray.length;
            var count = 0;



            // loop through the images and load.
            while(count < total) {
                loadImage("sprite images/opt/" + imageArray[count],count);


                count++;
            }


        }


        function padNum(num, digits){ 
            var str = num + ""; 
            return num.length >= digits? str: padNum("0" + str, digits);
        }

        function buildImageArray(){
            var firstImage = 1;
            var lastImgNumber = 668;
            var numLabel;


            for(var i = firstImage; i<lastImgNumber+1;i++){
                numLabel = padNum(i,5);
                imageArray.push("movie"+numLabel+".jpg");
            }
        }


        function loadImage(imageSrc,position) {
        // actual function that loads image into DOM

        var image = new Image(); // local scope, new object created per instance.
        image.onload = function() {
            if (!image) return;

            loadedImages[position] = image.src; // record this image path as loaded in global scope
            // or... store the objects themselves so you can inject them:
            // loadedImages.push(this);

            // sample report of progress
            reportProgress();

            // remove event and self to prevent IE on animated gif loops and clear up garbage.
            image = image.onload = image.onabort = image.onerror = null;
        };

        image.src = imageSrc;
        }


         function reportProgress() {
        // used to show how many images loaded thus far and / or trigger some event you can use when done.

        // optional to show onscreen..., 'where' should be an object referencing an element in the DOM
        // to do it silently, just remove the output bits below.
        var output = "loaded ";
        output += loadedImages.length;
        output += " of ";
        output += imageArray.length;
        output += " images.";
        $("#loader").html(output);

            // this bit will fire when all images done:
            if (imageArray.length == loadedImages.length) {
                // total images onComplete. done. rewrite as you deem fit - call your main site load function from here

                // keep in mind that if 1 of your images is a 404, this function may not fire, you
                // may want to assign onerror and onabort events

                //fire beginAnimation
                beginAnimation();
            }
        }


        function beginAnimation(){
            var canvas = document.getElementById("mycanvas");
            var context = canvas.getContext("2d");
            var img = new Image;
            var imgNumber = 0;
            var lastImgNumber = 667;


            img.onload = function(){
                context.clearRect(0,0,context.canvas.width,context.canvas.height);
                context.drawImage(img,0,0);


            };
            var timer = setInterval(function(){
                if(imgNumber>lastImgNumber){

                    clearInterval(timer);

                }else{

                    img.src = loadedImages[imgNumber];
                }
                imgNumber++;


            }, 1000/20);

        }

    </script>

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    这不是解决这个问题的方法。

    如果数字更小,我会提供第二种解决方案,但如果你真的有 668 张图像,你需要减少 waaaay。您不希望每个用户(和您的服务器)都发出 668 个请求,当然也不希望一个 IMG 不断交换 src。

    你需要制作一个精灵表。看起来像 this 的单个图像。

    使用类似 texturepacker 的东西来制作你的单图像精灵表:http://www.texturepacker.com/

    当需要在画布上绘图时,您将需要一个数组,其中包含较大图像中每个可能的精灵的 x、y、宽度、高度坐标。

    您将使用画布方法drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh),而不是drawImage(img, x, y)

    这使您可以指定源矩形,每个图像的源矩形都不同。具体来说,这些论点对应于:

    【讨论】:

    • 正如我在编辑中提到的,我想在我的网站设计中添加短视频剪辑。假设我使用的是 1920x1080 图像。这将意味着一个巨大的精灵表。当然我会预先加载精灵表,但是“它”可以处理这么大的图像吗?
    • 如果您上传一个实际的视频文件并将其绘制到画布上会更好。您实际上可以将drawImage&lt;video&gt; 一起使用,它会绘制视频的当前帧
    • 另外,我现在只用 668,但我想我只需要 200
    • Sarris,所以基本上从视频文件中抓取每一帧并像精灵一样播放?这似乎是一个更好的选择。
    • 是的,画布真的会自动完成,我给你举个例子……
    【解决方案2】:

    这是一个 html5 示例,如何使用 knockoutjs https://github.com/mazhekin/HTML5MultiLoadImages 加载多个图像

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多