javascriptsvgp5.jsptskirby

pts.js 'NS_ERROR_NOT_AVAILABLE: ' Error when trying to use an image for a particle


I'm wanting to load the same an image for particles in pts.js.

When I try to use a local image from my assets folder I get the error "NS_ERROR_NOT_AVAILABLE:" in the console.

I read somewhere this may be due to the image trying to be used before it has even been loaded in...

I've also tried using an external link to some other image rather than a local one and that works. So not sure what is happening with my local files.

EDIT:

I just tried this on chrome rather than firefox and I'm getting a new and more detailed error message.

"Uncaught DOMException: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The HTMLImageElement provided is in the 'broken' state." in pts.min.js:6.

Still not sure exactly what is wrong.

Pts.quickStart('#hello', 'transparent')

var world

// Loading in image to be used
var myImg = new Image()
myImg.src = '/assets/img/myImage.png'

space.add({
  start: (bound, space) => {
    // Create world and 100 random points
    world = new World(space.innerBound, 1, 0)
    let pts = Create.distributeRandom(space.innerBound, 20)

    // Create particles and hit them with a random impulse
    for (let i = 0, len = pts.length; i < len; i++) {
      let p = new Particle(pts[i]).size(i === 0 ? 10 : 20)
      p.hit(0, 0)
      world.add(p)
    }

    world.particle(0).lock = true
  },

  animate: (time, ftime) => {
    world.drawParticles((p, i) => {


// Image variable for the particle to be drawn as
      form.image(myImg)
    })

    world.update(ftime)
  },

  action: (type, px, py) => {
    if (type == 'move') {
      world.particle(0).position = new Pt(px, py)
    }
  },

  resize: (bound, evt) => {
    if (world) world.bound = space.innerBound
  }
})

space.bindMouse().bindTouch()
space.play()


Solution

  • For drawing images on canvas, the image needs to be loaded first. You can keep track of it using myImg.addEventListener( 'load', ... ).

    Once it's loaded, you can use it in form.image( myImg, ... ) in Pts' animate loop.

    Here's a working example based on your code above:

    Pts.quickStart( "#pt", "#123" );
    
    //// Demo code starts (anonymous function wrapper is optional) ---
    
    (function() {
    
      var world;
      var imgReady = false;
    
        // Loading in image to be used
        var myImg = new Image()
        myImg.src = 'http://icons.iconarchive.com/icons/icojoy/maneki-neko/256/cat-6-icon.png';
        myImg.addEventListener('load', function() {
            imgReady = true;
        }, false);
    
      space.add( {
    
        start: (bound, space) => {
    
          // Create world and 100 random points
          world = new World( space.innerBound, 1, 0 );
          let pts = Create.distributeRandom( space.innerBound, 100 );
    
          // Create particles and hit them with a random impulse
          for (let i=0, len=pts.length; i<len; i++) {
            let p = new Particle( pts[i] ).size( (i===0) ? 30 : 3+Math.random()*space.size.x/50 );
            p.hit( Num.randomRange(-50,50), Num.randomRange(-25, 25) );
            world.add( p );
          }
    
          world.particle( 0 ).lock = true; // lock it to move it by pointer later on
    
        },
    
    
        animate: (time, ftime) => {
          world.drawParticles( (p, i) => {
            if (imgReady) {
              console.log( p )
              form.image(myImg, [p.$subtract( p.radius ), p.$add( p.radius )] );
            }
          });
    
          world.update( ftime );
        },
    
    
        action:( type, px, py) => {
          if (type == "move") {
            world.particle( 0 ).position = new Pt(px, py);
          }
        },
    
        resize: (bound, evt) => {
          if (world) world.bound = space.innerBound;
        }
      });
    
      space.bindMouse().bindTouch();
      space.play();
    
    })();