• Jump To … +
    ./demo/modules/canvas-minimap.js ./demo/modules/canvas-scene-editor.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-graphic.js ./demo/modules/london-crime-lines.js ./demo/modules/london-crime-stacked-bars.js ./demo/modules/lottie-loader.js ./demo/modules/simple-chart-frame-tests.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 006

    Editable header text colorizer and animation effect snippets

    Related files:

    • Editable header text colorizer and animation effect snippets
    • Text snippet helper

    ‘Two-color Risograph effect used to color text’ snippet

    Purpose: This effect is inspired by Risograph printing which uses a limited color palette, stippling colors to create a gradient effect.

    • This snippet supports dark-mode alternative colors
    • This snippet supports high contrast alternative colors
    • This snippet is not animated

    Function input:

    • the DOM element - generally a block or inline-block element.

    Customisation: The snippet can be customised using the following data- attributes applied using CSS variables, or directly to the HTML header element:

    • data-top-color - any CSS color string
    • data-dark-top-color - any CSS color string
    • data-bottom-color - any CSS color string
    • data-dark-bottom-color - any CSS color string
    • data-outline-color - any CSS color string
    • data-dark-outline-color - any CSS color string
    • data-outline-width - (unit % of font size) outline width as a percentage of the font size
    • data-random-radius - (0 - 1) the amount of mixing of the top and bottom colors
    • data-random-level - (0 - 1) the density of the color mixing
    • data-contrast-color - any CSS color string, used when user has set prefers-contrast: more
    • data-dark-contrast-color - any CSS color string, used when user has set prefers-contrast: more

    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 * as scrawl from 'path/to/scrawl-canvas/library';
    
    import mySnippet from './relative/or/absolute/path/to/this/file.js';
    let myElements = document.querySelectorAll('.some-class');
    myElements.forEach(el => mySnippet(el, scrawl));
    
  • §

    Additional font-specific customisation can be added courtesy of the Text Snippet Helper module

    import { getSnippetData } from './text-snippet-helper.js';
  • §

    Effects on the element:

    • Imports the element’s background color, and sets the element background to transparent
    • Imports the element’s text node text, and sets the text color to transparent
    • Note that canvas text will NEVER be as good as DOM text!
    export default function (el, scrawl) {
  • §

    Apply the snippet to the DOM element

        let snippet = scrawl.makeSnippet({
            domElement: el,
        });
  • §

    Only proceed if the snippet is successfully generated

        if (snippet) {
  • §

    Import data and functionality from the Text Snippet Helper module

            let { canvas, group, dataset, compStyles, name, fontSize, lineHeight, initCanvas, initPhrase, textGroup, responsiveFunctions, contrastMoreActions, contrastOtherActions, colorSchemeDarkActions, colorSchemeLightActions, additionalDemolishActions } = getSnippetData(snippet, scrawl);
  • §

    Initialise the canvas

            initCanvas();
    
            canvas.base.set({
                compileOrder: 1,
            });
  • §

    Initialize and collect developer-supplied data

            let topColor = 'lightblue',
                darkTopColor = '#d7e3f5',
                bottomColor = 'blue',
                darkBottomColor = '#598ad9',
                outlineColor = 'black',
                darkOutlineColor = '#f4f5d7',
                outlineWidth = 0.03,
                randomRadius = 0.8,
                randomLevel = 1,
                contrastColor = 'black',
                darkContrastColor = 'white';
    
            if (dataset.topColor) topColor = dataset.topColor;
            else {
                const s = compStyles.getPropertyValue('--data-top-color');
                if (s) topColor = s;
            }
    
            if (dataset.darkTopColor) darkTopColor = dataset.darkTopColor;
            else {
                const s = compStyles.getPropertyValue('--data-dark-top-color');
                if (s) darkTopColor = s;
            }
    
            if (dataset.bottomColor) bottomColor = dataset.bottomColor;
            else {
                const s = compStyles.getPropertyValue('--data-bottom-color');
                if (s) bottomColor = s;
            }
    
            if (dataset.darkBottomColor) darkBottomColor = dataset.darkBottomColor;
            else {
                const s = compStyles.getPropertyValue('--data-dark-bottom-color');
                if (s) darkBottomColor = s;
            }
    
            if (dataset.outlineColor) outlineColor = dataset.outlineColor;
            else {
                const s = compStyles.getPropertyValue('--data-outline-color');
                if (s) outlineColor = s;
            }
    
            if (dataset.darkOutlineColor) darkOutlineColor = dataset.darkOutlineColor;
            else {
                const s = compStyles.getPropertyValue('--data-dark-outline-color');
                if (s) darkOutlineColor = s;
            }
    
            if (dataset.outlineWidth) outlineWidth = parseFloat(dataset.outlineWidth);
            else {
                const s = compStyles.getPropertyValue('--data-outline-width');
                if (s) outlineWidth = parseFloat(s);
            }
    
            if (dataset.randomRadius) randomRadius = parseFloat(dataset.randomRadius);
            else {
                const s = compStyles.getPropertyValue('--data-random-radius');
                if (s) randomRadius = parseFloat(s);
            }
    
            if (dataset.randomLevel) randomLevel = parseFloat(dataset.randomLevel);
            else {
                const s = compStyles.getPropertyValue('--data-random-level');
                if (s) randomLevel = parseFloat(s);
            }
    
            if (dataset.contrastColor) contrastColor = dataset.contrastColor;
            else {
                const s = compStyles.getPropertyValue('--data-contrast-color');
                if (s) contrastColor = s;
            }
    
            if (dataset.darkContrastColor) darkContrastColor = dataset.darkContrastColor;
            else {
                const s = compStyles.getPropertyValue('--data-dark-contrast-color');
                if (s) darkContrastColor = s;
            }
  • §

    Build the text effect

            const g1 = scrawl.makeGradient({
                name: `${name}-riso-gradient`,
                colors: [
                    [0, 'white'],
                    [999, 'black'],
                ],
                endY: '100%',
            });
    
            const f1 = scrawl.makeFilter({
                name: `${name}-random-filter`,
                method: 'randomNoise',
                height: Math.round(lineHeight * randomRadius),
                noWrap: true,
                level: randomLevel,
            });
    
            const f2 = scrawl.makeFilter({
                name: `${name}-threshold-filter`,
                method: 'threshold',
                level: 127,
                lowColor: bottomColor,
                highColor: topColor,
            });
    
            const cell = canvas.buildCell({
                name: `${name}-riso-cell`,
                width: 32,
                height: lineHeight,
                cleared: false,
                compiled: false,
                shown: false,
                useAsPattern: true,
            });
    
            scrawl.makeBlock({
                name: `${name}-riso-block`,
                group: `${name}-riso-cell`,
                dimensions: ['100%', '100%'],
                fillStyle: `${name}-riso-gradient`,
                lockFillStyleToEntity: true,
                filters: [`${name}-random-filter`, `${name}-threshold-filter`],
                memoizeFilterOutput: true,
            });
    
            cell.compile();
    
            const p1 = scrawl.makePattern({
                name: `${name}-riso-pattern`,
                asset: `${name}-riso-cell`,
                matrixF: Math.round(lineHeight / 10),
            });
    
            const textFill = scrawl.makePhrase({
                name: `${name}-text-stencil`,
                group,
                order: 0,
            });
    
            initPhrase(textFill);
    
            const textStroke = textFill.clone({
                name: `${name}-text-outline`,
                order: 2,
                lineWidth: outlineWidth * fontSize,
                strokeStyle: outlineColor,
                method: 'draw',
                globalCompositeOperation: 'destination-over',
            });
    
            textGroup.addArtefacts(textFill, textStroke);
    
            scrawl.makeBlock({
                name: `${name}-text-fill`,
                group,
                order: 1,
                width: '100%',
                height: '100%',
                fillStyle: `${name}-riso-pattern`,
                globalCompositeOperation: 'source-in',
            });
  • §

    Accessibility

            colorSchemeLightActions.push(() => {
                f2.set({
                    lowColor: bottomColor,
                    highColor: topColor,
                });
                cell.clear();
                cell.compile();
                textStroke.set({
                    strokeStyle: outlineColor,
                });
            });
    
            colorSchemeDarkActions.push(() => {
                f2.set({
                    lowColor: darkBottomColor,
                    highColor: darkTopColor,
                });
                cell.clear();
                cell.compile();
                textStroke.set({
                    strokeStyle: darkOutlineColor,
                });
            });
    
            contrastMoreActions.push(() => {
                el.style.color = (canvas.here.prefersDarkColorScheme) ? darkContrastColor : contrastColor;
                textGroup.setArtefacts({
                    visibility: false,
                });
            });
    
            contrastOtherActions.push(() => {
                el.style.color = 'transparent';
                textGroup.setArtefacts({
                    visibility: true,
                });
            });
  • §

    Responsiveness

            responsiveFunctions.push((items = {}) => {
    
                const localLineHeight = parseFloat(items.lineHeight),
                    localFontSize = parseFloat(items.fontSize);
    
                cell.set({
                    height: localLineHeight,
                });
                cell.clear();
                cell.compile();
    
                p1.set({
                    matrixF: Math.round(localLineHeight / 10),
                });
                
                f1.set({
                    height: Math.round(localLineHeight * randomRadius),
                });
    
                textStroke.set({
                    lineWidth: outlineWidth * localFontSize,
                });
            });
  • §

    Cleanup

            additionalDemolishActions.push(() => {
                f1.kill();
                f2.kill();
                g1.kill();
                p1.kill();
                cell.kill();
            });
        }
  • §

    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;
    };