<div class="cbtn-wrap">
<div id="cbtn-title"></div>
<div class="cbtn-nav" id="nav-prev">
<i class="fas fa-chevron-left"></i>
</div>
<div class="cbtn-o" id="cbtn1">
<div class="cbtn-i" data-mode="0">Hover / Click / Hold</div>
</div>
<div class="cbtn-nav" id="nav-next">
<i class="fas fa-chevron-right"></i>
</div>
<div class="info-wrap">
<div class="info-text"></div>
</div>
</div>
<div class="social">
<a class="icon" href="https://twitter.com/Tiibiix" target="_blank">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/1692350/twitter-icon-256.png"/>
</a>
</div>
@import url('https://fonts.googleapis.com/css?family=Montserrat&display=swap');
html,body{
margin: 0px;
background: #000;
}
.cbtn-wrap{
overflow: hidden;
text-align: center;
margin-top: 50px;
}
#cbtn-title{
position: relative;
font-family: Montserrat;
color: #fff;
font-size: 24px;
text-transform: uppercase;
font-weight: 600;
text-decoration: underline;
}
.cbtn-o{
display: inline-block;
position: relative;
& > .cbtn-i{
position: relative;
z-index: 3;
cursor: pointer;
margin: 40px 20px;
padding: 10px 25px;
border-radius: 100px;
font-family: Montserrat;
font-weight: 600;
color: #fff;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
transition: 250ms cubic-bezier(0,.5,.5,1);
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
&[data-mode="0"]{
background: #e96651;
box-shadow: 0px 0px 0px #e96651;
&:hover{
transform: scale(0.9);
background: #efaf60;
box-shadow: 0px 0px 30px #efaf60;
}
&:active{
transform: scale(1);
}
}
&[data-mode="1"]{
background: #3770a0;
box-shadow: 0px 0px 0px #3770a0;
&:hover{
transform: scale(0.9);
background: #77b6ea;
box-shadow: 0px 0px 20px #77b6ea;
}
&:active{
transform: scale(0.6);
}
}
&[data-mode="2"]{
background: #30a254;
box-shadow: 0px 0px 0px #30a254;
transition: 350ms cubic-bezier(0,.5,.5,1);
&:hover{
transform: scale(0.9);
background: #51e980;
box-shadow: 0px 0px 30px #51e980;
}
&:active{
transform: scale(0.9) rotateX(-360deg);
}
}
&[data-mode="3"]{
background: #8e54ff;
box-shadow: 0px 0px 0px #8e54ff;
&:hover{
transform: scale(0.9);
background: #a93ee0;
box-shadow: 0px 0px 30px #a93ee0;
}
&:active{
transform: scale(0.9) rotate(-360deg);
}
}
&[data-mode="4"]{
background: #ff0000;
box-shadow: 0px 0px 0px #ff0000;
&:hover{
transform: scale(0.9);
background: #ff0000;
box-shadow: 0px 0px 30px #ff0000;
}
&:active{
transition: none;
filter: blur(7px);
color: transparent;
}
}
}
& > canvas{
position: absolute;
z-index: 2;
top: 0px;
left: 0px;
}
}
.cbtn-nav{
color: #fff;
display: inline-block;
position: relative;
z-index: 1;
font-size: 18px;
padding: 10px;
cursor: pointer;
text-shadow: 2px 2px 4px #111;
&#nav-next{
margin-left: 20px;
&::before{
left: 15px;
}
}
&#nav-prev{
margin-right: 20px;
&::before{
left: 17px;
}
}
&:hover::before{
width: 40px;
height: 40px;
}
&::before{
content: "";
position: absolute;
border-radius: 100px;
top: 20px;
transform: translate(-50%, -50%);
height: 0px;
width: 0px;
background: #333333;
z-index: -1;
transition: 150ms ease-in-out;
}
}
.next_anim{
animation: next 600ms ease;
pointer-events: none;
}
.prev_anim{
animation: prev 600ms ease;
pointer-events: none;
}
.info-wrap{
font-family: Montserrat;
& > .info-text{
display: inline-block;
color: #333333;
width: 30%;
max-width: 300px;
padding: 15px;
background: #ccc;
border-radius: 100px;
font-size: 14px;
font-weight: 600;
}
}
@keyframes next{
0%{
left: 0px;
opacity: 1;
}
50%{
left: 300px;
opacity: 0;
}
50.1%{
left: -300px;
opacity: 0;
}
100%{
left: 0px;
opacity: 1;
}
}
@keyframes prev{
0%{
left: 0px;
opacity: 1;
}
50%{
left: -300px;
opacity: 0;
}
50.1%{
left: 300px;
opacity: 0;
}
100%{
left: 0px;
opacity: 1;
}
}
.social{
z-index: 1001;
position: absolute;
bottom: 20px;
left: 30px;
& .icon{
display: inline-block;
&:hover img{
transform: scale(0.8);
}
& img{
display: inline-block;
height: 40px;
width: 40px;
position: relative;
transition: 150ms cubic-bezier(0,.5,.5,1);
}
}
& .icon::before{
content: "";
position: absolute;
border-radius: 100px;
top: 20px;
left: 20px;
transform: translate(-50%, -50%);
height: 0px;
width: 0px;
background: #333;
z-index: -1;
transition: 150ms cubic-bezier(0,.5,.5,1);
}
& .icon:hover::before{
height: 50px;
width: 50px;
}
}
View Compiled
window.onload = function(){
var canvas = document.createElement("canvas");
var innerBtn = document.querySelector("#cbtn1 .cbtn-i");
var outerBtn = document.getElementById("cbtn1");
var nextBtn = document.getElementById("nav-next");
var prevBtn = document.getElementById("nav-prev");
var btnTitle = document.getElementById("cbtn-title");
var tipText = document.querySelector(".info-wrap .info-text");
outerBtn.appendChild(canvas);
var ctx = canvas.getContext("2d");
w = ctx.canvas.width = outerBtn.offsetWidth;
h = ctx.canvas.height = outerBtn.offsetHeight;
dots=[];
hoverFlag = false;
clickFlag = false;
mode = 0;
nt = 0;
tip = 0;
tips = [
"Stepping up your hover effects game!",
"The spacing/canvas area around the button can be easily adjusted via CSS margin.",
"Tested in IE and on various mobile devices.",
"No libraries required!",
"Imagine the endless possibilities :)",
"In this case there is only one Button which is being controlled via JS.",
"Using a black background for the best contrast.",
"More effects coming soon..."
];
modeSets = [
{
name: "Fireflies",
maxDots: 75,
maxSpeed: 3,
minSpeed: 1,
emitRate: 10,
emitNum: 2,
radius: 2,
trail: 0.2,
maxTime: 1500,
minTime: 750,
glow: 10,
hueMin: 15,
hueMax: 55
},
{
name: "Hyper Jump",
maxDots: 100,
maxSpeed: 3,
minSpeed: 1,
emitRate: 10,
emitNum: 3,
radius: 1.75,
trail: 0.06,
maxTime: 700,
minTime: 300,
glow: 7,
hueMin: 170,
hueMax: 230
},
{
name: "Focus",
maxDots: 75,
maxSpeed: 2,
minSpeed: 0.5,
emitRate: 10,
emitNum: 2,
radius: 7,
trail: 1,
maxTime: 1000,
minTime: 500,
glow: 0,
hueMin: 60,
hueMax: 130
},
{
name: "Vortex",
maxDots: 150,
maxSpeed: 2,
minSpeed: -2,
emitRate: 20,
emitNum: 5,
radius: 7,
trail: 1,
maxTime: 3000,
minTime: 1500,
glow: 0,
hueMin: 260,
hueMax: 330
}
,
{
name: "Code Red",
maxDots: 50,
maxSpeed: 1,
minSpeed: 0.3,
emitRate: 20,
emitNum: 1,
radius: 1.7,
trail: 1,
maxTime: 3000,
minTime: 1500,
glow: 10,
hueMin: 0,
hueMax: 10
}
]
function emitDots(x,y){
if(dots.length<modeSets[mode].maxDots){
for(var i=0; i<modeSets[mode].emitNum; i++){
var color = Math.random()*(modeSets[mode].hueMax-modeSets[mode].hueMin)+modeSets[mode].hueMin;
dots.push({
x: w/2,
y: h/2,
v: Math.random()*(modeSets[mode].maxSpeed-modeSets[mode].minSpeed)+modeSets[mode].minSpeed,
d: Math.random()*360,
c: Math.random()*(5-(-5))+(-5),
h: color,
st: Date.now(),
lt: Math.random()*(modeSets[mode].maxTime-modeSets[mode].minTime)+modeSets[mode].minTime
});
}
}
}
function draw(){
nt += 0.0005;
ctx.fillStyle = "rgba(0,0,0,"+modeSets[mode].trail+")";
ctx.fillRect(0,0,w,h);
ctx.fill();
for(var i=0; i<dots.length; i++){
var pct = (Date.now()-dots[i].st)/dots[i].lt;
switch(mode){
case 0:
ctx.save();
ctx.beginPath();
ctx.fillStyle = "hsla("+dots[i].h+", 100%, 60%, "+(1-pct)+")";
ctx.shadowColor = "hsla("+dots[i].h+", 100%, 60%, 1)";
ctx.shadowBlur = modeSets[mode].glow;
ctx.arc(dots[i].x, dots[i].y, Math.pow(modeSets[mode].radius,2)/dots[i].v, 0, Math.PI*2);
ctx.fill();
ctx.closePath();
ctx.restore();
dots[i].x += dots[i].v * Math.cos(dots[i].d * Math.PI/180);
dots[i].y += dots[i].v * Math.sin(dots[i].d * Math.PI/180);
dots[i].d += dots[i].c;
if(clickFlag)
dots[i].v = 1;
break;
case 1:
ctx.save();
ctx.beginPath();
ctx.fillStyle = "hsla("+dots[i].h+", 100%, 70%, "+(1-pct)+")";
ctx.shadowColor = "hsla("+dots[i].h+", 100%, 70%, 1)";
ctx.shadowBlur = modeSets[mode].glow;
ctx.arc(dots[i].x, dots[i].y, Math.pow(modeSets[mode].radius,2)/dots[i].v, 0, Math.PI*2);
ctx.fill();
ctx.closePath();
ctx.restore();
dots[i].x += dots[i].v * Math.cos(dots[i].d * Math.PI/180);
dots[i].y += dots[i].v * Math.sin(dots[i].d * Math.PI/180);
if(clickFlag)
dots[i].v = 3;
break;
case 2:
ctx.save();
ctx.beginPath();
ctx.fillStyle = "hsla("+dots[i].h+", 100%, 70%, "+(1-pct)+")";
ctx.shadowColor = "hsla("+dots[i].h+", 100%, 70%, 1)";
ctx.shadowBlur = modeSets[mode].glow;
ctx.arc(dots[i].x, dots[i].y, modeSets[mode].radius, 0, Math.PI*2);
ctx.fill();
ctx.closePath();
ctx.restore();
dots[i].x += dots[i].v * Math.cos(dots[i].d * Math.PI/180);
dots[i].y += dots[i].v * Math.sin(dots[i].d * Math.PI/180);
if(clickFlag)
dots[i].v = 0.3;
break;
case 3:
ctx.save();
ctx.beginPath();
ctx.translate(w/2,h/2);
ctx.rotate(dots[i].d*Math.PI/180);
ctx.fillStyle = "hsla("+dots[i].h+", 100%, 70%, "+(pct)+")";
ctx.shadowColor = "hsla("+dots[i].h+", 100%, 70%, 1)";
ctx.shadowBlur = modeSets[mode].glow;
ctx.rect(dots[i].x, dots[i].y, modeSets[mode].radius, modeSets[mode].radius);
ctx.fill();
ctx.closePath();
ctx.restore();
dots[i].x += dots[i].v;
dots[i].y += dots[i].v;
if(clickFlag)
dots[i].v = 3;
break;
case 4:
var sd = Math.pow(modeSets[mode].radius,2)/dots[i].v;
ctx.save();
ctx.beginPath();
ctx.strokeStyle = "hsla("+dots[i].h+", 100%, 50%, "+(1-pct)+")";
ctx.shadowColor = "hsla("+dots[i].h+", 100%, 50%, 1)";
ctx.shadowBlur = modeSets[mode].glow;
if(clickFlag){
ctx.arc(dots[i].x, dots[i].y, sd, 0, Math.PI*2);
}else{
ctx.rect(dots[i].x-sd, dots[i].y-sd, sd*2, sd*2);
}
ctx.stroke();
ctx.closePath();
ctx.restore();
dots[i].x += dots[i].v * Math.cos(dots[i].d * Math.PI/180);
dots[i].y += dots[i].v * Math.sin(dots[i].d * Math.PI/180);
break;
}
if(dots[i].x>w || dots[i].x<0 || dots[i].y>h || dots[i].y<0 || dots[i].st+dots[i].lt<Date.now()){
dots.splice(i,1);
}
}
anim = requestAnimationFrame(draw);
}
innerBtn.onmouseover = function(){
hoverFlag = true;
emitter = setInterval(emitDots, modeSets[mode].emitRate);
anim = requestAnimationFrame(draw);
}
innerBtn.onmouseout = function(){
hoverFlag = false;
clearInterval(emitter);
cancelAnimationFrame(anim);
ctx.clearRect(0,0,w,h);
dots = [];
}
innerBtn.onmousedown = function(){
clickFlag = true;
}
innerBtn.onmouseup = function(){
clickFlag = false;
}
btnTitle.innerHTML = modeSets[mode].name;
nextBtn.onclick = function(){
if(modeSets.length <= mode+1){
mode = 0;
}else{
mode += 1;
}
setTimeout(function(){
innerBtn.setAttribute("data-mode", mode);
btnTitle.innerHTML = modeSets[mode].name;
}, 300);
outerBtn.classList.add("next_anim");
btnTitle.classList.add("prev_anim");
setTimeout(function(){
outerBtn.classList.remove("next_anim");
btnTitle.classList.remove("prev_anim");
}, 600)
}
prevBtn.onclick = function(){
if(0 > mode-1){
mode = modeSets.length-1;
}else{
mode -= 1;
}
setTimeout(function(){
innerBtn.setAttribute("data-mode", mode);
btnTitle.innerHTML = modeSets[mode].name;
}, 300);
outerBtn.classList.add("prev_anim");
btnTitle.classList.add("next_anim");
setTimeout(function(){
outerBtn.classList.remove("prev_anim");
btnTitle.classList.remove("next_anim");
}, 600)
}
tipText.innerHTML = tips[tip];
setInterval(function(){
tips.length<=tip+1?tip=0:tip+=1;
tipText.innerHTML = tips[tip];
}, 7000)
}
// Hey! Wow, you found a comment. Thanks for checking this Pen out :)
This Pen doesn't use any external JavaScript resources.