Will I need to hire a coder to create code that produces the typewriter effect, as seen in this video, or is there a similar effect already available within Wix Studio for non-coders? Anything where a word is replaced. Here’s a video clip. Ignore the mouse pointer, just the text and the cursor line are what I’d like. Typewriter-Effect - TechSmith Screencast
And if i would generate a type writer effect, maybe it would look something like —>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Matrix Typewriter Interface</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=VT323&display=swap');
:root {
--matrix-green: #00FF41;
--matrix-dark-green: #00CC33;
--matrix-black: #0A0A0A;
--matrix-light-green: #00EE00;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'VT323', monospace;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
background-color: var(--matrix-black);
color: var(--matrix-green);
position: relative;
}
/* Matrix Rain Background */
.matrix-rain {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
overflow: hidden;
z-index: -1;
}
.matrix-column {
position: absolute;
width: 15px; /* Width of each column */
display: flex;
flex-direction: column;
white-space: pre;
}
.matrix-char {
color: var(--matrix-green);
font-size: 20px;
line-height: 20px; /* Adjust line-height to prevent gaps */
opacity: 0;
animation: fadeInOut 2s linear forwards; /* Controlled by JS */
}
.matrix-char.bright {
color: var(--matrix-light-green);
}
@keyframes fadeInOut {
0% { opacity: 0; }
20% { opacity: 1; }
80% { opacity: 1; }
100% { opacity: 0; }
}
/* Terminal Container */
.terminal-container {
width: 90%;
max-width: 900px;
background: rgba(0, 0, 0, 0.8);
border: 2px solid var(--matrix-dark-green);
box-shadow: 0 0 20px var(--matrix-dark-green), inset 0 0 10px var(--matrix-dark-green);
padding: 30px;
border-radius: 10px;
position: relative;
z-index: 1;
}
.terminal-container::before {
content: '';
position: absolute;
top: -5px;
left: -5px;
right: -5px;
bottom: -5px;
border: 2px solid var(--matrix-light-green);
border-radius: 12px;
opacity: 0.3;
animation: terminalGlow 3s infinite alternate;
z-index: -1;
}
@keyframes terminalGlow {
0% { box-shadow: 0 0 10px var(--matrix-light-green); }
100% { box-shadow: 0 0 30px var(--matrix-light-green), 0 0 40px rgba(0, 255, 65, 0.5); }
}
.terminal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 25px;
padding-bottom: 15px;
border-bottom: 1px dashed var(--matrix-dark-green);
}
.terminal-title {
font-size: 1.5em;
color: var(--matrix-light-green);
text-shadow: 0 0 10px var(--matrix-light-green);
}
.terminal-status {
font-size: 1.1em;
color: var(--matrix-green);
text-shadow: 0 0 5px var(--matrix-green);
}
.text-display {
min-height: 200px;
background: rgba(0, 0, 0, 0.6);
border: 1px solid var(--matrix-dark-green);
padding: 20px;
white-space: pre-wrap;
word-wrap: break-word;
font-size: 1.2em;
line-height: 1.4;
color: var(--matrix-green);
box-shadow: inset 0 0 8px var(--matrix-dark-green);
overflow-y: auto; /* Allow scrolling for longer texts */
max-height: 400px; /* Limit height */
}
#typewriter-text {
display: inline;
}
.char.typed {
opacity: 1;
transition: opacity 0.05s ease-in;
}
.char.deleted {
opacity: 0;
transition: opacity 0.05s ease-out;
}
.cursor {
display: inline-block;
background-color: var(--matrix-light-green);
width: 8px;
height: 1.2em;
margin-left: 5px;
animation: matrixBlink 0.7s step-end infinite;
box-shadow: 0 0 10px var(--matrix-light-green);
}
@keyframes matrixBlink {
from, to { background-color: transparent; }
50% { background-color: var(--matrix-light-green); }
}
.stats-panel {
display: flex;
justify-content: space-around;
margin-top: 25px;
padding: 15px;
border-top: 1px dashed var(--matrix-dark-green);
color: var(--matrix-green);
font-size: 1em;
}
.stat-item {
text-align: center;
padding: 5px 10px;
border: 1px solid rgba(0, 255, 65, 0.3);
border-radius: 5px;
}
.stat-item span {
color: var(--matrix-light-green);
font-weight: bold;
text-shadow: 0 0 5px var(--matrix-light-green);
}
/* Controls */
.controls {
position: fixed;
bottom: 30px;
right: 30px;
display: grid;
grid-template-columns: repeat(2, 1fr); /* Two columns for buttons */
gap: 15px;
background: rgba(0, 0, 0, 0.9);
border: 2px solid var(--matrix-dark-green);
box-shadow: 0 0 15px var(--matrix-dark-green), inset 0 0 8px var(--matrix-dark-green);
padding: 20px;
border-radius: 10px;
z-index: 1000;
}
.control-btn, .control-select {
background-color: var(--matrix-dark-green);
color: var(--matrix-light-green);
border: 1px solid var(--matrix-green);
padding: 12px 18px;
font-size: 1em;
font-family: 'VT323', monospace;
cursor: pointer;
border-radius: 5px;
box-shadow: 0 0 8px rgba(0, 255, 65, 0.5);
transition: all 0.2s ease-in-out;
}
.control-btn:hover, .control-select:hover {
background-color: var(--matrix-green);
color: var(--matrix-black);
box-shadow: 0 0 15px var(--matrix-light-green);
transform: translateY(-2px);
}
.control-btn:active, .control-select:active {
transform: translateY(0);
box-shadow: inset 0 0 5px var(--matrix-light-green);
background-color: var(--matrix-light-green);
}
.control-select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
text-align: center;
padding-right: 30px; /* Space for custom arrow */
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%2300FF41'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 8px center;
background-size: 20px;
}
/* Audio Visualizer (simple) */
.audio-visualizer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg, transparent, var(--matrix-green), var(--matrix-light-green), var(--matrix-green), transparent);
opacity: 0;
animation: visualizePulse 0.15s ease-out;
border-radius: 1.5px;
}
@keyframes visualizePulse {
0% { transform: scaleX(0); opacity: 0.5; }
50% { transform: scaleX(1); opacity: 1; }
100% { transform: scaleX(0); opacity: 0.5; }
}
/* Media Queries for Responsiveness */
@media (max-width: 768px) {
.terminal-container {
padding: 20px;
}
.terminal-title {
font-size: 1.2em;
}
.terminal-status {
font-size: 1em;
}
.text-display {
font-size: 1em;
padding: 15px;
min-height: 150px;
}
.controls {
bottom: 15px;
right: 15px;
grid-template-columns: 1fr; /* Single column on smaller screens */
padding: 15px;
}
.control-btn, .control-select {
padding: 10px 15px;
}
.stats-panel {
flex-direction: column;
gap: 10px;
}
}
</style>
</head>
<body>
<div class="matrix-rain" id="matrix-rain"></div>
<div class="terminal-container">
<div class="terminal-header">
<div class="terminal-title">>>> MTRX_OS v6.0_STABLE</div>
<div class="terminal-status" id="system-status">[ STATUS: ONLINE ]</div>
</div>
<div class="text-display">
<span id="typewriter-text"></span><span class="cursor" id="cursor"></span>
</div>
<div class="stats-panel">
<div class="stat-item">CHARACTERS: <span id="char-count">0</span></div>
<div class="stat-item">WPM: <span id="wpm">0</span></div>
<div class="stat-item">PROGRESS: <span id="progress">0</span>%</div>
<div class="stat-item">OPS_COUNT: <span id="op-count">0</span></div>
</div>
<div class="audio-visualizer" id="visualizer"></div>
</div>
<div class="controls">
<button class="control-btn" data-action="pause" title="Pause">PAUSE</button>
<button class="control-btn" data-action="resume" title="Resume">RESUME</button>
<button class="control-btn" data-action="next" title="Next Line">NEXT</button>
<button class="control-btn" data-action="restart" title="Restart Session">RESTART</button>
<button class="control-btn" data-action="toggleSpeed" title="Adjust Speed">SPEED</button>
<button class="control-btn" data-action="toggleSound" title="Toggle Sound">SOUND</button>
<select class="control-select" id="theme-select" title="Switch Theme">
<option value="matrix">MATRIX</option>
<option value="data_stream">DATA STREAM</option>
<option value="glitch">GLITCH</option>
</select>
<select class="control-select" id="sound-select" title="Select Sound Type">
<option value="synth">SYNTH</option>
<option value="digital">DIGITAL</option>
<option value="binary">BINARY</option>
</select>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
class MatrixTypewriter {
constructor() {
this.textElement = document.getElementById('typewriter-text');
this.cursorElement = document.getElementById('cursor');
this.visualizer = document.getElementById('visualizer');
this.charCountElement = document.getElementById('char-count');
this.wpmElement = document.getElementById('wpm');
this.progressElement = document.getElementById('progress');
this.opCountElement = document.getElementById('op-count');
this.systemStatusElement = document.getElementById('system-status');
this.texts = [
"INITIALIZING_MATRIX_PROTOCOL_V6.0...",
"ESTABLISHING_NEURAL_INTERFACE_LINK...",
"RECALIBRATING_REALITY_SIMULATOR...",
"ACCESSING_ANOMALY_DATABASE_PHI-7...",
"EXECUTING_CODE_INJECTION_SEQUENCE...",
"DETECTING_UNAUTHORIZED_PRESENCE...",
"ALERT: AGENT_PROGRAM_DETECTED. EVASIVE_MANEUVERS_RECOMMENDED.",
"DECRYPTING_SECURE_COMMUNICATION_CHANNEL_0110100001101001...",
"SYNCHRONIZING_DATA_STREAM_WITH_EXTERNAL_NETWORK...",
"THE_CHOICE_IS_YOURS:_RED_PILL_OR_BLUE_PILL?",
"WELCOME_TO_THE_REAL_WORLD,_NEO."
];
this.currentTextIndex = 0;
this.currentCharIndex = 0;
this.isDeleting = false;
this.isPaused = false;
this.soundEnabled = true;
this.currentSoundType = 'synth';
this.operationCount = 0; // Renamed particleCount for Matrix theme
this.startTime = Date.now();
this.totalCharsProcessed = 0; // Renamed totalCharsTyped
this.timeoutId = null;
this.speeds = [
{ name: "SLOW", multiplier: 0.3 },
{ name: "STANDARD", multiplier: 1 },
{ name: "RAPID", multiplier: 2.5 },
{ name: "HYPER", multiplier: 5 }
];
this.currentSpeedIndex = 1; // Starts at "STANDARD"
this.themes = ['matrix', 'data_stream', 'glitch']; // Matrix specific themes
this.currentTheme = 'matrix';
this.config = {
baseTypingSpeed: 60,
typingVariance: 40,
baseDeletingSpeed: 20,
deletingVariance: 15,
delayBeforeDelete: 2500,
delayBeforeNext: 800,
punctuationPause: 300,
punctuationChance: 0.7,
punctuationChars: ['_', '.', ':', '!', '?'] // Matrix-style "punctuation"
};
this.setupAudioContext();
this.initMatrixRain();
this.setupEventListeners();
this.updateSpeedStatus();
this.setTheme(this.currentTheme);
this.start();
}
setupAudioContext() {
this.audioContext = null;
try {
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
const resumeAudio = () => {
if (this.audioContext && this.audioContext.state === 'suspended') {
this.audioContext.resume().then(() => {
console.log('AudioContext resumed successfully.');
document.removeEventListener('click', resumeAudio);
document.removeEventListener('keydown', resumeAudio);
});
}
};
document.addEventListener('click', resumeAudio);
document.addEventListener('keydown', resumeAudio);
} catch (e) {
console.error('Web Audio API not supported:', e);
this.soundEnabled = false;
}
// Matrix-themed sound profiles
this.soundProfiles = {
synth: [
{ freq: 440, type: 'sine', duration: 0.05, volume: 0.2 },
{ freq: 880, type: 'triangle', duration: 0.03, volume: 0.1 }
],
digital: [
{ freq: 1200, type: 'square', duration: 0.04, volume: 0.15 },
{ freq: 2400, type: 'sawtooth', duration: 0.02, volume: 0.07 }
],
binary: [ // More abrupt, clicky sound
{ freq: 2000, type: 'square', duration: 0.01, volume: 0.1 },
{ freq: 3000, type: 'sine', duration: 0.005, volume: 0.05 }
]
};
}
playSound() {
if (!this.soundEnabled || !this.audioContext || this.audioContext.state === 'suspended') {
return;
}
const profiles = this.soundProfiles[this.currentSoundType];
profiles.forEach(profile => {
const oscillator = this.audioContext.createOscillator();
const gainNode = this.audioContext.createGain();
oscillator.type = profile.type;
oscillator.frequency.setValueAtTime(profile.freq + (Math.random() - 0.5) * 20, this.audioContext.currentTime);
gainNode.gain.setValueAtTime(profile.volume, this.audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.0001, this.audioContext.currentTime + profile.duration);
oscillator.connect(gainNode);
gainNode.connect(this.audioContext.destination);
oscillator.start();
oscillator.stop(this.audioContext.currentTime + profile.duration + 0.02);
});
this.visualizer.style.animation = 'none';
void this.visualizer.offsetWidth; // Trigger reflow
this.visualizer.style.animation = 'visualizePulse 0.15s ease-out forwards';
}
setSound(soundType) {
if (this.soundProfiles[soundType]) {
this.currentSoundType = soundType;
document.getElementById('sound-select').value = soundType;
console.log(`Sound profile set to: ${soundType}`);
}
}
setTheme(theme) {
// This is where you would switch CSS classes on the body or apply styles directly
// For this Matrix design, we'll implement a simple "theme" effect
const body = document.body;
// Reset previous theme classes (if any, from an older design)
body.classList.remove('data_stream', 'glitch');
if (theme === 'matrix') {
// Already default, but ensures consistency
body.style.setProperty('--matrix-green', '#00FF41');
body.style.setProperty('--matrix-dark-green', '#00CC33');
body.style.setProperty('--matrix-light-green', '#00EE00');
body.style.setProperty('--matrix-black', '#0A0A0A');
this.systemStatusElement.textContent = "[ STATUS: ONLINE ]";
document.querySelector('.terminal-title').textContent = ">>> MTRX_OS v6.0_STABLE";
} else if (theme === 'data_stream') {
body.style.setProperty('--matrix-green', '#00FFFF'); /* Cyan */
body.style.setProperty('--matrix-dark-green', '#00AAAA');
body.style.setProperty('--matrix-light-green', '#00DDDD');
body.style.setProperty('--matrix-black', '#000020'); /* Dark Blue-ish */
this.systemStatusElement.textContent = "[ STATUS: DATAFLOW ]";
document.querySelector('.terminal-title').textContent = ">>> NEURAL_STREAM_ACTIVE";
} else if (theme === 'glitch') {
body.style.setProperty('--matrix-green', '#FF00FF'); /* Magenta */
body.style.setProperty('--matrix-dark-green', '#AA00AA');
body.style.setProperty('--matrix-light-green', '#DD00DD');
body.style.setProperty('--matrix-black', '#200020'); /* Dark Purple-ish */
// Add a subtle glitch effect class to body
body.classList.add('glitch');
this.systemStatusElement.textContent = "[ STATUS: GLITCHING ]";
document.querySelector('.terminal-title').textContent = ">>> SYSTEM_ERROR_0xDEADBEEF";
}
this.currentTheme = theme;
document.getElementById('theme-select').value = theme;
console.log(`Theme set to: ${theme}`);
}
// Matrix Rain Effect (new)
initMatrixRain() {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const rainContainer = document.getElementById('matrix-rain');
rainContainer.appendChild(canvas);
let W = window.innerWidth;
let H = window.innerHeight;
canvas.width = W;
canvas.height = H;
const fontSize = 15; // Smaller font size for rain
const columns = Math.floor(W / fontSize);
const drops = [];
for (let i = 0; i < columns; i++) {
drops[i] = 1;
}
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=[]{}|;:,.<>/?';
const draw = () => {
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'; // Fading effect
ctx.fillRect(0, 0, W, H);
ctx.fillStyle = varColor('--matrix-green'); // Main rain color
ctx.font = `${fontSize}px VT323`;
for (let i = 0; i < drops.length; i++) {
const text = chars.charAt(Math.floor(Math.random() * chars.length));
const x = i * fontSize;
const y = drops[i] * fontSize;
ctx.fillText(text, x, y);
if (y > H && Math.random() > 0.975) {
drops[i] = 0; // Reset drop to top
}
drops[i]++;
}
};
setInterval(draw, 33); // Animation loop for rain
// Helper to get CSS variable color
const varColor = (varName) => {
return getComputedStyle(document.body).getPropertyValue(varName);
};
window.addEventListener('resize', () => {
W = window.innerWidth;
H = window.innerHeight;
canvas.width = W;
canvas.height = H;
// Re-initialize drops for new column count if needed
const newColumns = Math.floor(W / fontSize);
if (newColumns !== columns) {
drops.length = 0; // Clear existing
for (let i = 0; i < newColumns; i++) {
drops[i] = 1;
}
}
});
}
updateStats() {
this.charCountElement.textContent = this.totalCharsProcessed;
const elapsedSeconds = (Date.now() - this.startTime) / 1000;
const wpm = elapsedSeconds > 0 ? Math.round(this.totalCharsProcessed / 5 / (elapsedSeconds / 60)) : 0;
this.wpmElement.textContent = wpm;
const progress = this.texts.length > 0 ? Math.round((this.currentTextIndex / this.texts.length) * 100) : 0;
this.progressElement.textContent = progress;
this.opCountElement.textContent = this.operationCount;
}
updateSpeedStatus() {
this.systemStatusElement.textContent = `[ STATUS: ${this.speeds[this.currentSpeedIndex].name} ]`;
}
toggleSpeed() {
this.currentSpeedIndex = (this.currentSpeedIndex + 1) % this.speeds.length;
this.updateSpeedStatus();
console.log(`Speed mode set to: ${this.speeds[this.currentSpeedIndex].name}`);
}
toggleSound() {
this.soundEnabled = !this.soundEnabled;
const soundButton = document.querySelector('[data-action="toggleSound"]');
soundButton.textContent = this.soundEnabled ? 'SOUND' : 'MUTE';
console.log(`Sound enabled: ${this.soundEnabled}`);
}
type() {
if (this.isPaused) return;
const currentFullText = this.texts[this.currentTextIndex];
if (this.currentCharIndex < currentFullText.length) {
const char = currentFullText.charAt(this.currentCharIndex);
const charSpan = document.createElement('span');
charSpan.textContent = char;
charSpan.classList.add('char', 'typed'); // Add 'typed' class for animation
this.textElement.appendChild(charSpan);
this.currentCharIndex++;
this.totalCharsProcessed++;
this.operationCount++; // Increment operations count
this.updateStats();
this.playSound();
let delay = (this.config.baseTypingSpeed + (Math.random() * this.config.typingVariance)) / this.speeds[this.currentSpeedIndex].multiplier;
if (this.config.punctuationChars.includes(char) && Math.random() < this.config.punctuationChance) {
delay += this.config.punctuationPause;
}
this.timeoutId = setTimeout(() => this.type(), delay);
} else {
this.isDeleting = true;
this.timeoutId = setTimeout(() => this.delete(), this.config.delayBeforeDelete / this.speeds[this.currentSpeedIndex].multiplier);
}
}
delete() {
if (this.isPaused) return;
if (this.currentCharIndex > 0) {
this.currentCharIndex--;
const lastCharSpan = this.textElement.lastChild;
if (lastCharSpan) {
lastCharSpan.classList.add('deleted'); // Add 'deleted' class for fade-out
setTimeout(() => lastCharSpan.remove(), 50); // Remove after brief fade
}
this.operationCount++; // Increment operations count
this.updateStats();
this.playSound();
let delay = (this.config.baseDeletingSpeed + (Math.random() * this.config.deletingVariance)) / this.speeds[this.currentSpeedIndex].multiplier;
this.timeoutId = setTimeout(() => this.delete(), delay);
} else {
this.isDeleting = false;
this.currentTextIndex = (this.currentTextIndex + 1) % this.texts.length;
this.timeoutId = setTimeout(() => this.type(), this.config.delayBeforeNext / this.speeds[this.currentSpeedIndex].multiplier);
}
}
start() {
this.startTime = Date.now();
this.totalCharsProcessed = 0;
this.operationCount = 0; // Reset operation count
this.updateStats();
this.type();
}
pause() {
this.isPaused = true;
clearTimeout(this.timeoutId);
this.cursorElement.style.animationPlayState = 'paused';
this.systemStatusElement.textContent = "[ STATUS: PAUSED ]";
console.log("Terminal paused.");
}
resume() {
if (this.isPaused) {
this.isPaused = false;
this.cursorElement.style.animationPlayState = 'running';
this.updateSpeedStatus(); // Restore speed status
if (this.isDeleting) {
this.delete();
} else {
this.type();
}
console.log("Terminal resumed.");
}
}
next() {
clearTimeout(this.timeoutId);
this.isDeleting = false;
this.currentCharIndex = 0;
this.currentTextIndex = (this.currentTextIndex + 1) % this.texts.length;
this.textElement.innerHTML = '';
this.start();
console.log("Skipping to next sequence.");
}
restart() {
clearTimeout(this.timeoutId);
this.currentTextIndex = 0;
this.currentCharIndex = 0;
this.isDeleting = false;
this.isPaused = false;
this.totalCharsProcessed = 0;
this.operationCount = 0;
this.textElement.innerHTML = '';
this.cursorElement.style.animationPlayState = 'running';
this.updateSpeedStatus(); // Restore speed status
this.start();
console.log("Terminal session restarted.");
}
setupEventListeners() {
document.querySelectorAll('.control-btn').forEach(button => {
button.addEventListener('click', (e) => {
const action = e.target.dataset.action;
if (this[action]) {
this[action]();
}
});
});
document.getElementById('sound-select').addEventListener('change', (e) => {
this.setSound(e.target.value);
});
document.getElementById('theme-select').addEventListener('change', (e) => {
this.setTheme(e.target.value);
});
}
}
new MatrixTypewriter();
});
</script>
</body>
</html>
Hello, I have this code already written, and have used it successfully on my site in the past (www.wix911.com) Happy to share it for free and help set it up for you
Feel free to reach out!
This is on the App marketplace. if you dont know code
After extensively researching these apps before writing the code for the effect I shared above, I found that most are either paid or offer free versions with significant limitations, often in exactly the areas users need most.
Hey.
Here is a velo code that will add the effect
$w.onReady(function () {
startTypewriterEffect();
addBlinkingCursor();
});
const words = ["The Future", "Everything", "Love", "Like Art"];
const typingSpeed = 100;
const erasingSpeed = 50;
const pauseBetweenWords = 1500;
const pauseAfterErase = 500;
let currentWordIndex = 0;
let isTyping = false;
function startTypewriterEffect() {
$w('#typewriterText').text = "";
typeNextWord();
}
function typeNextWord() {
if (isTyping) return;
isTyping = true;
const currentWord = words[currentWordIndex];
let currentChar = 0;
const typingInterval = setInterval(() => {
const displayText = currentWord.substring(0, currentChar + 1);
$w('#typewriterText').text = displayText;
currentChar++;
if (currentChar >= currentWord.length) {
clearInterval(typingInterval);
setTimeout(() => {
eraseCurrentWord(currentWord);
}, pauseBetweenWords);
}
}, typingSpeed);
}
function eraseCurrentWord(word) {
let currentChar = word.length;
const erasingInterval = setInterval(() => {
currentChar--;
const displayText = word.substring(0, currentChar);
$w('#typewriterText').text = displayText;
if (currentChar <= 0) {
clearInterval(erasingInterval);
currentWordIndex = (currentWordIndex + 1) % words.length;
isTyping = false;
setTimeout(() => {
typeNextWord();
}, pauseAfterErase);
}
}, erasingSpeed);
}
function addBlinkingCursor() {
let showCursor = true;
setInterval(() => {
const currentText = $w('#typewriterText').text;
if (showCursor) {
if (!currentText.endsWith('|')) {
$w('#typewriterText').text = currentText + '|';
}
} else {
if (currentText.endsWith('|')) {
$w('#typewriterText').text = currentText.slice(0, -1);
}
}
showCursor = !showCursor;
}, 500);
}
export function restartTypewriter() {
currentWordIndex = 0;
isTyping = false;
startTypewriterEffect();
}
export function updateWords(newWords) {
words.length = 0;
words.push(...newWords);
currentWordIndex = 0;
}
Use the
const typingSpeed = 100;
const erasingSpeed = 50;
const pauseBetweenWords = 1500;
const pauseAfterErase = 500;
To change the timing of the animations. 1000 = 1 Second.
Add 2 texts. In one add your static text like “Coding is” and in another text set its element ID “typewriterText” . Stack them together with 3-5px gap. Replace your words in
["The Future", "Everything", "Love", "Like Art"]
Feel free to ask any questions.
Best Regards
Thanks to all for the replies. Solved.