UNPKG

scrawl-canvas

Version:
196 lines (153 loc) 6.72 kB
// # Demo Canvas 046 // Kill cycles for Cell, Group, Tween/Ticker, Picture and Asset objects, and Picture source elements in the DOM // [Run code](../../demo/canvas-046.html) import * as scrawl from '../source/scrawl.js'; import { reportSpeed } from './utilities.js'; // #### Smoke ring generator // We could place this code in its own module then import it into this code // + The generator creates a new Cell, adds a Polyline entity to it, compiles the Cell and captures the output into a DOM image. // + It then destroys the Cell and Polyline and creates a Picture entity from the asset they produced // + Finally it constructs a Tween to animate various aspects of the Picture entity // + When the Tween completes it will destroy the image asset wrapper and the Picture entity, then remove the &lt;img> element from the DOM, after which it will destroy itself // + In other words, by the time the Tween completes, none of the objects generated for the smoke ring effect should remain in the Scrawl-canvas library or the page DOM. // Use a Color object to generate colors on demand, in a restricted color range const colorMaker = scrawl.makeColor({ name: 'color-maker', minimumColor: 'blue', maximumColor: 'green', }); // To avoid nameclashes, we're using a counter as part of the smokering's name let counter = 0; // The main function const buildSmokeRing = function (namespace, canvasWrapper, color) { // Create new Cell const cell = canvasWrapper.buildCell({ name: `${namespace}-cell`, width: 600, height: 600, cleared: false, compiled: false, shown: false, }); // Create a set of coordinates to be consumed by the Polyline entity const v = scrawl.requestVector(0, 200), pins = []; for (let i = 0; i < 120; i++) { v.rotate((Math.random() * 45) - 10); pins.push([v.x + ((Math.random() * 120) - 60) + 300, v.y + ((Math.random() * 120) - 60) + 300]) } scrawl.releaseVector(v); // Create Polyline entity let snake = scrawl.makePolyline({ name: `${namespace}-snake`, group: `${namespace}-cell`, pins: pins, start: ['center', 'center'], handle: ['center', 'center'], lineWidth: 2, lineJoin: 'round', tension: 1, strokeStyle: color, method: 'draw', globalAlpha: 0.1, }); // We need to perform a clear-compile on the Cell, outside of the Display cycle cell.clear(); scrawl.createImageFromCell(cell, true); cell.compile(); snake.kill(); cell.kill(); // Create the Picture entity which will destroy the (dearly departed) Polyline on the canvas let img = scrawl.makePicture({ name: `${namespace}-smokering`, group: canvasWrapper.base.name, start: ['center', 'center'], handle: ['center', 'center'], asset: `${namespace}-cell-image`, // 'dom' - is the magic String that tells Scrawl-canvas to remove both the asset wrapper object, and the &lt;img> element itself. Any other non-false value will cause only the asset wrapper object to remove itself. removeAssetOnKill: 'dom', dimensions: [600, 600], copyDimensions: [600, 600], }); // Create the Tween that will animate the Picture entity scrawl.makeTween({ name: `${namespace}-tween`, duration: '16s', targets: `${namespace}-smokering`, // The Tween will run once and then destroy the Picture, the &lt;img> element and its asset wrapper, and then itself cycles: 1, killOnComplete: true, completeAction: () => { img.kill(true); counter++; buildSmokeRing(`ring${counter}`, canvas, colorMaker.getRangeColor(Math.random())); }, definitions: [ { attribute: 'scale', start: 0, end: 2, engine: 'easeIn3', }, { attribute: 'globalAlpha', start: 1, end: 0, }, { attribute: 'roll', start: 0, end: (Math.random() * 180) - 90, engine: 'easeIn', }, ] }).run(); }; // #### Scene setup const canvas = scrawl.library.canvas.mycanvas; // #### Scene animation // Function to display frames-per-second data, and other information relevant to the demo const report = reportSpeed('#reportmessage', function () { const lib = scrawl.library; return `Cells: ${lib.cellnames.join(', ')} Groups: ${lib.groupnames.join(', ')} Assets: ${lib.assetnames.join(', ')} Entitys: ${lib.entitynames.join(', ')} Tickers: ${lib.animationtickersnames.join(', ')} Tweens: ${lib.tweennames.join(', ')}`; }); // Create the Display cycle animation const render = scrawl.makeRender({ name: 'demo-animation', target: canvas, afterShow: report, }); // The tween runs for 16 seconds, and we want a regular supply of rings ... so we release some initially to get the scene running setTimeout(() => buildSmokeRing(`initRingFirst`, canvas, colorMaker.getRangeColor(Math.random())), 0); setTimeout(() => buildSmokeRing(`initRingSecond`, canvas, colorMaker.getRangeColor(Math.random())), 3700); setTimeout(() => buildSmokeRing(`initRingThird`, canvas, colorMaker.getRangeColor(Math.random())), 8100); setTimeout(() => buildSmokeRing(`initRingFourth`, canvas, colorMaker.getRangeColor(Math.random())), 12300); // We also want to halt the animation when the browser page loses focus, and resume them when it regains focus // + We could use` scrawl.stopCoreAnimationLoop()` and `scrawl.startCoreAnimationLoop()` to achieve this, but that action will stop ALL canvas animations on the page, not just this demo. // + Instead, we can halt/resume/run our render animation, and also any existing smoke ring Tweens. window.addEventListener('blur', () => { scrawl.library.animationtickersnames.forEach(t => { if (t.indexOf('ring') === 0) { let ticker = scrawl.library.animationtickers[t]; if (ticker) ticker.halt(); } }); render.halt(); }); // We could add the focus event listener the same as we did the blur listener, or we can add it using Scrawl-canvas functionality: scrawl.addNativeListener('focus', () => { scrawl.library.animationtickersnames.forEach(t => { if(t.indexOf('ring') === 0) { let ticker = scrawl.library.animationtickers[t]; if (ticker) ticker.resume(); } }); render.run(); }, window); // #### Development and testing console.log(scrawl.library);