From 93df47281c8cb1698387b5cb02cf2b3597eadaba Mon Sep 17 00:00:00 2001 From: khanh-devos Date: Wed, 23 Aug 2023 12:38:26 +0700 Subject: [PATCH] Add animation - Create a new file animate. - Keep the origin file unchanged except the browser file. - Set the format below a frame to declare the animation. @(animate:{time:1000, repeat:true, width:2000, height:100}) ( animated_item_0 ... item_n )@{className} - Without the first line and the frame ()@{className}, the app will run normally. - Width and height is properties of a parent SVG to contain the animated child svg. --- .gitignore | 2 ++ src/animate.js | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/browser.js | 34 ++++++++++++++++++++++++----- 3 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 src/animate.js diff --git a/.gitignore b/.gitignore index 74f6368..15eade8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +index.html + .bundle/ _site/ vendor/ diff --git a/src/animate.js b/src/animate.js new file mode 100644 index 0000000..f8f83ce --- /dev/null +++ b/src/animate.js @@ -0,0 +1,58 @@ +function separate (text) { + let [res, checkBracket, start, classname, animation] = [[''], true, false, '', {}]; + for (const line of text.split('\n')) { + // define animate + if (line.includes('@(animate:{')) { + const ani = line.substring(line.indexOf('{') + 1, line.indexOf('}')); + for (const item of ani.split(',')) { + animation[item.split(':')[0].trim()] = item.split(':')[1]; + } + continue; + } + + if (line.includes('(')) { + start = true; + if (start) { + if (checkBracket) { + res.push(line.replace('(','')) + checkBracket = false; + } + else res.push(line) + } + } + else if (line.includes(')@{')) { + classname = line.substring(line.indexOf('{') + 1, line.indexOf('}')) + if (start) { + checkBracket = true; + res.push(line.substr(0, line.indexOf(')@{'))) + }; + res.push('\n###'); + start = false; + } + else { + if (start) res.push(line); + } + + } + + return [res.join('\n').split('###'), classname, animation]; +} + +// delay time during animation +const delay = time => new Promise(res => setTimeout(res, time)); + +async function animation (classname, ani) { + const {time, repeat} = ani; + do { + for (const svg of document.getElementsByClassName(classname)) { + if (svg.getAttribute('width') === '0') continue; + svg.style.display = 'block'; + await delay(time); + svg.style.display = 'none'; + } + + document.querySelector(`.${classname}`).style.display = 'block'; + // console.log(document.querySelector(`.${classname}`)); + await delay(time); + } while (repeat === 'true'); +} \ No newline at end of file diff --git a/src/browser.js b/src/browser.js index b110ecd..cde931d 100644 --- a/src/browser.js +++ b/src/browser.js @@ -7,11 +7,35 @@ document.addEventListener("DOMContentLoaded", function() { continue; } //setTimeout(() => { - const source = script.innerText; - const zoom = Number(script.getAttribute("zoom") || 0.3); - const debug = script.hasAttribute("grid"); - const svg = create(source, zoom, debug); - script.parentNode.insertBefore(svg, script.nextSibling); + const source = script.innerText; + const zoom = Number(script.getAttribute("zoom") || 0.3); + const debug = script.hasAttribute("grid"); + + if (!source.includes(')@{')) { + // define there is no animation inside. + const svg = create(source, zoom, debug); + script.parentNode.insertBefore(svg, script.nextSibling); + continue; + } + + // animation starts + const [newSources, classname, ani] = separate(source); + const {width, height} = ani; + const containSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + containSvg.setAttribute("width", width); + containSvg.setAttribute("height", height); + + for (const newSource of newSources) { + const svg = create(newSource, zoom, debug); + svg.classList.add(classname) + svg.style.display = 'none'; + containSvg.appendChild(svg); + } + + script.parentNode.insertBefore(containSvg, script.nextSibling); + //}, 0); + + animation(classname, ani); //}, 0); } });