- Jump To … +
  ./demo/canvas-001.js ./demo/canvas-002.js ./demo/canvas-003.js ./demo/canvas-004.js ./demo/canvas-005.js ./demo/canvas-006.js ./demo/canvas-007.js ./demo/canvas-008.js ./demo/canvas-009.js ./demo/canvas-010.js ./demo/canvas-011.js ./demo/canvas-012.js ./demo/canvas-013.js ./demo/canvas-014.js ./demo/canvas-015.js ./demo/canvas-015a.js ./demo/canvas-016.js ./demo/canvas-017.js ./demo/canvas-018.js ./demo/canvas-019.js ./demo/canvas-019a.js ./demo/canvas-020.js ./demo/canvas-021.js ./demo/canvas-022.js ./demo/canvas-023.js ./demo/canvas-024.js ./demo/canvas-025.js ./demo/canvas-026.js ./demo/canvas-027.js ./demo/canvas-028.js ./demo/canvas-029.js ./demo/canvas-030.js ./demo/canvas-031.js ./demo/canvas-032.js ./demo/canvas-033.js ./demo/canvas-034.js ./demo/canvas-035.js ./demo/canvas-036.js ./demo/canvas-037.js ./demo/canvas-038.js ./demo/canvas-039.js ./demo/canvas-040.js ./demo/canvas-041.js ./demo/canvas-042.js ./demo/canvas-043.js ./demo/canvas-044.js ./demo/canvas-045.js ./demo/canvas-046.js ./demo/canvas-047.js ./demo/canvas-048.js ./demo/canvas-049.js ./demo/canvas-050.js ./demo/canvas-051.js ./demo/canvas-052.js ./demo/canvas-053.js ./demo/canvas-054.js ./demo/canvas-055.js ./demo/canvas-056.js ./demo/canvas-058.js ./demo/canvas-059.js ./demo/canvas-060.js ./demo/canvas-061.js ./demo/canvas-062.js ./demo/canvas-063.js ./demo/canvas-064.js ./demo/core-001.js ./demo/delaunator-001.js ./demo/delaunator-002.js ./demo/dom-001.js ./demo/dom-002.js ./demo/dom-003.js ./demo/dom-004.js ./demo/dom-005.js ./demo/dom-006.js ./demo/dom-007.js ./demo/dom-008.js ./demo/dom-009.js ./demo/dom-010.js ./demo/dom-011.js ./demo/dom-012.js ./demo/dom-013.js ./demo/dom-015.js ./demo/dom-016.js ./demo/dom-017.js ./demo/dom-018.js ./demo/filters-001.js ./demo/filters-002.js ./demo/filters-002a.js ./demo/filters-003.js ./demo/filters-004.js ./demo/filters-005.js ./demo/filters-006.js ./demo/filters-007.js ./demo/filters-008.js ./demo/filters-009.js ./demo/filters-010.js ./demo/filters-011.js ./demo/filters-012.js ./demo/filters-013.js ./demo/filters-014.js ./demo/filters-015.js ./demo/filters-016.js ./demo/filters-017.js ./demo/filters-018.js ./demo/filters-019.js ./demo/filters-020.js ./demo/filters-021.js ./demo/filters-022.js ./demo/filters-023.js ./demo/filters-024.js ./demo/filters-025.js ./demo/filters-026.js ./demo/filters-027.js ./demo/filters-028.js ./demo/filters-101.js ./demo/filters-102.js ./demo/filters-103.js ./demo/filters-104.js ./demo/filters-105.js ./demo/filters-501.js ./demo/filters-502.js ./demo/filters-503.js ./demo/filters-504.js ./demo/filters-505.js ./demo/mediapipe-001.js ./demo/mediapipe-002.js ./demo/mediapipe-003.js ./demo/modules-001.js ./demo/modules-002.js ./demo/modules-003.js ./demo/modules-004.js ./demo/modules-005.js ./demo/modules-006.js ./demo/packets-001.js ./demo/packets-002.js ./demo/particles-001.js ./demo/particles-002.js ./demo/particles-003.js ./demo/particles-004.js ./demo/particles-005.js ./demo/particles-006.js ./demo/particles-007.js ./demo/particles-008.js ./demo/particles-009.js ./demo/particles-010.js ./demo/particles-011.js ./demo/particles-012.js ./demo/particles-013.js ./demo/particles-014.js ./demo/particles-015.js ./demo/particles-016.js ./demo/rapier-001.js ./demo/snippets-001.js ./demo/snippets-002.js ./demo/snippets-003.js ./demo/snippets-004.js ./demo/snippets-005.js ./demo/snippets-006.js ./demo/tensorflow-001.js ./demo/tensorflow-002.js ./demo/utilities.js

- §

  # Demo Canvas 019a

  Gradient and Color factories - transparency - alternative approach using Cells instead of images

- §

  Run code

      import {
          library as L,
          importDomImage,
          makeFilter,
          makePicture,
          makeRadialGradient,
          makeBlock,
          makeRender,
          addNativeListener,
      } from '../source/scrawl.js';

      import { reportSpeed } from './utilities.js';

