ટાઈપરાઈટર ઇફેક્ટ એ કોઈ વ્યક્તિ મોટેથી વિચારતી હોય તે જોવાની ડિજિટલ સમકક્ષ છે. ટેક્સ્ટ એક પછી એક કેરેક્ટર તરીકે દેખાય છે, જાણે કે કોઈ સાચો હાથ સાચા કીઝ (keys) દબાવી રહ્યો હોય. તમે તેને પોર્ટફોલિયો સાઇટ્સના હીરો સેક્શનમાં, બ્રાઉઝર-આધારિત ટર્મિનલ એમ્યુલેટર્સમાં, અને AI આસિસ્ટન્ટ્સના ચેટ વિન્ડોમાં જોઈ શકો છો જે સાબિત કરવા માંગે છે કે તેઓ કોઈ પહેલેથી તૈયાર કરેલ ટેક્સ્ટ બ્લોક ફેચ કરવાને બદલે ખરેખર "ટાઈપ" કરી રહ્યા છે. જ્યારે તે સારી રીતે કરવામાં આવે, ત્યારે તે ઉત્તેજના પેદા કરે છે. જ્યારે તે ખરાબ રીતે કરવામાં આવે, ત્યારે તે 1987માં અટકી ગયેલા પ્રિન્ટર જેવું લાગે છે.
આ પેટર્ન શા માટે ટકી રહી છે
કમ્પ્યુટર્સ માહિતી ત્વરિત રીતે પહોંચાડે છે. માણસો નહીં. આ બંને ગતિ વચ્ચેનો તફાવત ઉપયોગી છે. ટાઈપરાઈટર ઇફેક્ટ માનવીય ગતિનું અનુકરણ કરીને આ અંતરને પૂરે છે. લેન્ડિંગ પેજ પર, તે હેડલાઇનને શબ્દવાર એવી રીતે આકર્ષિત કરી શકે છે કે મુલાકાતીઓ માત્ર ઉપરછલ્લી નજર નાખવાને બદલે ખરેખર વેલ્યુ પ્રપોઝિશન વાંચે. ટર્મિનલ એમ્યુલેટરમાં, તે એવો ભ્રમ પેદા કરે છે કે કમાન્ડ્સ રીઅલ ટાઇમમાં એક્ઝિક્યુટ થઈ રહ્યા છે. ચેટબોટ ઇન્ટરફેસમાં, તે લય એ સંકેત આપે છે કે પ્રતિસાદ ડેટાબેઝમાંથી મેળવવાને બદલે તરત જ જનરેટ કરવામાં આવી રહ્યો છે.
પરંતુ આ ઇફેક્ટ ત્યારે જ કામ કરે છે જો તેની કાર્યપદ્ધતિ યુઝરનું સન્માન કરે. સમાન અંતરાલનું સપાટ, મેટ્રોનોમિક ટિક-ટિક-ટિક રોબોટિક લાગે છે. તેનાથી પણ ખરાબ બાબત એ છે કે, જે અમલીકરણ સહાયક ટેકનોલોજી (assistive technology) ને અવગણે છે, તે એક મનોરંજક વિઝ્યુઅલ ફ્લોરિશને હતાશાજનક અવરોધમાં બદલી શકે છે. ધ્યેય યુઝરને ધીમો પાડવાનો નથી; ધ્યેય ઇન્ટરફેસને જીવંત લાગે તેટલું જ ઘર્ષણ (friction) ઉમેરવાનો છે.
તેને Recursive setTimeout સાથે બનાવો
setTimeout થી શરૂઆત કરો, અને setInterval ને અડશો નહીં. આ તફાવત દેખાય છે તેના કરતા વધુ મહત્વનો છે.
setInterval જિદ્દી છે. તે તમારા સ્ક્રિપ્ટ અથવા બ્રાઉઝરના મેઈન થ્રેડમાં બીજું શું ચાલી રહ્યું છે તેના પર ધ્યાન આપ્યા વગર દર n મિલિસેકન્ડે ફાયર થાય છે. જો તમારા લોજિકને સામાન્ય કીસ્ટ્રોક્સ વચ્ચે 50-મિલિસેકન્ડનો વિરામ અને વિરામચિહ્નો પછી 150-મિલિસેકન્ડનો વિરામ જોઈતો હોય, તો setInterval અનુકૂલન સાધી શકતું નથી. પરિણામે તમારે તેને વધારાના કંડિશનલ લોજિકમાં લપેટવું પડે છે, રેસ કંડિશન (race conditions) સાથે લડવું પડે છે, અને અંતે ઇન્ટરવલને એટલી વાર ક્લિયર અને રીસેટ કરવું પડે છે કે કોડ સ્ટેટ-મેનેજમેન્ટ માટે кошાળ બની જાય છે. ફિક્સ્ડ ઇન્ટરવલ્સ તે ક્ષણે નિષ્ફળ જાય છે જ્યારે તમારે બદલાતી ગતિની જરૂર હોય.
Recursive setTimeout દરેક સ્ટેપને તેના પછીના સ્ટેપ માટેના નિયમો નક્કી કરવા દેવાથી આ સમસ્યાનું નિરાકરણ લાવે છે. તેને એક નાની સ્ટેટ મશીન તરીકે વિચારો. તમે થોડા વેરિયેબલ્સ જાળવો છો: વર્તમાન સ્ટ્રિંગ, વર્તમાન કેરેક્ટર ઇન્ડેક્સ, તમે ટાઈપ કરી રહ્યા છો કે ડિલીટ કરી રહ્યા છો તેનો બુલિયન ફ્લેગ, અને એક textIndex કાઉન્ટર જેથી તમે બહુવિધ સ્ટ્રિંગ્સમાંથી લૂપ કરી શકો. ફંક્શન એક કેરેક્ટર ઉમેરે છે, તે વાક્યમાં ક્યાં છે તે તપાસે છે, અને પછી તેના સંદર્ભ સાથે મેળ ખાતા વિલંબ સાથે તેના પોતાના આગામી ઇન્વોકેશનનું શેડ્યૂલ કરે છે.
ઉદાહરણ તરીકે, તમે મોટાભાગના કેરેક્ટર્સ 50 મિલિસેકન્ડમાં ટાઈપ કરી શકો છો, અલ્પવિરામ પછી 150 મિલિસેકન્ડ સુધી ધીમા થઈ શકો છો, અને ડિલીટ મોડમાં બદલાતા પહેલા આખા વાક્યના અંતે 800 મિલિસેકન્ડ માટે થોભી શકો છો. તમે setInterval સાથે તે સ્પષ્ટ રીતે કરી શકતા નથી. Recursive setTimeout સાથે, લોજિક સાદું છે:
if typing:
append next character
if at end of string:
switch to pause mode
schedule next call after 1000ms
if deleting:
remove last character
if string empty:
increment textIndex
load next string
switch to typing mode
આ માળખું ક્લીનઅપને પણ અત્યંત સરળ બનાવે છે. ટાઈમઆઉટ ID સ્ટોર કરો. જ્યારે કમ્પોનન્ટ અનમાઉન્ટ થાય અથવા યુઝર બીજા પેજ પર જાય, ત્યારે એકવાર clearTimeout કોલ કરો. બેકગ્રાઉન્ડમાં ચાલતા કોઈ અનાથ (orphaned) ઇન્ટરવલ્સ નહીં રહે.
કર્સર પોતાની મેળે બ્લિંક થવું જોઈએ
બ્લિંકિંગ કર્સર એ એક વિઝ્યુઅલ વિગત છે, ડેટાની ચિંતા નથી. તેને તમારા JavaScript સ્ટેટ એન્જિનથી દૂર રાખો. ::after સ્યુડો-એલિમેન્ટ સાથે જોડાયેલ અલગ CSS એનિમેશન અથવા તમારા ટેક્સ્ટ કન્ટેનરના અંતે રહેલા સમર્પિત <span નો ઉપયોગ કરો.
એક સાદું @keyframes blink જે step-end ટાઇમિંગ સાથે opacity અથવા border-color ને ટોગલ કરે છે, તે તમને એક સ્પષ્ટ, હાર્ડવેર-ફ્રેન્ડલી પલ્સ આપે છે જે કમ્પોઝિટર પર ચાલે છે. JavaScript પાસે કર્સરની વિઝિબિલિટીનું માઇક્રોમેનેજિંગ કરવાનો કોઈ વ્યવસાય નથી. જો તમે તમારા setTimeout રિકર્ઝનમાંથી ડિસ્પ્લે પ્રોપર્ટીઝને ટોગલ કરો છો, તો તમે દરેક કેરેક્ટર પર બિનજરૂરી સ્ટાઇલ રીકેલ્ક્યુલેશન કરવા માટે મજબૂર કરો છો. એસ્થેટિક્સ (aesthetics) માટે CSS ને સંભાળવા દો. સિક્વન્સ માટે JavaScript ને સંભાળવા દો.
textIndex કાઉન્ટર સાથે બહુવિધ સ્ટ્રિંગ્સમાંથી લૂપ કરવું સરળ છે. તમારી સ્ટ્રિંગ્સને એક એરેમાં સ્ટોર કરો. જ્યારે એનિમેશન તેના ડિલીટ ફેઝને પૂર્ણ કરે અને કન્ટેનર ખાલી હોય, ત્યારે એરેની લંબાઈના મોડ્યુલો (modulo) મુજબ textIndex વધારો, કેરેક્ટર પોઇન્ટરને શૂન્ય પર રીસેટ કરો, અને ફરીથી ટાઈપ કરવાનું શરૂ કરો. આ રીતે પોર્ટફોલિયો સાઇટ્સ પેજને ફરીથી લોડ કર્યા વિના ભૂમિકાઓ—["Developer", "Designer", "Writer"]—થઈ બદલે છે.
ભૂલો જે ભ્રમને તોડી નાખે છે
એમેચ્યોર અમલીકરણોમાં ત્રણ ભૂલો વારંવાર જોવા મળે છે.
setInterval નો ઉપયોગ કરવો. અમે વેરિએબલ-સ્પીડની સમસ્યા વિશે પહેલેથી જ વાત કરી છે, પરંતુ એક સૂક્ષ્મ સમસ્યા પણ છે. જો તમારા DOM અપડેટમાં ક્યારેય વિલંબ થાય—ધારો કે, બ્રાઉઝર લેઆઉટ શિફ્ટ પેઇન્ટ કરી રહ્યું હોય—તો setInterval સતત ચાલતું રહે છે. તેના પરિણામે ઓવરલેપિંગ રાઈટ્સ, ડુપ્લીકેટ અક્ષરો, અથવા બ્રાઉઝર જેટલી ઝડપથી રેન્ડર કરી શકે તેના કરતા વધુ ઝડપી રાઈટ્સ થઈ શકે છે. રિકર્સિવ setTimeout આગલા સ્ટેપ વિશે વિચારતા પહેલા વર્તમાન સ્ટેપ પૂર્ણ થાય તેની રાહ જુએ છે.
HTML એસ્કેપ કરવાનું ભૂલી જવું. જો તમારા સોર્સ સ્ટ્રિંગ્સમાં એંગલ બ્રેકેટ્સ હોય, અને તમે એક સમયે એક અક્ષર દ્વારા innerHTML મારફતે કન્ટેન્ટ ઇન્જેક્ટ કરી રહ્યા હોવ, તો તમે ટેગ્સને અધવચ્ચેથી વિભાજિત કરી દેશો. બ્રાઉઝર પહેલા <, પછી <s, અને પછી <st જોશે. આનાથી યોગ્ય ટેગ પાર્સિંગ અટકી જાય છે અને તેનાથી બ્રોકન DOM નોડ્સ અથવા અણધારી સ્ટાઇલિંગ કેસ્કેડ્સ થઈ શકે છે. જો તમે લિટરલ અક્ષરો જોવા માંગતા હોવ, તો પહેલા તેને એસ્કેપ કરો અથવા, વધુ સારું એ છે કે innerHTML ને બદલે textContent નો ઉપયોગ કરો. જો તમારે ટાઇપરાઇટર આઉટપુટની અંદર સ્ટાઇલિશ <span> ટેગ્સની ખરેખર જરૂર હોય, તો અક્ષર લૂપ શરૂ કરતા પહેલા સ્ટ્રિંગને પ્રી-પ્રોસેસ કરો જેથી તમે જાણી શકો કે ટેગ્સ ક્યાં શરૂ થાય છે અને ક્યાં સમાપ્ત થાય છે.
એક્સેસિબિલિટીને અવગણવી. સ્ક્રીન રીડર્સને એક સમયે એક અક્ષર વાંચવું ગમતું નથી. જેમ જેમ તમારું સ્ક્રિપ્ટ DOM માં દરેક નવો અક્ષર ઉમેરે છે, તેમ કેટલીક આસિસ્ટિવ ટેકનોલોજી આખું નોડ ફરીથી જાહેર કરે છે, જેના કારણે અપૂર્ણ શબ્દોનો અવાજ સતત આવતો રહે છે. જેઓ શ્રાવ્ય નેવિગેશન (auditory navigation) પર આધાર રાખે છે તેમના માટે આ એક кошાળ સમાન છે. આનો ઉકેલ જટિલ નથી: કન્ટેનર જે આખું, અંતિમ ટેક્સ્ટ ધરાવે છે તેમાં aria-label ઉમેરો. તમે aria-hidden="true" સાથે આનિમેટેડ એલિમેન્ટને આસિસ્ટિવ ટેકનોલોજીથી સંપૂર્ણપણે છુપાવી શકો છો અને સ્ક્રીન રીડર્સ માટે વિઝ્યુઅલી હિડન સ્ટેટિક કોપી આપી શકો છો. ગમે તે રીતે, યુઝર્સને તમારી પરફોર્મન્સ જોવાની ફરજ પાડવાને બદલે તેમને સીધું આખું વાક્ય આપો.
તમારા વર્ઝનને વધુ સારું બનાવવાની રીતો
એકવાર મુખ્ય લૂપ બરાબર કામ કરવા લાગે, પછી તમે વધારાના ફીચર્સ ઉમેરી શકો છો. પરંતુ જ્યાં સુધી પાયાની બાબતો મજબૂત ન થાય ત્યાં સુધી તેને ઉમેરવાની ઉતાવળ ન કરો.
કીસ્ટ્રોક સાઉન્ડ ઇફેક્ટ્સ. દરેક અક્ષર પર એક સૂક્ષ્મ ક્લિક સંતોષકારક હોઈ શકે છે, પરંતુ વેબપેજ પર ઓડિયો એક જોખમી બાબત છે. Web Audio API અથવા ટૂંકા બફર સાથેના હળવા Audio એલિમેન્ટનો ઉપયોગ કરો. પ્લેબેક રેટમાં થોડો ફેરફાર કરો—0.95 અને 1.05 ની વચ્ચે—જેથી સમાન ક્લિક્સ કૃત્રિમ ન લાગે. હંમેશા બ્રાઉઝરની ઓટોપ્લે પોલિસીઝનું સન્માન કરો અને મ્યૂટ ટોગલ આપો. સવારે 9 વાગ્યે ટાઇપિંગ અવાજો ઓટોપ્લે થતા પોર્ટફોલિયો પેજ કરતાં યુઝર્સને કંઈ જ ઝડપથી દૂર નથી કરી શકતું.
મલ્ટી-લાઇન ટાઇપિંગ. અસલી ટર્મિનલ વિન્ડોઝમાં લાઇન વ્રેપ થાય છે. જો તમારું ટેક્સ્ટ લાઇન બ્રેક કરે છે, તો તમારો લેઆઉટ જો અનુમાનિત ન હોય તો સાદો border-right કર્સર વિચિત્ર રીતે જમ્પ કરશે. ન્યૂલાઇન કેરેક્ટર્સ દ્વારા સ્ટ્રિંગ્સને વિભાજિત કરો અને દરેક લાઇનને તેના પોતાના <span માં રેન્ડર કરો, અથવા પોઝિશન કરેલા સ્યુડો-એલિમેન્ટનો ઉપયોગ કરો જે કન્ટેન્ટના અંતને ટ્રેક કરે છે. ટેક્સ્ટ વ્રેપિંગ બાબતે સાવધ રહો; ઇનલાઇન બોર્ડર તરીકે અમલમાં મુકાયેલ કર્સર ટેક્સ્ટથી અલગ પડી શકે છે જો કન્ટેનરની પહોળાઈ બદલાય. ટર્મિનલ સ્ટાઇલ માટે white-space: pre-wrap અને મોનોસ્પેસ્ડ ફોન્ટનો ઉપયોગ કરવાનું વિચારો, કારણ કે ફિક્સ્ડ-વિડ્થ અક્ષરો કર્સર ગણતરીને વધુ અનુમાનિત બનાવે છે.
રિયલ-ટાઇમ Markdown રેન્ડરિંગ. અહીં વસ્તુઓ જટિલ બને છે. જો તમે **bold** ટાઇપ કરો છો, તો તમારી પાસે બે વિકલ્પ છે: એસ્ટરિસ્કને તે દેખાય છે તેમ લિટરલ રીતે રેન્ડર કરો, અથવા તેને તરત જ બોલ્ડ સ્ટાઇલમાં રૂપાંતરિત કરો. જો તમે બીજો વિકલ્પ પસંદ કરો છો, તો પ્રક્રિયા દરમિયાન textContent થી innerHTML પર સ્વિચ કરવાનો અર્થ એ છે કે તમારા ટેક્સ્ટ નોડની સીમાઓ બદલાઈ જાય છે. કર્સર પોઝિશન એક હેડએક બની જાય છે કારણ કે HTML ટેગ્સ તમારી નીચેના DOM ટ્રીને ખસેડે છે. એક સુરક્ષિત અભિગમ એ છે કે સામાન્ય રીતે રૉ (raw) Markdown સ્ટ્રિંગ ટાઇપ કરો, અને પછી જ્યારે આખી સ્ટ્રિંગ સ્ક્રીન પર આવી જાય ત્યારે રેન્ડર પાસ ટ્રિગર કરો. જો તમારે ખરેખર લાઈવ ફોર્મેટિંગની જરૂર હોય, તો બે લેયર જાળવો: એક હિડન ટાઇપ્ડ બફર અને એક પાર્સ કરેલ વિઝ્યુઅલ ઓવરલે.
રિવર્સ ઇફેક્ટ્સ. ટેક્સ્ટ ડિલીટ કરવાનો અર્થ એક સમયે એક અક્ષર બેકસ્પેસ કરવો એવો નથી. તમે "select all, then delete" રિસેટ કરી શકો છો જે આગલી સ્ટ્રિંગ ટાઇપ થાય તે પહેલાં ફિલ્ડને તરત જ સાફ કરી દે છે. તે યાંત્રિક લાગે છે. વૈકલ્પિક રીતે, પ્રતિ અક્ષર 30 મિલિસેકન્ડના ધીમા બેકસ્પેસિંગથી ઉત્તેજના વધે છે. બંનેનું મિશ્રણ કરો: ટાઇપો (typo) ને ઝડપથી બેકસ્પેસ કરો, થોભો, અને પછી સામાન્ય ઝડપે ડિલીટ કરવાનું શરૂ કરો. આ વિવિધતા ઇફેક્ટને વધુ કુદરતી બનાવે છે.
મુખ્ય વાત (The Real Takeaway)
ટાઇપરાઇટર ઇફેક્ટ એ એવા UI ફ્લોરિશમાંનું એક છે જે ઉપરથી સામાન્ય લાગે છે અને તમે તેને બનાવ્યા પછી જ તેની જટિલતા પ્રગટ કરે છે. શરૂઆત કરો
