0

Sorry, I've read the responses to several similar problems, but I can't seem to understand them well enough to apply it to my own problem. I'm hoping seeing the solution to my own code will help to make it click!

I'm working with canvas images, and need to make sure they load before I attempt to grab data from them. So, I'm using a for loop to assign the final portion of the script to the onload event for each image.

I suspect the problem is that my variables are not being preserved by the time the onload event fires, but can't for the life of me figure out how to fix that. Here's the closest attempt I've made, which actually does work for the final slide. No errors, but setSliderBG doesn't appear to be applied to any except the final slide:

    function loadCanvasImages(){
        var slides = $('.slide');
        var num_of_slides = slides.length;
        for(i = 0; i < num_of_slides; i++){
            var slide = slides.eq(i);
            var img_url = slide.css('background-image');
            var canvas = document.getElementById('slide_' + i);
            var the_image = new Image();
            the_image.src = img_url.slice(5, -2);
            globalTestVar = canvas;
            the_image.onload = (function(){
                setSliderBG(slide, canvas, the_image);
            });
        }
    }

And here is the related code:

    function getSliderColor(canvas){
        var context = canvas.getContext('2d');
        var sample_pixel = context.getImageData(0, 0, 1, 1);
        var rgba = sample_pixel.data[0] + ", " + sample_pixel.data[1] + ", " + sample_pixel.data[2] + ", " + sample_pixel.data[3];

        return rgba;
    }

    function setSliderBG(slide, canvas, the_image){
        var context = canvas.getContext('2d');
        context.drawImage(the_image, 0, 0);
        var rgba = getSliderColor(canvas);
        slide.css("background-color", "rgba(" + rgba + ")");
    }

Thanks!

EDIT Nevermind, I got it. I had overlooked that I needed to have my anonymous function actually return a function as well. I changed the code to:

            the_image.onload = (function(slide, canvas, the_image){
                return function(){
                    setSliderBG(slide, canvas, the_image);
                }
            })(slide, canvas, the_image);

And now everything's peachy. Still trying to really grok why that works, but I'll get it.

  • @Pointy although this has been closed, it's worth pointing out that when one already has an array (or can trivially get one) then a simple `$.each` or `array.forEach` block is a far simpler way of closing over each element of that array than the other tricks usually used to close over a plain loop index variable as shown in every answer to the question you closed this one against. – Alnitak Apr 24 '15 at 20:59
  • That's a good point, @Alnitak, and maybe that should be added as an answer (or to the top answer) on that "simple practical example" question. Since this comes up almost hourly it seems, that question is pretty easy to find and makes a good repository. I'd be happy to do it or you may if you'd prefer. (What I think you're saying is that each iteration via `.forEach()` is its own closure, so this problem sort-of vanishes in a puff of logic, right?) – Pointy Apr 24 '15 at 21:03
  • @Pointy right, that's a good way of putting it. I'm short on time just now, so please add if you can. In this question's case, a simple `$('.slide').each(function(index, slide) { .. })` would have automatically and trivially closed over both the element and its index. – Alnitak Apr 24 '15 at 21:07
  • Thanks @Alnitak, what I have is very clumsy. Thanks for pointing out the better path! – Aaron Simmons Apr 24 '15 at 21:14

0 Answers0