- Jump To … +
  ./demo/modules/canvas-minimap.js ./demo/modules/canvas-scene-editor.js ./demo/modules/demo-m006-c1.js ./demo/modules/demo-m006-c2.js ./demo/modules/demo-m006-c3.js ./demo/modules/demo-m006-c4.js ./demo/modules/demo-m006-utils.js ./demo/modules/dom-entity-editor.js ./demo/modules/entity-copy-paste.js ./demo/modules/entity-manipulation-gui.js ./demo/modules/entity-navigation.js ./demo/modules/entity-ring-builder.js ./demo/modules/london-crime-lines.js ./demo/modules/london-crime-stacked-bars.js ./demo/modules/lottie-loader.js ./demo/modules/simple-chart-frame.js ./demo/modules/simple-graph-lines.js ./demo/modules/simple-graph-stacked-bars.js ./demo/modules/wikipedia-views-spiral-chart.js ./demo/snippets/animated-highlight-gradient-text-snippet.js ./demo/snippets/animated-hover-gradient-snippet.js ./demo/snippets/animated-word-gradient-snippet.js ./demo/snippets/before-after-slider-infographic.js ./demo/snippets/bubbles-text-snippet.js ./demo/snippets/green-box-snippet.js ./demo/snippets/jazzy-button-snippet.js ./demo/snippets/page-performance-snippet-test.js ./demo/snippets/page-performance-snippet.js ./demo/snippets/pan-image-snippet.js ./demo/snippets/placeholder-effect-snippet.js ./demo/snippets/ripple-effect-snippet.js ./demo/snippets/risograph-text-gradient-snippet.js ./demo/snippets/spotlight-text-snippet-test.js ./demo/snippets/spotlight-text-snippet.js ./demo/snippets/swirling-stripes-text-snippet.js ./demo/snippets/text-snippet-helper.js ./demo/snippets/word-highlighter-snippet.js ./demo/snippets/worley-text-gradient-snippet.js

- §

  # Demo Snippets 001

  Scrawl-canvas DOM element snippets

  Related files:

  - DOM element snippets - main module
  - Spotlight text snippet
  - Jazzy button snippet
  - Page performance snippet

  ### Snippet definitions

  Snippet definitions are functions that take a DOM element and manipulate it to supply it with additional functionality, including the ability to add Scrawl-canvas displays and animations to the DOM element

  Example of how a Javascript module can import and use a snippet definition:

      import scrawl from '../relative/or/absolute/path/to/scrawl.js';
      import { mySnippet } from './relative/or/absolute/path/to/snippet/definition/file.js';

      let myElements = document.querySelectorAll('.some-class');
      myElements.forEach(el => mySnippet(el));

  Snippet definition functions can be written in any way the developer sees fit - a developer could write a snippet definition so that it:

  - can accept additional data to help further personalize how the snippet gets built
  - visits remote APIs to gather additional data as part of the snippet build
  - holds local state for the snippet
  - supplies a return object, class instance or function containing handles to the objects built by the definition, or functions for manipulating the Scrawl-canvas assets, artefacts, styles, animation(s) and/or canvas built by the definition (a ‘mini-API’ for each snippet)
  - etc…

  At a minimum, a snippet definition function will need to take a DOM element (or a pointer to it) as an argument. Note that Scrawl-canvas will manipulate the element in the following ways to make it work as a snippet:

  - the element’s CSS ‘position’ value, if set to ‘static’ (the default value), will change to either ‘relative’ or ‘absolute’ - this is required to get any added canvas to stick to its element in the final display
  - it will also be given a unique Scrawl-canvas identifier in a new data-scrawl-name attribute on the element
  - the new <canvas> element will be added to the element as its first child; the canvas will be absolutely positioned within the element
  - Scrawl-canvas will also add a hidden text-hold <div> element immediately after the canvas element - this is where Scrawl-canvas keeps dynamic text (for assistive technology)
  - by default, the canvas is built so that it displays beneath the element, using a lower z-index CSS property on the canvas element (compared to the host’s z-index value)
  - the new canvas’s dimensions will include the element’s padding and border as well as its content

  For the sake of fellow developers, each snippet definition function should come with some documentation to explain:

  - the purpose and usage of the snippet that the definition function will deliver/render
  - any effects (beyond those explained above) that snippetization will have on the DOM element and any child elements it may contain
  - what input the function requires, and in what format and argument order
  - what - if anything - the definition function will return

  Each of the following snippet definition functions could live in its own file; we can also bundle snippets together so that related snippets can be imported into another Javascript module using a single import statement in that file