- §

  #### Scene setup

  Get a handle to the Canvas wrapper

      const canvases = L.canvas;

- §

  Namespacing boilerplate

      const namespace = 'demo';
      const name = (n) => `${namespace}-${n}`;

- §

  Import the images we defined in the DOM (in <img> elements)

      importDomImage('.places');

- §

  For this scene, we’ll build a data structure which we can iterate over, to build the entitys, assets and gradients required by the scene

      const data = [
          {
              canvas: canvases['hackney'],
              image: 'hackney-bg',
              transparency: 'transparent',
          },
          {
              canvas: canvases['heathrow'],
              image: 'heathrow-bg',
              transparency: 'rgb(0 0 0 / 0)',
          },
          {
              canvas: canvases['kingston'],
              image: 'kingston-bg',
              transparency: '#00000000',
          },
          {
              canvas: canvases['burglary'],
              image: 'burglary-bg',
              transparency: '#0000',
          },
      ];

- §

  This array will hold a set of functions which we will invoke in turn at the start of each Display cycle

      const checkFunctions = [];

- §

  The blur filter is temporary - we use it once on each image to generate a blurred version of that image

  - We do it this way because the blur filter is computationally very expensive - capturing a blurred version of the image is a lot better for end user power consumption

      makeFilter({
          name: name('blur'),
          method: 'gaussianBlur',
          radius: 20,
      });

- §

  Iterate through our data array to create Scrawl-canvas objects

      data.forEach(scene => {

- §

  Firstly, build the blurred image in its own cell

  - We only need to compile this once, thus don’t include the cell in any part of the Display cycle

          const mycell = scene.canvas.buildCell({

              name: name(`${scene.image}-blurred-cell`),
              dimensions: ['100%', '100%'],
              cleared: false,
              compiled: false,
              shown: false,
          });

          makePicture({

              name: name(`${scene.image}-blurred-image`),
              group: name(`${scene.image}-blurred-cell`),

              asset: scene.image,

              dimensions: ['100%', '100%'],
              copyDimensions: ['100%', '100%'],

              filters: [name('blur')],
              method: 'fill',
          });

- §

  The new Cell’s compile action is blocking, because the blur filter takes a long time to complete. To get something up on the screen we can defer the compile action until after the current RAF completes by putting it in a setTimeout invocation.

          setTimeout(() => mycell.compile(), 0);

- §

  Next, build a gradient using transparency and apply it in a second Block which displays in the original canvas

          makeRadialGradient({

              name: name(`${scene.image}-gradient`),
              start: ['50%', '50%'],
              end: ['50%', '50%'],
              startRadius: '5%',
              endRadius: '20%',

              colors: [
                  [0, scene.transparency],
                  [999, 'lightgray']
              ],
          });

          const gradientBlock = makeBlock({

              name: name(`${scene.image}-gradient-block`),
              group: scene.canvas.base.name,

              start: ['center', 'center'],
              handle: ['center', 'center'],
              dimensions: ['200%', '200%'],

              fillStyle: name(`${scene.image}-gradient`),
              lockFillStyleToEntity: true,
          });

- §

  Now we can draw our blurred image into the scene

  - We use some compositing magic so it only appears where the gradient is not transparent

          makePicture({

              name: name(`${scene.image}-blurred-block`),
              group: scene.canvas.base.name,

              asset: name(`${scene.image}-blurred-cell`),

              dimensions: ['100%', '100%'],
              copyDimensions: ['100%', '100%'],

              method: 'fill',
              globalCompositeOperation: 'source-atop',
          });

- §

  Lastly, display the original image in the canvas

  - Again, we use compositing magic to draw on the bits missed by the blurred image

          makePicture({

              name: name(`${scene.image}-original-image`),
              group: scene.canvas.base.name,

              asset: scene.image,

              dimensions: ['100%', '100%'],
              copyDimensions: ['100%', '100%'],

              method: 'fill',
              globalCompositeOperation: 'destination-over',
          });

- §

  Check whether the mouse cursor is hovering over this canvas, and update the filter Block entity’s positioning accordingly

          const f = () => {

              const here = scene.canvas.here;

              return function () {

                  gradientBlock.set({
                      lockTo: (here.active) ? 'mouse' : 'start',
                  });
              }
          };
          checkFunctions.push(f());
      });

- §

  #### Scene animation

  Function to display frames-per-second data, and other information relevant to the demo

      const report = reportSpeed('#reportmessage');

- §

  Create the Display cycle animation

      makeRender({

          name: name('animation'),
          target: [canvases['hackney'], canvases['heathrow'], canvases['kingston'], canvases['burglary']],
          observer: true,

          commence: () => checkFunctions.forEach(f => f()),
      });

      makeRender({

          name: name('speed'),
          noTarget: true,
          afterShow: report,
      });

- §

  For this demo we will suppress touchmove functionality over the canvas

      addNativeListener('touchmove', (e) => {

          e.preventDefault();
          e.returnValue = false;

      }, [canvases['hackney'].domElement, canvases['heathrow'].domElement, canvases['kingston'].domElement, canvases['burglary'].domElement]);

- §

  #### Development and testing

      console.log(L);