<svg 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="page-bg">
		<p>M</p>
		<div class="noise"></div>
	</div>
	
	<div class="lines">
		<div class="line1"></div>
		<div class="line2"></div>
		<div class="line3"></div>
		<div class="line4"></div>
		<div class="line5"></div>
	</div>
	
	<div class="container">
		<div class="child">
			<div class="content">
				<div>
				<div id="button" class="HoverButton">
					<div class="bg"></div>
					<h1>Hover Me</h1>
				</div>
				</div>
			</div>
		</div>
	</div>
	
	<div class="images">
		<img src="https://foo-exp.s3.amazonaws.com/morph_mouse/img_big.png" class="big" id="bigImg">
		<img src="https://foo-exp.s3.amazonaws.com/morph_mouse/img_small.png" class="small" id="smallImg">
	</div>
	
	<div class="stamp">
		<div class="circle">
			<p id="circle-content">EXPERIMENTS . EXPERIMENTS .</p>
		</div>
		<p>2018</p>
	</div>
	
	<div class="design">
		<p>Best viewed on Chrome</p>
		<a href="https://dribbble.com/eaamst" target="blank">Designed by: Eder Anaya</a>
	</div>
	
</div>
<div id="cursor" class="Cursor">
</div>
*
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;

body
html
    cursor none
    width 100%
    height 100%
    font-family 'Roboto', sans-serif
    background-color #e0dad5
    overflow hidden

svg
    display none

.page
    width 100%
    height 100%
    background-color #e0dad5
    display block

.page-bg
    width 100%
    height 100%
    display block
    position absolute
    overflow hidden
    top 0
    left 0
    z-index 1
    background-color #e0dad5

    p
        font-family 'Asul', sans-serif
        color #dbd6d1
        opacity 0.8
        font-size 85vmin
        margin 0
        text-align center
        line-height 100vh

.noise
    background-image url('https://foo-exp.s3.amazonaws.com/morph_mouse/noise_pattern.png')
    background-size 200px 200px
    background-repeat repeat
    position absolute
    top 0
    left 0
    width 100%
    height 100%
    mix-blend-mode hard-light

.container
    width 100%
    height 100%
    display table
    z-index 100

.child
    display table-row

.content
    display table-cell
    vertical-align middle
    text-align center

.HoverButton
    position relative
    display inline-block
    z-index 20
    padding 0 2%
    overflow hidden
    //overflow-x hidden
    &:after
        content "01"
        display block
        position absolute
        color #ee3d3d
        top 5%
        right 3%
        mix-blend-mode difference
        font-family 'Asul', sans-serif
        font-size 1.2vmax
        font-weight bold

    .bg
        pointer-events none
        position absolute
        background-color #ee3d3d
        height 100%
        width: 125%
        display block
        //z-index 1
        transform translateX(-112%) skew(-10deg)

h1
    color #ee3d3d
    position relative
    font-weight normal
    font-family 'Asul', sans-serif
    z-index 1
    margin 0
    font-size 11vmax
    mix-blend-mode difference

.images
    position absolute
    left 50%
    top 64vh
    transform translate(-50%, 0);
    z-index 10
    pointer-events none
    .big
        width 36vmax
    .small
        width 27vmax
        position absolute
        left 50%
        top 50%
        transform translate(-50%, -50%)

.Cursor
    pointer-events none
    position fixed
    display block
    border-radius 0
    transform-origin center center
    mix-blend-mode difference
    top 0
    left 0
    z-index 1000
    filter url("#goo")
    span
        position absolute
        display block
        width: 26px
        height 26px
        border-radius 20px
        background-color: white
        transform-origin center center
        transform: translate(-50%, -50%)


.stamp
    position absolute
    right 6vmax
    top 6vmax
    z-index 10
    p
        color #ee3d3d
        font-size 2vmax
        font-family 'Asul', sans-serif
        margin 0
    .circle
        position absolute
        width 1px
        height 1px
        display block
        left 50%
        top 50%
        background-color transparent
        animation rotating 9.5s linear infinite
        span
            font-family: 'Rubik', sans-serif;
            font-weight bold
            font-size 0.8vmax
            color #ee3d3d
            height 5vmax
            position absolute
            display inline-block
            left 0
            bottom 0
            transform-origin: bottom center

for i in (1..28)
    .char{i}
        transform rotate((i*13)deg)

@keyframes rotating {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(360deg);
    }
}

.line
    position absolute
    background-color #ede8e5

.line-vertical
    @extends .line
    width 2px
    height 100%
    top 0

.line-horizontal
    @extends .line
    width 100%
    height 2px
    left 0


.lines
    position absolute
    width 100%
    height 100%
    left 0
    top 0
    z-index 2
    .line1
        @extends .line-horizontal
        top 36vh

    .line2
        @extends .line-horizontal
        top 64vh

    .line3
        @extends .line-vertical
        left 22vw

    .line4
        @extends .line-vertical
        left 78vw

    .line5
        @extends .line-vertical
        left 50vw



.design
    position absolute
    left 10px
    top 10px
    z-index 5
    color black
    font-family: 'Work Sans', sans-serif;
    font-size 10px
    a
        color black
View Compiled
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) {
        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);
    }

    onMouseEnter = () => {
        this.hoverInAnim();
    };

    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();
                        }
                    }
                }
            );
        }
    };

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

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

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();
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.1/TweenMax.min.js