From 97535b3953e5c20a695f3cc7f26d94eb5bee410d Mon Sep 17 00:00:00 2001 From: travisryan Date: Thu, 1 Jun 2023 10:55:50 -0400 Subject: [PATCH 1/2] Added dirty way of setting what the result should be AFTER the spinning starts. --- examples/index.html | 11 ++++- src/bounty.js | 104 ++++++++++++++++++++++++++++++++------------ src/transition.js | 20 ++++++++- 3 files changed, 104 insertions(+), 31 deletions(-) diff --git a/examples/index.html b/examples/index.html index fa328fe..c03873c 100644 --- a/examples/index.html +++ b/examples/index.html @@ -31,9 +31,16 @@
- +
click here
+
+ + diff --git a/src/bounty.js b/src/bounty.js index 8151156..7f5bcd1 100644 --- a/src/bounty.js +++ b/src/bounty.js @@ -2,11 +2,23 @@ import loop from "./loop"; import { select, append, attr, style, text } from "./selection"; import transition from "./transition"; -const DIGITS_COUNT = 10; + const ROTATIONS = 3; +var ALL_CHARS = "";//"0123456789ABCDEFGHIJKLMNOPRSTUVWXYZabcdefghijklmnoprstuvwxyz."; + +for( var i = 32; i <= 126; i++ ) +{ + ALL_CHARS += String.fromCharCode( i ); +} +//include the non breaking space; +ALL_CHARS += String.fromCharCode("\u00a0"); + +//console.log(ALL_CHARS[ALL_CHARS.length-1]); +const DIGITS_COUNT = ALL_CHARS.length; const createDigitRoulette = (svg, fontSize, lineHeight, id) => { - const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + //const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 'a']; + const digits = ALL_CHARS.split(""); const roulette = svg ::append("g") ::attr("id", `digit-${id}`) @@ -81,9 +93,15 @@ const setViewBox = (svg, width, height) => { svg::attr("viewBox", `0 0 ${width} ${height}`); svg::style("overflow", "hidden"); }; - +const pad = (str, length, char = ALL_CHARS[ALL_CHARS.length-1]) => + str.padStart((str.length + length) / 2, char).padEnd(length, char); const main = (initialOptions) => { - const { + //console.log(initialOptions); + if(initialOptions.continuousRun == true) + { + initialOptions.duration = 20000; + } + var { el, value, initialValue = null, @@ -92,7 +110,9 @@ const main = (initialOptions) => { animationDelay = 100, letterAnimationDelay = 100, duration = 3000, + continuousRun = false, } = initialOptions; + const element = select(el); const computedStyle = window.getComputedStyle(element); const fontSize = parseInt(computedStyle.fontSize, 10); @@ -111,56 +131,69 @@ const main = (initialOptions) => { createMask(defs, salt); const prepareValues = (value, secondValue) => { - const values = String(value).replace(/ /g, "\u00a0").split(""); + + const values = String(value).replace(/ /g, ALL_CHARS[ALL_CHARS.length-1]).split(""); - const digitIndex = String(value).search(/\d/); + //const digitIndex = String(value).search(/\d/); while (secondValue.length > values.length) { const char = - secondValue[secondValue.length - values.length - 1 + digitIndex]; - values.splice(digitIndex, 0, isNaN(parseInt(char, 10)) ? char : "0"); + secondValue[secondValue.length - values.length - 1]; + //console.log(char); + //console.log(values); + values.splice(0, 0, char); } return values; }; - - const initialString = String(initialValue || "0"); - const values = prepareValues(String(value), initialString); - const initial = prepareValues(initialString, String(value)); + let initValue = initialValue || ""; + let Value = value; + if(initValue.length > Value.length) + { + //Value = Value.padStart(initValue.length/2," "); + Value = pad(Value, initValue.length," "); + } + else if(Value.length > initValue.length) + { + initValue = pad(initValue,Value.length, " "); + } + const initialString = String(initValue || ""); + const values = prepareValues(String(Value), initialString); + //console.log("values:" + JSON.stringify(values)); + const initial = prepareValues(initialString, String(Value)); + //console.log("initial:" + JSON.stringify(initial)); const chars = values.map((char, i) => { + //console.log("char: " + char); + //console.log("i: " + i); + const id = `${i}-${salt}`; - if (isNaN(parseInt(char, 10)) || isNaN(parseInt(initial[i], 10))) { - return { - isDigit: false, - node: createCharacter(svg, char, fontSize), - value: char, - offset: { x: 0, y: offset }, - }; - } else { + return { isDigit: true, id: id, node: createDigitRoulette(svg, fontSize, lineHeight, id), filter: createFilter(defs, id), - value: Number(char), - initial: Number(initial[i]), + value: char, + initial: initial[i], offset: { x: 0, - y: offset + Number(initial[i]) * (fontSize * lineHeight), + y: offset + Number(ALL_CHARS.indexOf(initial[i])) * (fontSize * lineHeight), }, }; - } + }); - + console.log(JSON.stringify(chars)); + const transitions = []; const digits = chars.filter((char) => char.isDigit); digits.forEach((digit, i) => { - const sourceDistance = digit.initial * (fontSize * lineHeight); + const sourceDistance = ALL_CHARS.indexOf(digit.initial) * (fontSize * lineHeight); const targetDistance = - (ROTATIONS * DIGITS_COUNT + digit.value) * (fontSize * lineHeight); + (ROTATIONS * DIGITS_COUNT + ALL_CHARS.indexOf(digit.value)) * (fontSize * lineHeight); const digitTransition = transition({ from: sourceDistance, to: targetDistance, duration: duration, + continuousRun: true, delay: (digits.length - 1 - i) * letterAnimationDelay + animationDelay, step(value) { digit.offset.y = @@ -234,7 +267,22 @@ const main = (initialOptions) => { main({ ...initialOptions, ...options }); }; - return { cancel, pause, resume, restart }; + const setTo = (toValue) => { + //duration = 3000; + //cancel(); + restart({el, + value: toValue, + initialValue: pad("", 12), + //lineHeight = 1.35, + //letterSpacing = 1, + animationDelay: -3000, + letterAnimationDelay: 0, + duration: 4000, + continuousRun: false,}) + transitions.forEach((transition) => transition.startFinish()); + } + + return { cancel, pause, resume, restart, setTo }; }; export default main; diff --git a/src/transition.js b/src/transition.js index b259580..c13d754 100644 --- a/src/transition.js +++ b/src/transition.js @@ -6,6 +6,7 @@ export default ({ to, duration = 3000, delay = 0, + continuousRun = false, easing = cubicInOut, start = (v) => v, step = (v) => v, @@ -16,6 +17,8 @@ export default ({ let paused = false; let prevTime = 0; let finished = false; + let finishNow = false; + const update = (timestamp) => { if (finished) { return; @@ -25,6 +28,11 @@ export default ({ prevTime = timestamp; start(value); } + if(continuousRun && finishNow){ + + duration = timestamp + 3000; + continuousRun = false; + } if (paused) { startTime += timestamp - prevTime; @@ -33,6 +41,8 @@ export default ({ const t = Math.min(Math.max(timestamp - startTime - delay, 0), duration) / duration; value = easing(t) * (to - from) + from; + //console.log("value in transition: " + value + " : " + to + " : " + from + " : " + t); + //console.log("duration: " + duration); step(value); if (t === 1) { finished = true; @@ -48,6 +58,14 @@ export default ({ const resume = () => { paused = false; }; + const startFinish = () => { + //console.log("to before: " + to + " :duration: " + duration); + //to = toValue; + finishNow = true; + //startTime = 0; + //console.log("to after: " + to + " :duration: " + duration); + + }; - return { update, pause, resume }; + return { update, pause, resume, startFinish }; }; From 0d39cba04fa79784522224ac2f19b73804757aa0 Mon Sep 17 00:00:00 2001 From: travisryan Date: Fri, 2 Jun 2023 12:27:13 -0400 Subject: [PATCH 2/2] Added noBlur option on load. Defaults to using Blur. This can be used to minimize the processing by non-hardware accelerated browsers such as Safari and iOS --- src/bounty.js | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/bounty.js b/src/bounty.js index 7f5bcd1..58a602d 100644 --- a/src/bounty.js +++ b/src/bounty.js @@ -16,13 +16,14 @@ ALL_CHARS += String.fromCharCode("\u00a0"); //console.log(ALL_CHARS[ALL_CHARS.length-1]); const DIGITS_COUNT = ALL_CHARS.length; -const createDigitRoulette = (svg, fontSize, lineHeight, id) => { +const createDigitRoulette = (svg, fontSize, lineHeight, id, noBlur) => { //const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 'a']; const digits = ALL_CHARS.split(""); const roulette = svg ::append("g") ::attr("id", `digit-${id}`) - ::style("filter", `url(#motionFilter-${id})`); + if(!noBlur) + roulette::style("filter", `url(#motionFilter-${id})`); digits.forEach((el, i) => { roulette @@ -111,6 +112,7 @@ const main = (initialOptions) => { letterAnimationDelay = 100, duration = 3000, continuousRun = false, + noBlur = false, } = initialOptions; const element = select(el); @@ -138,8 +140,6 @@ const main = (initialOptions) => { while (secondValue.length > values.length) { const char = secondValue[secondValue.length - values.length - 1]; - //console.log(char); - //console.log(values); values.splice(0, 0, char); } return values; @@ -148,7 +148,6 @@ const main = (initialOptions) => { let Value = value; if(initValue.length > Value.length) { - //Value = Value.padStart(initValue.length/2," "); Value = pad(Value, initValue.length," "); } else if(Value.length > initValue.length) @@ -157,20 +156,17 @@ const main = (initialOptions) => { } const initialString = String(initValue || ""); const values = prepareValues(String(Value), initialString); - //console.log("values:" + JSON.stringify(values)); const initial = prepareValues(initialString, String(Value)); - //console.log("initial:" + JSON.stringify(initial)); - + const chars = values.map((char, i) => { - //console.log("char: " + char); - //console.log("i: " + i); const id = `${i}-${salt}`; - + if(!noBlur) + { return { isDigit: true, id: id, - node: createDigitRoulette(svg, fontSize, lineHeight, id), + node: createDigitRoulette(svg, fontSize, lineHeight, id, noBlur), filter: createFilter(defs, id), value: char, initial: initial[i], @@ -179,6 +175,22 @@ const main = (initialOptions) => { y: offset + Number(ALL_CHARS.indexOf(initial[i])) * (fontSize * lineHeight), }, }; + } + else { + return { + isDigit: true, + id: id, + node: createDigitRoulette(svg, fontSize, lineHeight, id, noBlur), + //filter: createFilter(defs, id), + value: char, + initial: initial[i], + offset: { + x: 0, + y: offset + Number(ALL_CHARS.indexOf(initial[i])) * (fontSize * lineHeight), + }, + }; + } + }); console.log(JSON.stringify(chars)); @@ -209,7 +221,8 @@ const main = (initialOptions) => { sourceDistance ) / 100 ).toFixed(1); - digit.filter::attr("stdDeviation", `0 ${motionValue}`); + if(!noBlur) + digit.filter::attr("stdDeviation", `0 ${motionValue}`); }, end: i === 0