Skip to content

Instantly share code, notes, and snippets.

@gschier
Last active August 19, 2023 18:27
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save gschier/6903476 to your computer and use it in GitHub Desktop.
Save gschier/6903476 to your computer and use it in GitHub Desktop.
A Pen by Gregory Schier.
<h1>This pen is
<span
class="txt-rotate"
data-period="2000"
data-rotate='[ "nerdy.", "simple.", "pure JS.", "pretty.", "fun!" ]'></span>
</h1>
<h2>A single &lt;span&gt; is all you need.</h2>
var TxtRotate = function(el, toRotate, period) {
this.toRotate = toRotate;
this.el = el;
this.loopNum = 0;
this.period = parseInt(period, 10) || 2000;
this.txt = '';
this.tick();
this.isDeleting = false;
};
TxtRotate.prototype.tick = function() {
var i = this.loopNum % this.toRotate.length;
var fullTxt = this.toRotate[i];
if (this.isDeleting) {
this.txt = fullTxt.substring(0, this.txt.length - 1);
} else {
this.txt = fullTxt.substring(0, this.txt.length + 1);
}
this.el.innerHTML = '<span class="wrap">'+this.txt+'</span>';
var that = this;
var delta = 300 - Math.random() * 100;
if (this.isDeleting) { delta /= 2; }
if (!this.isDeleting && this.txt === fullTxt) {
delta = this.period;
this.isDeleting = true;
} else if (this.isDeleting && this.txt === '') {
this.isDeleting = false;
this.loopNum++;
delta = 500;
}
setTimeout(function() {
that.tick();
}, delta);
};
window.onload = function() {
var elements = document.getElementsByClassName('txt-rotate');
for (var i=0; i<elements.length; i++) {
var toRotate = elements[i].getAttribute('data-rotate');
var period = elements[i].getAttribute('data-period');
if (toRotate) {
new TxtRotate(elements[i], JSON.parse(toRotate), period);
}
}
// INJECT CSS
var css = document.createElement("style");
css.type = "text/css";
css.innerHTML = ".txt-rotate > .wrap { border-right: 0.1em solid #666 }";
document.body.appendChild(css);
};
@hdhumanez
Copy link

hdhumanez commented Aug 19, 2023

If you use Typescript or Next.js with Typescript this is the code:

"use client";
import { useEffect } from 'react';

export default function Home() {
  class TxtRotate {
    private toRotate: string[];
    private el: HTMLElement;
    private loopNum: number;
    private period: number;
    private txt: string;
    private isDeleting: boolean;
  
    constructor(el: HTMLElement, toRotate: string[], period: string) {
      this.toRotate = toRotate;
      this.el = el;
      this.loopNum = 0;
      this.period = parseInt(period, 10) || 2000;
      this.txt = '';
      this.tick();
      this.isDeleting = false;
    }
  
    private tick(): void {
      const i = this.loopNum % this.toRotate.length;
      const fullTxt = this.toRotate[i];
  
      if (this.isDeleting) {
        this.txt = fullTxt.substring(0, this.txt.length - 1);
      } else {
        this.txt = fullTxt.substring(0, this.txt.length + 1);
      }
  
      this.el.innerHTML = '<span class="wrap">' + this.txt + '</span>';
  
      const that = this;
      let delta = 300 - Math.random() * 100;
  
      if (this.isDeleting) {
        delta /= 2;
      }
  
      if (!this.isDeleting && this.txt === fullTxt) {
        delta = this.period;
        this.isDeleting = true;
      } else if (this.isDeleting && this.txt === '') {
        this.isDeleting = false;
        this.loopNum++;
        delta = 500;
      }
  
      setTimeout(function () {
        that.tick();
      }, delta);
    }
  }
  
  useEffect(() => {
    const elements = document.getElementsByClassName('txt-rotate');
    for (let i = 0; i < elements.length; i++) {
      const toRotate = elements[i].getAttribute('data-rotate');
      const period = elements[i].getAttribute('data-period');
      if (toRotate && period) {
        new TxtRotate(elements[i] as HTMLElement, JSON.parse(toRotate), period);
      }
    }
    // INJECT CSS
    const css = document.createElement('style');
    css.setAttribute('type', 'text/css');  //Because css.type is deprecated
    css.innerHTML = '.txt-rotate > .wrap { border-right: 0.1em solid #666 }';
    document.body.appendChild(css);
  }, [])
  
  return(
    <>
      <h1>This pen is
        <span
          className="txt-rotate"
          data-period="2000"
          data-rotate='[ "nerdy.", "simple.", "pure JS.", "pretty.", "fun!" ]'
        >
        </span>
      </h1>
      <h2>A single &lt;span&gt; is all you need.</h2>
    </>
  )

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment