基于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 相关文章推荐
javascript contains和compareDocumentPosition 方法来确定是否HTML节点间的关系
Feb 04 Javascript
cument.execCommand()用法深入理解
Dec 04 Javascript
求数组最大最小值方法适用于任何数组
Aug 16 Javascript
js由下向上不断上升冒气泡效果实例
May 07 Javascript
jquery Easyui快速开发总结
Aug 20 Javascript
js实现表单多按钮提交action的处理方法
Oct 24 Javascript
JS封装的三级联动菜单(使用时只需要一行js代码)
Oct 24 Javascript
jquery-mobile基础属性与用法详解
Nov 23 Javascript
利用js+css+html实现固定table的列头不动
Dec 08 Javascript
详解Vue-基本标签和自定义控件
Mar 24 Javascript
详解vue中axios请求的封装
Apr 08 Javascript
Vue-cli4 配置 element-ui 按需引入操作
Sep 11 Javascript
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
第一节--面向对象编程
2006/11/16 PHP
ThinkPHP中实例Model方法的区别说明
2010/08/21 PHP
浅析get与post的一些特殊情况
2014/07/28 PHP
使用PHP把HTML生成PDF文件的几个开源项目介绍
2014/11/17 PHP
Yii2验证器(Validator)用法分析
2016/07/23 PHP
php图片合成方法(多张图片合成一张)
2017/11/25 PHP
php解决crontab定时任务不能写入文件问题的方法分析
2019/09/16 PHP
对javascript的一点点认识总结《javascript高级程序设计》读书笔记
2011/11/30 Javascript
JQuery Highcharts 动态生成图表的方法
2013/11/15 Javascript
纯JavaScript实现的兼容各浏览器的添加和移除事件封装
2015/03/28 Javascript
微信小程序 location API实例详解
2016/10/02 Javascript
js仿拉勾网首页穿墙广告效果
2017/03/08 Javascript
微信小程序 跳转传参数与传对象详解及实例代码
2017/03/14 Javascript
详解angular中通过$location获取路径(参数)的写法
2017/03/21 Javascript
js canvas实现简单的图像扩散效果
2020/06/28 Javascript
vue中eventbus被多次触发以及踩过的坑
2017/12/02 Javascript
vue2中使用less简易教程
2018/03/27 Javascript
前端Electron新手入门教程详解
2019/06/21 Javascript
微信小程序实现上传图片裁剪图片过程解析
2019/08/22 Javascript
使用python装饰器验证配置文件示例
2014/02/24 Python
在Python的一段程序中如何使用多次事件循环详解
2017/09/07 Python
python 删除指定时间间隔之前的文件实例
2018/04/24 Python
[原创]Python入门教程5. 字典基本操作【定义、运算、常用函数】
2018/11/01 Python
简单易懂Pytorch实战实例VGG深度网络
2019/08/27 Python
如何在Python3中使用telnetlib模块连接网络设备
2020/09/21 Python
HTML5仿手机微信聊天界面
2016/03/18 HTML / CSS
英国简约舒适女装品牌:Great Plains
2018/07/27 全球购物
ASICS印度官方网站:日本专业运动品牌
2020/06/20 全球购物
求两个数的乘积和商数,该作用由宏定义来实现
2013/03/13 面试题
安全资金保障制度
2014/01/23 职场文书
热爱祖国的演讲稿
2014/05/04 职场文书
违反交通法规检讨书
2014/09/10 职场文书
房产协议书范本2014
2014/09/30 职场文书
师德师风事迹材料
2014/12/20 职场文书
给老师的感谢信
2015/01/20 职场文书
本溪水洞导游词
2015/02/11 职场文书