UNPKG

scrawl-canvas

Version:

Responsive, interactive and more accessible HTML5 canvas elements. Scrawl-canvas is a JavaScript library designed to make using the HTML5 canvas element easier, and more fun

132 lines (85 loc) 3.59 kB
// # Cell-fragment factory // Create a highly reduced CellFragment which supplies the cell pool // #### Imports import { doCreate, λnull, λcloneError, Ωempty } from '../helper/utilities.js'; import { makeState } from './state.js'; import baseMix from '../mixin/base.js'; import cellMix from '../mixin/cell-key-functions.js'; import { getCanvasColorSpace } from '../core/user-interaction.js'; // Shared constants import { _2D, CANVAS, DISPLAY_P3, LEFT, SRGB, TOP } from '../helper/shared-vars.js'; // Local constants const T_CELLFRAGMENT = 'CellFragment'; // #### CellFragment constructor const CellFragment = function (name, colorSpace = SRGB) { this.name = name; const element = this.element = document.createElement(CANVAS); this.engine = element.getContext(_2D, { willReadFrequently: true, colorSpace, }); element.width = 1; element.height = 1; const state = this.state = makeState(Ωempty); state.setStateFromEngine(this.engine); return this; }; // #### CellFragment prototype const P = CellFragment.prototype = doCreate(); P.type = T_CELLFRAGMENT; // #### Mixins baseMix(P); cellMix(P); // #### Packet/Clone management // This functionality is disabled for CellFragments objects P.stringifyFunction = λnull; P.processPacketOut = λnull; P.finalizePacketOut = λnull; P.saveAsPacket = function () { return `[${this.name}, ${this.type}, ${this.lib}, {}]` }; P.clone = λcloneError; // #### Kill functionality // None required P.setDimensions = function (w, h) { this.w = w; this.h = h; this.element.width = w; this.element.height = h; // Resetting canvas dimensions sets the canvas engine back to system default values // + As we always require `textAlign` and `textBaseline` to be 'left' and 'top' respectively, we reset them here. // + `requestCell` will always call this function before releasing a pool cell into the wild. this.engine.textAlign = LEFT; this.engine.textBaseline = TOP; }; P.clearCell = function () { this.engine.clearRect(0, 0, this.w, this.h); }; // #### Cell pool // A number of processes - for instance collision functionality, and applying filters to entitys and groups - require the use of a <canvas> element and its CanvasRenderingContext2D engine. Rather than generate these canvas elements on the fly, we store them in a pool, to help make the code more efficiant. // // To use a pool cell, request it using the exposed __requestCell__ function. // // IT IS IMPERATIVE that requested cells are released once work with them completes, using the __releaseCell__ function. Failure to do this leads to impaired performance as Javascript creates new canvas elements (often in multiples of 60 per second) which need to be garbage collected by the Javascript engine, thus leading to increasingly shoddy performance the longer the animation runs. const cellPool = []; let count = 0; // `Exported function` - __requestCell__ export const requestCell = function (w = 1, h = 1, colorSpace = SRGB) { if (!cellPool.length) { cellPool.push(new CellFragment(`pool_${count++}`, getCanvasColorSpace(colorSpace === DISPLAY_P3))); } const c = cellPool.shift(); c.setDimensions(w, h); c.engine.save(); return c; }; export const releaseCell = function (...args) { args.forEach(a => { if (a && a.type === T_CELLFRAGMENT) { a.setDimensions(1, 1); a.engine.restore(); a.state.setStateFromEngine(a.engine); cellPool.push(a); } }); };