<!DOCTYPE html> <html> <head> <script src="https://code.createjs.com/1.0.0/easeljs.min.js"></script> <script src="https://code.createjs.com/1.0.0/tweenjs.min.js"></script> <script src="/api/assetProxy?url=http://images.neopets.com/cp/items/data/000/000/564/564507_fc3216b9b8/all-item_foreground_lower.js"></script> </head> <body> <div style="display: flex; justify-content: center;"> <div style=" width: 100%; max-width: 600px; border: 1px solid #aaa; position: relative; " > <div style="padding-bottom: 100%;"></div> <canvas id="stage-canvas" style=" position: absolute; left: 0; right: 0; top: 0; bottom: 0; width: 100%; height: 100%; " ></canvas> </div> </div> <div style="margin-top: 1em; text-align: center;"> <button id="show-hide">Show/hide</button> <button id="pause-play">Pause/play</button> </div> <script> function loadImage(src) { return new Promise((resolve, reject) => { const image = new Image(); image.onload = () => resolve(image); image.onerror = (e) => reject(e); image.src = src; }); } function proxyUrl(url) { return "/api/assetProxy?url=" + encodeURIComponent(url); } async function main() { const composition = Object.values(AdobeAn.compositions)[0]; const library = composition.getLibrary(); const manifestImages = new Map( library.properties.manifest.map(({ id, src }) => [ id, loadImage( proxyUrl( "http://images.neopets.com/cp/items/data/000/000/564/564507_fc3216b9b8/" + src ) ), ]) ); try { await Promise.all(manifestImages.values()); } catch (e) { console.error("Error loading images", e); return; } const spriteSheets = composition.getSpriteSheet(); for (const { name, frames } of library.ssMetadata) { const image = await manifestImages.get(name); spriteSheets[name] = new createjs.SpriteSheet({ images: [image], frames, }); } const movieClip = new library.allitem_foreground_lower(); const canvas = document.getElementById("stage-canvas"); const stage = new library.Stage(canvas); canvas.width = canvas.offsetWidth * window.devicePixelRatio; canvas.height = canvas.offsetHeight * window.devicePixelRatio; stage.scaleX = (canvas.offsetWidth * window.devicePixelRatio) / library.properties.width; stage.scaleY = (canvas.offsetHeight * window.devicePixelRatio) / library.properties.height; movieClip.cache( 0, 0, library.properties.width, library.properties.height ); movieClip.alpha = 0; const tween = createjs.Tween.get(movieClip, { paused: true }).to( { alpha: 1 }, 200 ); stage.on( "drawend", () => { tween.paused = false; }, null, true ); stage.addChild(movieClip); // FPS-ish updates with RAF! https://stackoverflow.com/a/19772220/107415 // Quite a bit going on here, the basic idea is that we want to update // the stage _more often_ than we update the MovieClip, because we want // fade-ins to happen with as high of a frame-rate as possible, but we // want the movie itself to run at its canonical FPS. So, we set the // Ticker into `requestAnimationFrame` mode to send a global tick every // time we get to draw, and update the stage on every such tick - but // we only let it tick its _children_ if enough time has passed since // the last one. const movieTickInterval = 1000 / library.properties.fps; let lastMovieTick = performance.now(); let pauseMovies = false; createjs.Ticker.timingMode = createjs.Ticker.RAF; createjs.Ticker.on("tick", () => { const now = performance.now(); const elapsed = now - lastMovieTick; if (elapsed > movieTickInterval && !pauseMovies) { stage.tickOnUpdate = true; lastMovieTick = now - (elapsed % movieTickInterval); movieClip.updateCache(); } else { stage.tickOnUpdate = false; } stage.update(); }); document.getElementById("show-hide").addEventListener("click", () => { tween.reversed = !tween.reversed; tween.setPosition(0); tween.paused = false; }); document.getElementById("pause-play").addEventListener("click", () => { pauseMovies = !pauseMovies; }); } main(); </script> </body> </html>