- §

  ### ‘Spotlight text’ snippet

  Purpose: adds a spotlight effect to an element. When the user hovers the mouse over the element, a ‘spotlight’ gradient will track the mouse’s movements.

  Function input:

  - the DOM element, or a handle to it, as the first argument.
  - an optional key:value Object as the second argument

  Function output: a Javascript object will be returned, containing the following attributes

      {
          element     // the Scrawl-canvas wrapper for the DOM element supplied to the function
          canvas      // the Scrawl-canvas wrapper for the snippet's canvas
          animation   // the Scrawl-canvas animation object
          demolish    // remove the snippet from the Scrawl-canvas library
      }

  ##### Usage example:

      import spotlightText from './relative/or/absolute/path/to/this/file.js';

      let myElements = document.querySelectorAll('.some-class');

      myElements.forEach(el => spotlightText(scrawl, el));

  Effects on the element:

  - no additional effects on the DOM element
  - setting any background fill on the DOM element will hide the snippet canvas, unless it is deliberately brought forward

      export default function (scrawl, el, args = {}) {

- §

  The snippet will accept an optional key:value Object as the second argument

  - spotlightColor - default: `white`
  - backgroundColor - default: `lightgray`

          const spotlightColor = args.spotlightColor || 'white',
              backgroundColor = args.backgroundColor || 'lightgray';

- §

  Apply the snippet to the DOM element

          const snippet = scrawl.makeSnippet({

- §

  (required) The DOM element we are about to snippetize

              domElement: el,

- §

  (optional) An array of animation hook functions with the following attributes

  - `commence` - for an preparatory work required before the display cycle kicks off
  - `afterClear` - runs between the ‘clear’ and ‘compile’ stages of the display cycle
  - `afterCompile` - runs between the ‘compile’ and ‘show’ stages of the display cycle
  - `afterShow` - for any cleanup work required after the display cycle completes
  - `error` - a function to run when an error in the display cycle occurs

  For this snippet, we’ll define and add an animation hook function after the animation object has been created

              animationHooks: {},

- §

  (optional) Options we can supply for the IntersectionObserver. Defaults are usually good enough; changing the ‘threshold’ value is probably the most useful option to play with

              observerSpecs: {},

- §

  (optional - default: true) Scrawl-canvas snippets don’t have to include a canvas!

              includeCanvas: true,

- §

  (optional, and only useful if we are including a canvas) - canvas-specific options. The most useful attribute is (probably) fit, whose value can be one of: `contain`, `cover`, `fill`, or `none` (the default value)

              canvasSpecs: {},
          });

- §

  NOTE: makeSnippet() defines its own afterClear animation hook

  - the functionality is to keep the canvas properly aligned and sized with its DOM element
  - overwriting this hook here will lose that functionality!
  - instead, use the commence animation hook for all display cycle preparations

  Once the snippet is built, we can supply values to our previously defined variables

          if (snippet) {

- §

  Set some convenience variables

              const canvas = snippet.canvas,
                  animation = snippet.animation,
                  wrapper = snippet.element,
                  name = wrapper.name;

              canvas.setAsCurrentCanvas();

- §

  Define the gradient

              const spotlightGradient = scrawl.makeRadialGradient({

                  name: `${name}-gradient`,
                  startX: '50%',
                  startY: '50%',
                  endX: '50%',
                  endY: '50%',
                  endRadius: '20%',
              })
              .updateColor(0, spotlightColor)
              .updateColor(999, backgroundColor);

- §

  This animation hook uses the variables and gradient we defined above

              animation.commence = function () {

                  let active = false;

                  return function () {

                      if (canvas.here.active !== active) {

                          active = canvas.here.active;

- §

  The block entity swaps between the gradient and a color fill, dependent on user interaction

                          block.set({
                              lockTo: (active) ? 'mouse' : 'start',
                              fillStyle: (active) ? spotlightGradient : backgroundColor,
                          });
                      }
                  };
              }();

- §

  Define the block which will (sometimes) display our spotlingt gradient

              const block = scrawl.makeBlock({

                  name: `${name}-spotlight`,
                  width: '200%',
                  height: '200%',

                  startX: "50%",
                  startY: "50%",
                  handleX: "50%",
                  handleY: "50%",

                  fillStyle: backgroundColor,
                  lockFillStyleToEntity: true,

                  method: 'fill',
              });
          }

- §

  Return the snippet, so coders can access the snippet’s parts - in case they need to tweak the output to meet the web page’s specific requirements

          return snippet;
      }