<a href="#" class="btn-liquid" id="liquid-btn">
<span class="inner">Liquid button ?</span>
</a>
<style>
.btn-liquid {
display: inline-block;
position: relative;
width: 240px;
height: 60px;
border-radius: 27px;
color: #fff;
font: 700 14px/60px "Droid Sans", sans-serif;
letter-spacing: 0.05em;
text-align: center;
text-decoration: none;
text-transform: uppercase;
cursor: pointer;
user-select: none;
overflow: hidden;
}
.btn-liquid .inner {
position: relative;
z-index: 2;
}
.btn-liquid canvas {
position: absolute;
top: -50px;
right: -50px;
bottom: -50px;
left: -50px;
z-index: 1;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
(function($) {
$(function() {
var pointsA = [],
pointsB = [],
$canvas = null,
canvas = null,
context = null,
points = 8,
viscosity = 20,
mouseDist = 70,
damping = 0.05,
showIndicators = false;
var mouseX = 0,
mouseY = 0,
relMouseX = 0,
relMouseY = 0,
mouseLastX = 0,
mouseLastY = 0,
mouseDirectionX = 0,
mouseDirectionY = 0,
mouseSpeedX = 0,
mouseSpeedY = 0;
function mouseDirection(e) {
if (mouseX < e.pageX) mouseDirectionX = 1;
else if (mouseX > e.pageX) mouseDirectionX = -1;
else mouseDirectionX = 0;
if (mouseY < e.pageY) mouseDirectionY = 1;
else if (mouseY > e.pageY) mouseDirectionY = -1;
else mouseDirectionY = 0;
mouseX = e.pageX;
mouseY = e.pageY;
relMouseX = (mouseX - $canvas.offset().left);
relMouseY = (mouseY - $canvas.offset().top);
}
function mouseSpeed() {
mouseSpeedX = mouseX - mouseLastX;
mouseSpeedY = mouseY - mouseLastY;
mouseLastX = mouseX;
mouseLastY = mouseY;
setTimeout(mouseSpeed, 50);
}
function Point(x, y, level) {
this.x = this.ix = 50 + x;
this.y = this.iy = 50 + y;
this.vx = 0;
this.vy = 0;
this.cx1 = 0;
this.cy1 = 0;
this.level = level;
}
Point.prototype.move = function() {
this.vx += (this.ix - this.x) / (viscosity * this.level);
this.vy += (this.iy - this.y) / (viscosity * this.level);
var dx = this.ix - relMouseX;
var dy = this.iy - relMouseY;
var relDist = (1 - Math.sqrt((dx * dx) + (dy * dy)) / mouseDist);
if ((mouseDirectionX > 0 && relMouseX > this.x) || (mouseDirectionX < 0 && relMouseX < this.x)) {
if (relDist > 0 && relDist < 1) {
this.vx = (mouseSpeedX / 4) * relDist;
}
}
this.vx *= (1 - damping);
this.x += this.vx;
if ((mouseDirectionY > 0 && relMouseY > this.y) || (mouseDirectionY < 0 && relMouseY < this.y)) {
if (relDist > 0 && relDist < 1) {
this.vy = (mouseSpeedY / 4) * relDist;
}
}
this.vy *= (1 - damping);
this.y += this.vy;
};
function addPoints(x, y) {
pointsA.push(new Point(x, y, 1));
pointsB.push(new Point(x, y, 2));
}
function initButton() {
var button = $('.btn-liquid');
var buttonWidth = button.width();
var buttonHeight = button.height();
$canvas = $('<canvas></canvas>');
button.append($canvas);
canvas = $canvas.get(0);
canvas.width = buttonWidth + 100;
canvas.height = buttonHeight + 100;
context = canvas.getContext('2d');
var x = buttonHeight / 2;
for (var j = 1; j < points; j++) {
addPoints((x + ((buttonWidth - buttonHeight) / points) * j), 0);
}
addPoints(buttonWidth - buttonHeight / 5, 0);
addPoints(buttonWidth + buttonHeight / 10, buttonHeight / 2);
addPoints(buttonWidth - buttonHeight / 5, buttonHeight);
for (var j = points - 1; j > 0; j--) {
addPoints((x + ((buttonWidth - buttonHeight) / points) * j), buttonHeight);
}
addPoints(buttonHeight / 5, buttonHeight);
addPoints(-buttonHeight / 10, buttonHeight / 2);
addPoints(buttonHeight / 5, 0);
renderCanvas();
}
function renderCanvas() {
requestAnimationFrame(renderCanvas);
context.clearRect(0, 0, canvas.width, canvas.height);
// переменные для градиента
var gradientX = Math.min(Math.max(mouseX - $canvas.offset().left, 0), canvas.width);
var gradientY = Math.min(Math.max(mouseY - $canvas.offset().top, 0), canvas.height);
var distance = Math.sqrt(Math.pow(gradientX - canvas.width / 2, 2) + Math.pow(gradientY - canvas.height / 2, 2)) /
Math.sqrt(Math.pow(canvas.width / 2, 2) + Math.pow(canvas.height / 2, 2));
var gradient = context.createRadialGradient(gradientX, gradientY, 300 + (300 * distance), gradientX, gradientY, 0);
gradient.addColorStop(0, '#102ce5');
gradient.addColorStop(1, '#E406D6');
for (var i = 0; i < pointsA.length; i++) {
pointsA[i].move();
pointsB[i].move();
}
var groups = [pointsA, pointsB];
for (var j = 0; j <= 1; j++) {
var pts = groups[j];
context.beginPath();
context.moveTo(pts[0].x, pts[0].y);
for (var i = 0; i < pts.length; i++) {
var p = pts[i];
var nextP = pts[i + 1] || pts[0];
p.cx1 = (p.x + nextP.x) / 2;
p.cy1 = (p.y + nextP.y) / 2;
context.bezierCurveTo(p.x, p.y, p.cx1, p.cy1, p.cx1, p.cy1);
}
if (j === 0) {
context.fillStyle = '#1CE2D8';
} else {
context.fillStyle = gradient;
}
context.fill();
}
}
$(document).on('mousemove', mouseDirection);
mouseSpeed();
initButton();
});
})(jQuery);
</script>
https://codepen.io/waaark/pen/VbgwEM