基于JS+Canves实现点击按钮水波纹效果


Posted in Javascript onSeptember 15, 2016

近来看到个不错的按钮点击效果,当点击时产生一次水波涟漪效果,挺好玩的,于是简单的实现了下(没考虑低版本浏览器兼容问题)

先看看效果吧,如下图(录制gif软件有点渣,看起来卡卡的...)

基于JS+Canves实现点击按钮水波纹效果

这种效果可以由元素内嵌套canves实现,也可以由css3实现。

Canves实现

网上摘了一份canves实现的代码,略微去掉了些重复定义的样式并且给出js注释,代码如下

html代码

<a class="btn color-1 material-design" data-color="#2f5398">Press me!</a>

css代码

* {
box-sizing: border-box;
outline: none;
}
body {
font-family: 'Open Sans';
font-size: 100%;
font-weight: 300;
line-height: 1.5em;
text-align: center;
}
.btn {
border: none;
display: inline-block;
color: white;
overflow: hidden;
margin: 1rem;
padding: 0;
width: 150px;
height: 40px;
text-align: center;
line-height: 40px;
border-radius: 5px;
}
.btn.color-1 {
background-color: #426fc5;
}
.btn-border.color-1 {
background-color: transparent;
border: 2px solid #426fc5;
color: #426fc5;
}
.material-design {
position: relative;
}
.material-design canvas {
opacity: 0.25;
position: absolute;
top: 0;
left: 0;
}
.container {
align-content: center;
align-items: flex-start;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
margin: 0 auto;
max-width: 46rem;
}

js代码

var canvas = {},
centerX = 0,
centerY = 0,
color = '',
containers = document.getElementsByClassName('material-design')
context = {},
element = {},
radius = 0,
// 根据callback生成requestAnimationFrame动画
requestAnimFrame = function () {
return (
window.requestAnimationFrame || 
window.mozRequestAnimationFrame || 
window.oRequestAnimationFrame || 
window.msRequestAnimationFrame || 
function (callback) {
window.setTimeout(callback, 1000 / 60);
}
);
} (),
// 为每个指定元素生成canves
init = function () {
containers = Array.prototype.slice.call(containers);
for (var i = 0; i < containers.length; i += 1) {
canvas = document.createElement('canvas');
canvas.addEventListener('click', press, false);
containers[i].appendChild(canvas);
canvas.style.width ='100%';
canvas.style.height='100%';
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
}
},
// 点击并且获取需要的数据,如点击坐标、元素大小、颜色
press = function (event) {
color = event.toElement.parentElement.dataset.color;
element = event.toElement;
context = element.getContext('2d');
radius = 0;
centerX = event.offsetX;
centerY = event.offsetY;
context.clearRect(0, 0, element.width, element.height);
draw();
},
// 绘制圆形,并且执行动画
draw = function () {
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = color;
context.fill();
radius += 2;
// 通过判断半径小于元素宽度,不断绘制 radius += 2 的圆形
if (radius < element.width) {
requestAnimFrame(draw);
}
};
init();

CSS3实现

接下来就是纯手打的代码了...觉得还是css3实现的方便些,可能是css写习惯了...

html代码

<a class="waves ts-btn">Press me!</a>

css代码

.waves{
position:relative;
cursor:pointer;
display:inline-block;
overflow:hidden;
text-align: center;
-webkit-tap-highlight-color:transparent;
z-index:1;
}
.waves .waves-animation{
position:absolute;
border-radius:50%;
width:25px;
height:25px;
opacity:0;
background:rgba(255,255,255,0.3);
transition:all 0.7s ease-out;
transition-property:transform, opacity, -webkit-transform;
-webkit-transform:scale(0);
transform:scale(0);
pointer-events:none
}
.ts-btn{
width: 200px;
height: 56px;
line-height: 56px;
background: #f57035;
color: #fff;
border-radius: 5px;
}

js代码

document.addEventListener('DOMContentLoaded',function(){
var duration = 750;
// 样式string拼凑
var forStyle = function(position){
var cssStr = '';
for( var key in position){
if(position.hasOwnProperty(key)) cssStr += key+':'+position[key]+';';
};
return cssStr;
}
// 获取鼠标点击位置
var forRect = function(target){
var position = {
top:0,
left:0
}, ele = document.documentElement;
'undefined' != typeof target.getBoundingClientRect && (position = target.getBoundingClientRect());
return {
top: position.top + window.pageYOffset - ele.clientTop,
left: position.left + window.pageXOffset - ele.clientLeft
}
}
var show = function(event){
var pDiv = event.target,
cDiv = document.createElement('div');
pDiv.appendChild(cDiv);
var rectObj = forRect(pDiv),
_height = event.pageY - rectObj.top,
_left = event.pageX - rectObj.left,
_scale = 'scale(' + pDiv.clientWidth / 100 * 10 + ')';
var position = {
top: _height+'px',
left: _left+'px'
};
cDiv.className = cDiv.className + " waves-animation",
cDiv.setAttribute("style", forStyle(position)),
position["-webkit-transform"] = _scale,
position["-moz-transform"] = _scale,
position["-ms-transform"] = _scale,
position["-o-transform"] = _scale,
position.transform = _scale,
position.opacity = "1",
position["-webkit-transition-duration"] = duration + "ms",
position["-moz-transition-duration"] = duration + "ms",
position["-o-transition-duration"] = duration + "ms",
position["transition-duration"] = duration + "ms",
position["-webkit-transition-timing-function"] = "cubic-bezier(0.250, 0.460, 0.450, 0.940)",
position["-moz-transition-timing-function"] = "cubic-bezier(0.250, 0.460, 0.450, 0.940)",
position["-o-transition-timing-function"] = "cubic-bezier(0.250, 0.460, 0.450, 0.940)",
position["transition-timing-function"] = "cubic-bezier(0.250, 0.460, 0.450, 0.940)",
cDiv.setAttribute("style", forStyle(position));
var finishStyle = {
opacity: 0,
"-webkit-transition-duration": duration + "ms", // 过渡时间
"-moz-transition-duration": duration + "ms",
"-o-transition-duration": duration + "ms",
"transition-duration": duration + "ms",
"-webkit-transform" : _scale,
"-moz-transform" : _scale,
"-ms-transform" : _scale,
"-o-transform" : _scale,
top: _height + "px",
left: _left + "px",
};
setTimeout(function(){
cDiv.setAttribute("style", forStyle(finishStyle));
setTimeout(function(){
pDiv.removeChild(cDiv);
},duration);
},100)
}
document.querySelector('.waves').addEventListener('click',function(e){
show(e);
},!1);
},!1);

