Как сделать курсор в виде чернильного пятна в Tilda

Модификация позволяет сделать эффект притягивания элементов к курсору мыши при наведении

Инструкция 

1
Создаём блок T123 и помещаем в него скрипт, который расположен ниже

<script src='https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.14.2/matter.min.js'></script><script  src="./script.js"></script>
2
Создаём блок T123 и помещаем в него стили, которые расположены ниже
В коде можно настроить показывать курсор-стрелку на странице или оставить только чернильный курсор, а также настроить цвет и размер курсора

<script>
var canvas = document.getElementById('canvas');
    var Engine = Matter.Engine,
    Render = Matter.Render,
    Events = Matter.Events,
    MouseConstraint = Matter.MouseConstraint,
    Mouse = Matter.Mouse,
    World = Matter.World,
    Bodies = Matter.Bodies;

// create an engine
var engine = Engine.create(),
    world = engine.world;

engine.world.gravity.y = -1;
engine.world.gravity.x =0;

// create a renderer
var render = Render.create({
    element: canvas,
    engine: engine,
    options: {
      width: window.innerWidth,
      height: window.innerHeight,
      pixelRatio: 2,
      background: 'transparent',
      wireframes: false,
    }
});


// create bounds
var ground = Bodies.rectangle(
  (window.innerWidth / 2) + 160, window.innerHeight + 80, window.innerWidth + 320, 160,{render: { fillStyle: '#080808'}, isStatic: true });
var wallLeft = Bodies.rectangle( -80, window.innerHeight / 2, 160,   window.innerHeight, { isStatic: true });
var wallRight = Bodies.rectangle(window.innerWidth + 80, window.innerHeight / 2, 160, 1200, { isStatic: true })
var roof = Bodies.rectangle(
  (window.innerWidth / 2) + 160, -80, window.innerWidth + 320, 160, { isStatic: true })

// object colors & variables
var arts = "#000"
var videos = "#B3E8F3"
var abouts = '#4D4D4D'

var border = 0
var radius = 0

// create objects

// art & design
var illustration = Bodies.rectangle(970, 50, 133, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/RADmiFI.png', xScale: 0.5, yScale: 0.5 }}})
var art = Bodies.rectangle(935, 60, 56, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/NwQqeng.png', xScale: 0.5, yScale: 0.5 }}})
var threeD = Bodies.rectangle(990, 160, 52, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/ptUWXgO.png', xScale: 0.5, yScale: 0.5 }}})
var graphic = Bodies.rectangle(960, 120, 105, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/TyOmVtt.png', xScale: 0.5, yScale: 0.5 }}})
var photo = Bodies.rectangle(1250, 380, 86, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/tc3MsJP.png', xScale: 0.5, yScale: 0.5 }}})
// video
var documentary = Bodies.rectangle(920, 140, 165, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/QYNTBNr.png', xScale: 0.5, yScale: 0.5 }}})
var animation = Bodies.rectangle(900, 90, 128, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/rSnEY9Q.png', xScale: 0.5, yScale: 0.5 }}})
var vintage = Bodies.rectangle(790, 140, 104, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/5BSBvSm.png', xScale: 0.5, yScale: 0.5 }}})
var short = Bodies.rectangle(970, 390, 82, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/VEyrikN.png', xScale: 0.5, yScale: 0.5 }}})
//misc
var website = Bodies.rectangle(760, 420, 108, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/hr9p4uV.png', xScale: 0.5, yScale: 0.5 }}})
var article = Bodies.rectangle(1100, 380, 92, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/n6TV7XG.png', xScale: 0.5, yScale: 0.5 }}})
var music = Bodies.rectangle(1290, 360, 86, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/dax8MwT.png', xScale: 0.5, yScale: 0.5 }}})
var star = Bodies.rectangle(1200, 260, 42, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/C2qPMbB.png', xScale: 0.5, yScale: 0.5 }}})
//about
var about = Bodies.rectangle(930, 140, 87, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/4gPcZVN.png', xScale: 0.5, yScale: 0.5 }}})
var instagram = Bodies.rectangle(920, 180, 40, 40, {id: 'instagramBody', chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/RStSwfG.png', xScale: 0.5, yScale: 0.5 }}, url: 'https://www.instagram.com/fuse.blog/'})
var random = Bodies.rectangle(930, 180, 112, 40, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://i.imgur.com/YS51eIC.png', xScale: 0.5, yScale: 0.5 }}})
var matilda = Bodies.rectangle(930, 180, 165, 76, {chamfer: {radius: radius}, render: { sprite: { texture: 'https://static.tildacdn.com/tild3830-3437-4538-b762-653738393335/Matilda.png', xScale: 1, yScale: 1 }}})


// Original Shape
// var illustration = Bodies.rectangle(70, 500, 133, 40, {render: { fillStyle: arts}, chamfer: {radius: 20}})


// add all of the bodies to the world
World.add(engine.world, [
  ground, wallLeft, wallRight, roof, illustration, art, threeD, graphic, photo, documentary, animation, vintage, short, website, article, music, star, about, instagram, random, matilda
]);

// add mouse control
var mouse = Mouse.create(render.canvas),
    mouseConstraint = MouseConstraint.create(engine, {
      mouse: mouse,
      constraint: {
        stiffness: 0.2,
        render: {
          visible: false
        }
      }
    });

World.add(world, mouseConstraint);

// keep the mouse in sync with rendering
render.mouse = mouse;

// Allow page scrolling in matter.js window
mouse.element.removeEventListener("mousewheel", mouse.mousewheel);
mouse.element.removeEventListener("DOMMouseScroll", mouse.mousewheel);

// Detect clicks vs. drags
let click = false;

document.addEventListener('mousedown', () => click = true);
document.addEventListener('mousemove', () => click = false);
document.addEventListener('mouseup', () => console.log(click ? 'click' : 'drag'));

// Create a On-Mouseup Event-Handler
Events.on(mouseConstraint, 'mouseup', function(event) {
  var mouseConstraint = event.source;
  var bodies = engine.world.bodies;
  if (!mouseConstraint.bodyB) {
    for (i = 0; i < bodies.length; i++) { 
      var body = bodies[i];
      // Check if clicked or dragged
      if (click === true) {
      if (Matter.Bounds.contains(body.bounds, mouseConstraint.mouse.position)) {
          var bodyUrl = body.url;
          console.log("Body.Url >> " + bodyUrl);
          // Hyperlinking feature
          if (bodyUrl != undefined) {
            //window.location.href = bodyUrl;
            window.open(bodyUrl, '_blank');
            console.log("Hyperlink was opened");
          }
          break;
        }
      }
    }
  }
});

// run the engine
Engine.run(engine);

// run the renderer
Render.run(render);
</script>
3
Создаём ещё один блок T123 и помещаем в него скрипт

<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>
Было полезно?