How to Create This Typewriter Effect?

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>

:upside_down_face:

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 :slight_smile:

Feel free to reach out!

typewriter effect wix911

This is on the App marketplace. if you dont know code

1 Like

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

1 Like

Thanks to all for the replies. Solved.