Чернильный
курсор

Модификаторы
Модификация позволяет создать живой чернильный курсор
Описание
Инструкция по подключению
Создаём блок T123 и помещаем в него скрипт для работы
Шаг 1
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.8.0/gsap.min.js"></script>

<svg class='ink-icon' xmlns="http://www.w3.org/2000/svg" version="1.1" width="800">
        <defs>
          <filter id="goo">
            <feGaussianBlur in="SourceGraphic" stdDeviation="6" result="blur" />
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 35 -15" result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="atop"/>
          </filter>
        </defs>
      </svg>

<div class="page">
  <div class="container">
    <div class="child">
      <div class="content">
        <div id="button" class="HoverButton">
        </div>
      </div>
    </div>
  </div>
  <div class="stamp">
    <div class="circle">
      <p id="circle-content"></p>
    </div>
  </div>
</div>

<div id="cursor" class="Cursor">
</div>
Создаём блок T123 и помещаем в него стили
Шаг 2
.cursor span {background-color: #fff;} - меняем цвет курсора
<style>
.ink-icon {
  display: none;
}
.Cursor {
  pointer-events: none;
  position: fixed;
  display: block;
  border-radius: 0;
  transform-origin: center center;
  top: 0;
  left: 0;
  z-index: 1000;
  filter: url("#goo");
  mix-blend-mode: difference;
}
.Cursor span {
  position: absolute;
  display: block;
  width: 26px;
  height: 26px;
  border-radius: 20px;
  background-color: #fff;
  transform-origin: center center;
  transform: translate(-50%, -50%);
}

    @media screen and (max-width: 480px) {
        .Cursor {
            display: none;
        }
</style>
Cоздаём последний блок T123 и помещаем в него скрипт
Шаг 3
<script>
    function _defineProperty(obj, key, value) {if (key in obj) {Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });} else {obj[key] = value;}return obj;}const cursor = document.getElementById("cursor");
const amount = 20;
const sineDots = Math.floor(amount * 0.3);
const width = 26;
const idleTimeout = 150;
let lastFrame = 0;
let mousePosition = { x: 0, y: 0 };
let dots = [];
let timeoutID;
let idle = false;
let hoverButton;
let hoverTL;

class HoverButton {
  constructor(id) {_defineProperty(this, "onMouseEnter",










    () => {
      this.hoverInAnim();
    });_defineProperty(this, "hoverInAnim",

    () => {
      if (!this.hovered) {
        this.hovered = true;
        this.animatingHover = true;
        this.forceOut = false;
        TweenMax.fromTo(
        this.bg,
        this.timing,
        { x: "-112%" },
        {
          x: "-12%",
          ease: Power3.easeOut,
          onComplete: () => {
            this.animatingHover = false;
            if (this.forceOut) {
              this.foceOut = false;
              this.hoverOutAnim();
            }
          } });


      }
    });_defineProperty(this, "onMouseLeave",

    () => {
      if (!this.animatingHover) {
        this.hoverOutAnim();
      } else {
        this.forceOut = true;
      }
    });_defineProperty(this, "hoverOutAnim",

    () => {
      this.hovered = false;
      TweenMax.to(this.bg, this.timing, {
        x: "100%",
        ease: Power3.easeOut,
        onComplete: () => {
        } });

    });this.hovered = false;this.animatingHover = false;this.forceOut = false;this.timing = 0.65;this.el = document.getElementById(id);this.bg = this.el.getElementsByClassName("bg")[0];this.el.addEventListener("mouseenter", this.onMouseEnter);this.el.addEventListener("mouseleave", this.onMouseLeave);}}


class Dot {
  constructor(index = 0) {
    this.index = index;
    this.anglespeed = 0.05;
    this.x = 0;
    this.y = 0;
    this.scale = 1 - 0.05 * index;
    this.range = width / 2 - width / 2 * this.scale + 2;
    this.limit = width * 0.75 * this.scale;
    this.element = document.createElement("span");
    TweenMax.set(this.element, { scale: this.scale });
    cursor.appendChild(this.element);
  }

  lock() {
    this.lockX = this.x;
    this.lockY = this.y;
    this.angleX = Math.PI * 2 * Math.random();
    this.angleY = Math.PI * 2 * Math.random();
  }

  draw(delta) {
    if (!idle || this.index <= sineDots) {
      TweenMax.set(this.element, { x: this.x, y: this.y });
    } else {
      this.angleX += this.anglespeed;
      this.angleY += this.anglespeed;
      this.y = this.lockY + Math.sin(this.angleY) * this.range;
      this.x = this.lockX + Math.sin(this.angleX) * this.range;
      TweenMax.set(this.element, { x: this.x, y: this.y });
    }
  }}


class Circle {
  constructor(id) {
    const el = document.getElementById(id);
    const parent = el.parentElement;
    parent.removeChild(el);
    const chars = el.innerText.split("");
    chars.push(" ");
    for (let i = 0; i < chars.length; i++) {
      const span = document.createElement("span");
      span.innerText = chars[i];
      span.className = `char${i + 1}`;
      parent.appendChild(span);
    }
  }}


function init() {
  window.addEventListener("mousemove", onMouseMove);
  window.addEventListener("touchmove", onTouchMove);
  hoverButton = new HoverButton("button");
  // eslint-disable-next-line no-new
  new Circle("circle-content");
  lastFrame += new Date();
  buildDots();
  render();
}

/*function limit(value, min, max) {
    return Math.min(Math.max(min, value), max);
}*/

function startIdleTimer() {
  timeoutID = setTimeout(goInactive, idleTimeout);
  idle = false;
}

function resetIdleTimer() {
  clearTimeout(timeoutID);
  startIdleTimer();
}

function goInactive() {
  idle = true;
  for (let dot of dots) {
    dot.lock();
  }
}

function buildDots() {
  for (let i = 0; i < amount; i++) {
    let dot = new Dot(i);
    dots.push(dot);
  }
}

const onMouseMove = event => {
  mousePosition.x = event.clientX - width / 2;
  mousePosition.y = event.clientY - width / 2;
  resetIdleTimer();
};

const onTouchMove = () => {
  mousePosition.x = event.touches[0].clientX - width / 2;
  mousePosition.y = event.touches[0].clientY - width / 2;
  resetIdleTimer();
};

const render = timestamp => {
  const delta = timestamp - lastFrame;
  positionCursor(delta);
  lastFrame = timestamp;
  requestAnimationFrame(render);
};

const positionCursor = delta => {
  let x = mousePosition.x;
  let y = mousePosition.y;
  dots.forEach((dot, index, dots) => {
    let nextDot = dots[index + 1] || dots[0];
    dot.x = x;
    dot.y = y;
    dot.draw(delta);
    if (!idle || index <= sineDots) {
      const dx = (nextDot.x - dot.x) * 0.35;
      const dy = (nextDot.y - dot.y) * 0.35;
      x += dx;
      y += dy;
    }
  });
};

init();
</script>
Made on
Tilda