- 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 027

  Video control and manipulation; chroma-based hit zone

- §

  Run code

      import * as scrawl from '../source/scrawl.js'

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

- §

  #### Scene setup

  Get a handle to the Canvas wrapper

      const canvas = scrawl.library.canvas.mycanvas;

- §

  Namespacing boilerplate

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

- §

  Importing the video file programmatically

      const myvideo = scrawl.makePicture({

          name: name('test-video'),

          videoSource: 'img/swans.mp4',

          width: '100%',
          height: '100%',

          copyWidth: '100%',
          copyHeight: '100%',
      });

      const initialVideoStart = scrawl.addListener('up', () => {

          myvideo.set({

              video_muted: true,
              video_loop: true,
          });

- §

  Get rid of the event listener after invocation - it’s a one-time-only action

          initialVideoStart();

      }, canvas.domElement);

- §

  canvas-based buttons

      scrawl.makePhrase({

          name: name('test-button-play-pause'),
          order: 2,

          text: 'PLAY',

          family: 'sans-serif',
          size: '2rem',

          startX: '75%',
          handleX: 'center',
          startY: '90%',

          letterSpacing: 2,
          underlinePosition: 0.75,

          fillStyle: 'yellow',

          underlineStyle: 'yellow',

          onEnter: function () {

              canvas.set({
                  css: {
                      cursor: 'pointer',
                  }
              });

- §

  ‘§UNDERLINE§’ is a section class marker which makes subsequent letters underlined Note: - dynamic underlining is currently not triggering in Firefox browser @ts-expect-error

              this.set({
                  text: `§UNDERLINE§${this.text}`,
              });
          },

          onLeave: function () {

              canvas.set({
                  css: {
                      cursor: 'auto',
                  }
              });

- §

  @ts-expect-error

              this.set({
                  text: this.text.replace('§UNDERLINE§', ''),
              });
          },

          onUp: function () {

              if (myvideo.get('video_paused')) {

- §

  @ts-expect-error

                  this.set({
                      text: 'PAUSE',
                  });

                  myvideo.videoPlay();
              }
              else {

- §

  @ts-expect-error

                  this.set({
                      text: 'PLAY',
                  });

                  myvideo.videoPause();
              }
          },

      }).clone({

          name: name('test-button-listen-mute'),

          text: 'LISTEN',

          startX: '25%',

          onUp: function () {

              if (myvideo.get('video_muted')) {

- §

  @ts-expect-error

                  this.set({
                      text: 'MUTE',
                  });

                  myvideo.set({
                      video_muted: false,
                  });
              }
              else {

- §

  @ts-expect-error

                  this.set({
                      text: 'LISTEN',
                  });

                  myvideo.set({
                      video_muted: true,
                  });
              }
          },
      });

- §

  Turn the swans pink

      scrawl.makeFilter({

          name: name('swan-mask'),

          actions: [
              {
                  action: 'threshold',
                  level: 200,
                  low: [0, 0, 0],
                  high: [255, 0, 0],
              },
              {
                  action: 'channels-to-alpha',
                  includeGreen: false,
                  includeBlue: false,
              },
          ],
      });

      scrawl.makePicture({

          name: name('test-swan-image'),

          asset: 'swans',

          width: '100%',
          height: '55%',

          startY: '25%',

          copyWidth: '100%',
          copyHeight: '55%',

          copyStartY: '25%',

          filters: [name('swan-mask')],

          globalAlpha: 0.01,

          onEnter: function () {

- §

  @ts-expect-error

              this.set({
                  globalAlpha: 0.1,
              });

              canvas.set({
                  css: {
                      cursor: 'pointer',
                  }
              });
          },

          onLeave: function () {

- §

  @ts-expect-error

              this.set({
                  globalAlpha: 0.01,
              });

              canvas.set({
                  css: {
                      cursor: 'auto',
                  }
              });
          },

          onUp: function () {

- §

  @ts-expect-error

              this.clickAnchor();
          },

          anchor: {
              name: name('wikipedia-swan-link'),
              href: 'https://en.wikipedia.org/wiki/Swan',
              description: 'Link to the Wikipedia article on swans',

              focusAction: true,
              blurAction: true,
          },

          checkHitIgnoreTransparency: true,
      });

- §

  Ticker

      const myticker = scrawl.makeTicker({

          name: name('test-video-ticker'),
          duration: '22.55s',
          cycles: 0,
      });

      const myLocalTweenFactory = function (name, ticker, target, data) {

          for (let i = 0, iz = data.length; i < iz; i++) {

              const [start, duration, x0, y0, x1, y1] = data[i];

              scrawl.makeTween({

                  name: `${name}-${i}`,

                  ticker: ticker,

                  targets: [target],

                  time: start,
                  duration: duration,

                  definitions: [
                      {
                          attribute: 'startX',
                          start: x0,
                          end: x1,
                      },
                      {
                          attribute: 'startY',
                          start: y0,
                          end: y1,
                      },
                  ],
              });
          }
      };

- §

  Goose 1

      const mygoose = scrawl.makeBlock({

          name: name('test-goose1-hitzone'),
          order: 1,

          width: '15%',
          height: '15%',

          handleX: 'center',
          handleY: 'center',

          lineWidth: 2,
          strokeStyle: 'yellow',

          method: 'none',

          onEnter: function () {

              canvas.set({
                  css: {
                      cursor: 'pointer',
                  }
              });

- §

  @ts-expect-error

              this.set({
                  method: 'draw',
              });
          },

          onLeave: function () {

              canvas.set({
                  css: {
                      cursor: 'auto',
                  }
              });

- §

  @ts-expect-error

              this.set({
                  method: 'none',
              });
          },

          onUp: function () {

- §

  @ts-expect-error

              this.clickAnchor();
          },

          anchor: {
              name: name('wikipedia-goose-link'),
              href: 'https://en.wikipedia.org/wiki/Goose',
              description: 'Link to the Wikipedia article on geese',

              focusAction: true,
              blurAction: true,
          },
      });

      myLocalTweenFactory(
          name('test-goose1-tween'),
          name('test-video-ticker'),
          name('test-goose1-hitzone'),
          [
              [0, '3s', '27%', '73%', '12%', '66%'],
              ['3s', '3s', '12%', '66%', '-3%', '68%']
          ],
      );

      scrawl.makeAction({

          name: name('test-goose1-action-show'),

          ticker: name('test-video-ticker'),

          time: 0,

          targets: [name('test-goose1-hitzone')],

          action: function () {

              this.targets[0].set({

                  visibility: true,
              });
          },

      }).clone({

          name: name('test-goose1-action-hide'),
          time: '6s',

          action: function () {

              this.targets[0].set({

                  visibility: false,
              });
          },
      });

- §

  Goose 2

      mygoose.clone({

          name: name('test-goose2-hitzone'),

          width: '22%',
          height: '16%',

          onUp: function () {

              mygoose.clickAnchor();
          },

          anchor: null,
      });

      myLocalTweenFactory(
          name('test-goose2-tween'),
          name('test-video-ticker'),
          name('test-goose2-hitzone'),
          [
              [0,       '4s',   '89%', '89%', '77%', '80%'],
              ['4s',    '4s',   '77%', '80%', '65%', '80%'],
              ['8s',    '2.5s', '65%', '80%', '63%', '74%'],
              ['10.5s', '6s',   '63%', '74%', '43%', '68%'],
              ['16.5s', '3s',   '43%', '68%', '33%', '66%'],
              ['19.5s', '3s',   '33%', '66%', '31%', '64%'],
          ],
      );

      scrawl.addListener('move', () => canvas.cascadeEventAction('move'), canvas.domElement);
      scrawl.addNativeListener(['touchstart', 'touchmove'], () => canvas.cascadeEventAction('move'), canvas.domElement);
      scrawl.addNativeListener(['click', 'touchend'], () => canvas.cascadeEventAction('up'), canvas.domElement);

- §

  Video time bar

      const vtBackground = scrawl.makeBlock({

          name: name('test-video-time-background'),

          width: '100%',
          height: 10,

          fillStyle: 'white',
      });

      const vtTime = vtBackground.clone({

          name: name('test-video-time-bar'),

          width: 0,
          fillStyle: 'red',
      })

      const vtPhrase = scrawl.makePhrase({

          name: name('test-video-time-phrase'),

          family: 'monospace',
          size: '1em',
          weight: 700,

          startX: '1%',
          startY: '4%',
          width: '40%',

          fillStyle: 'yellow',
      });

      const videoTimeBar = function () {

          let currentVideoTime,
              videoDuration;

          return function () {

              currentVideoTime = myvideo.get('video_currentTime');

              if (!videoDuration) videoDuration = myvideo.get('video_duration');

              if (videoDuration) {

                  vtTime.set({

                      width: `${(currentVideoTime * 100) / videoDuration}%`,
                  });

                  vtPhrase.set({

                      text: ` ${currentVideoTime.toFixed(2)} / ${videoDuration.toFixed(2)}`,
                  });

                  myticker.seekTo(currentVideoTime * 1000, true);
              }
          };
      }();

- §

  #### Scene animation

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

      const report = reportSpeed('#reportmessage');

- §

  Create the Animation loop which will run the Display cycle

      scrawl.makeRender({
          name: name('animation'),
          target: canvas,

          commence: videoTimeBar,
          afterShow: report,
      });

- §

  #### Development and testing

      console.log(scrawl.library);