好了,就这些, 顺便,中秋快乐~

Javascript 相关文章推荐
jquery 获取dom固定元素 添加样式的简单实例
Feb 04 Javascript
用json方式实现在 js 中建立一个map
May 02 Javascript
jquery.validate使用时遇到的问题
May 25 Javascript
JS随机洗牌算法之数组随机排序
Mar 23 Javascript
深入浅析javascript中的作用域(推荐)
Jul 19 Javascript
总结几道关于Node.js的面试问题
Jan 11 Javascript
thinkphp标签实现bootsrtap轮播carousel实例代码
Feb 19 Javascript
使用Browserify来实现CommonJS的浏览器加载方法
May 14 Javascript
vue脚手架vue-cli的学习使用教程
Jun 06 Javascript
Vue源码探究之状态初始化
Nov 14 Javascript
js实现多个倒计时并行 js拼团倒计时
Feb 25 Javascript
vue二维数组循环嵌套方式 循环数组、循环嵌套数组
Apr 24 Vue.js
js点击按钮实现水波纹效果代码(CSS3和Canves)
Sep 15 #Javascript
Node.js connect ECONNREFUSED错误解决办法
Sep 15 #Javascript
Bootstrap精简教程中秋大放送
Sep 15 #Javascript
AngularJS 指令的交互详解及实例代码
Sep 14 #Javascript
jQuery实现带遮罩层效果的blockUI弹出层示例【附demo源码下载】
Sep 14 #Javascript
什么是JavaScript注入攻击?
Sep 14 #Javascript
jQuery实现可拖拽的许愿墙效果【附demo源码下载】
Sep 14 #Javascript
You might like
PHP 获取MSN好友列表的代码(2009-05-14测试通过)
2009/09/09 PHP
让Json更懂中文(JSON_UNESCAPED_UNICODE)
2011/10/27 PHP
php实现批量修改文件名称的方法
2016/07/23 PHP
PHP房贷计算器实例代码,等额本息,等额本金
2017/04/01 PHP
Thinkphp结合AJAX长轮询实现PC与APP推送详解
2017/07/31 PHP
phpstudy2018升级MySQL5.5为5.7教程(图文)
2018/10/24 PHP
php根据地址获取百度地图经纬度的实例方法
2019/09/03 PHP
在 Laravel 6 中缓存数据库查询结果的方法
2019/12/11 PHP
用jscript实现新建和保存一个word文档
2007/06/15 Javascript
javascript实现的像java、c#之类的sleep暂停的函数代码
2010/03/04 Javascript
jquery阻止冒泡事件使用模拟事件
2013/09/06 Javascript
js简单实现交换Li的值
2014/05/22 Javascript
jquery中animate的stop()方法作用实例分析
2015/01/30 Javascript
Bootstrap Table 删除和批量删除
2017/09/22 Javascript
Vue2 配置 Axios api 接口调用文件的方法
2017/11/13 Javascript
Vuex实现计数器以及列表展示效果
2018/03/10 Javascript
React+Antd+Redux实现待办事件的方法
2019/03/14 Javascript
详解vue 命名视图
2019/08/14 Javascript
JavaScript函数重载操作实例浅析
2020/05/02 Javascript
[01:09:01]完美世界DOTA2联赛循环赛 Magma vs PXG BO2第一场 10.28
2020/10/28 DOTA
PyCharm代码格式调整方法
2018/05/23 Python
Windows下Anaconda2安装NLTK教程
2018/09/19 Python
解决安装pycharm后不能执行python脚本的问题
2019/01/19 Python
Python操作redis和mongoDB的方法
2019/12/19 Python
利用css3制作3D样式按钮实现代码
2013/03/18 HTML / CSS
HTML5实现视频弹幕功能
2019/08/09 HTML / CSS
玩具反斗城美国官网:Toys"R"Us
2016/09/17 全球购物
一些关于MySql加速和优化的面试题
2014/01/30 面试题
Java中会存在内存泄漏吗,请简单描述
2016/12/22 面试题
恐龙的灭绝教学反思
2014/02/12 职场文书
高中军训感想800字
2014/02/23 职场文书
腾讯广告词
2014/03/19 职场文书
2014年廉洁自律承诺书
2014/05/26 职场文书
音乐兴趣小组活动总结
2014/07/07 职场文书
我为党旗添光彩演讲稿
2014/09/10 职场文书
大学运动会加油稿200字(5篇)
2014/09/27 职场文书