import { getSnippetData } from './text-snippet-helper.js';Editable header text colorizer and animation effect snippets
Related files:
Purpose: Displays text with an animation of rising bubbles over the text fill
Function input:
Customisation: The snippet can be customised using the following data- attributes applied using CSS variables, or directly to the HTML header element:
data-text-color - any CSS color stringdata-dark-text-color - any CSS color stringdata-outline-color - any CSS color stringdata-dark-outline-color - any CSS color stringdata-outline-width - (unit % of font size) percentage of the font size for text outline widthdata-bubble-color - any CSS color stringdata-dark-bubble-color - any CSS color stringdata-bubble-outline-color - any CSS color stringdata-dark-bubble-outline-color - any CSS color stringdata-bubble-density - the number of bubbles to generatedata-contrast-color - any CSS color string, used when user has set prefers-contrast: moredata-dark-contrast-color - any CSS color string, used when user has set prefers-contrast: moreFunction 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
}
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:
transparenttransparentexport 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, yOffset, fontSize, lineHeight, initCanvas, initPhrase, textGroup, eternalTweens, responsiveFunctions, contrastMoreActions, contrastOtherActions, colorSchemeDarkActions, colorSchemeLightActions, additionalDemolishActions } = getSnippetData(snippet, scrawl);Initialise the canvas
initCanvas();Initialize and collect developer-supplied data
let textColor = '#c213bc',
darkTextColor = '#fcdeef',
outlineColor = '#f59dcf',
darkOutlineColor = '#f59dcf',
outlineWidth = 0.05,
bubbleColor = '#fcdeef',
darkBubbleColor = '#ed5fb0',
bubbleOutlineColor = '#c213bc',
darkBubbleOutlineColor = '#c213bc',
bubbleDensity = 50,
contrastColor = 'black',
darkContrastColor = 'white';
if (dataset.textColor) textColor = dataset.textColor;
else {
const s = compStyles.getPropertyValue('--data-text-color');
if (s) textColor = s;
}
if (dataset.darkTextColor) darkTextColor = dataset.darkTextColor;
else {
const s = compStyles.getPropertyValue('--data-dark-text-color');
if (s) darkTextColor = 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.bubbleColor) bubbleColor = dataset.bubbleColor;
else {
const s = compStyles.getPropertyValue('--data-bubble-color');
if (s) bubbleColor = s;
}
if (dataset.darkBubbleColor) darkBubbleColor = dataset.darkBubbleColor;
else {
const s = compStyles.getPropertyValue('--data-dark-bubble-color');
if (s) darkBubbleColor = s;
}
if (dataset.bubbleOutlineColor) bubbleOutlineColor = dataset.bubbleOutlineColor;
else {
const s = compStyles.getPropertyValue('--data-bubble-outline-color');
if (s) bubbleOutlineColor = s;
}
if (dataset.darkBubbleOutlineColor) darkBubbleOutlineColor = dataset.darkBubbleOutlineColor;
else {
const s = compStyles.getPropertyValue('--data-dark-bubble-outline-color');
if (s) darkBubbleOutlineColor = s;
}
if (dataset.bubbleDensity) bubbleDensity = parseFloat(dataset.bubbleDensity);
else {
const s = compStyles.getPropertyValue('--data-bubble-density');
if (s) bubbleDensity = 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 bubblesGroup = scrawl.makeGroup({
name: `${name}-bubbles-group`,
});
const fizz = scrawl.makeWheel({
name: `${name}-bubbles-template`,
group,
order: 1,
startY: '100%',
handleX: 'center',
handleY: 'center',
fillStyle: bubbleColor,
strokeStyle: bubbleOutlineColor,
method: 'fillThenDraw',
globalCompositeOperation: 'source-atop',
noDeltaUpdates: true,
noPositionDependencies: true,
noFilters: true,
noUserInteraction: true,
purge: 'all',
});
bubblesGroup.addArtefacts(fizz);
for (let i = 0; i < bubbleDensity; i++) {
const bubble = fizz.clone({
name: `${name}-bubble-${i}`,
radius: Math.round((Math.random() * (fontSize / 2)) + 4),
startX: `${Math.random() * 100}%`,
noCanvasEngineUpdates: true,
sharedState: true,
});
bubblesGroup.addArtefacts(bubble);
const myRandom = Math.random();
eternalTweens.push(scrawl.makeTween({
name: bubble.name,
targets: bubble,
duration: Math.round((myRandom * 3000) + 5000),
cycles: 0,
definitions: [{
attribute: 'startY',
start: '100%',
end: '0%',
}, {
attribute: 'scale',
start: 0.3,
end: Math.round((1 - myRandom) * 0.9) + 0.6,
}],
}).run());
}
const textFill = scrawl.makePhrase({
name: `${name}-text-stencil`,
group,
fillStyle: textColor,
underlineStyle: 'rgba(0 0 0 / 0)',
method: 'fill',
order: 0,
});
initPhrase(textFill);
const textStroke = textFill.clone({
name: `${name}-text-outline`,
order: 2,
strokeStyle: outlineColor,
lineWidth: outlineWidth * fontSize,
underlineStyle: outlineColor,
method: 'draw',
});
textGroup.addArtefacts(textFill, textStroke);Accessibility
colorSchemeLightActions.push(() => {
fizz.set({
fillStyle: bubbleColor,
strokeStyle: bubbleOutlineColor,
});
textFill.set({
fillStyle: textColor,
});
textStroke.set({
strokeStyle: outlineColor,
underlineStyle: outlineColor,
});
});
colorSchemeDarkActions.push(() => {
fizz.set({
fillStyle: darkBubbleColor,
strokeStyle: darkBubbleOutlineColor,
});
textFill.set({
fillStyle: darkTextColor,
});
textStroke.set({
strokeStyle: darkOutlineColor,
underlineStyle: 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 localFontSize = parseFloat(items.fontSize),
localRadius = localFontSize / 2;
textStroke.set({
lineWidth: outlineWidth * localFontSize,
});
bubblesGroup.setArtefacts({
radius: Math.round((Math.random() * localRadius) + 4),
});
});Cleanup
additionalDemolishActions.push(() => {
bubblesGroup.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;
};