Javascript 如何在点击材质设计中产生涟漪效应
我是CSS动画新手,在过去的几个小时里,我一直试图通过查看他们的代码来让他们的动画工作,但现在我无法让它工作 我说的是这个效果:(菜单效果)。 基本上,这是一个点击动画,从鼠标光标开始传播一个圆 似乎可以归结为以下两行:Javascript 如何在点击材质设计中产生涟漪效应,javascript,jquery,html,css,Javascript,Jquery,Html,Css,我是CSS动画新手,在过去的几个小时里,我一直试图通过查看他们的代码来让他们的动画工作,但现在我无法让它工作 我说的是这个效果:(菜单效果)。 基本上,这是一个点击动画,从鼠标光标开始传播一个圆 似乎可以归结为以下两行: transition: box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1),-webkit-transform .4s cubic-bezier(.2
transition: box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1),-webkit-transform .4s cubic-bezier(.25,.8,.25,1);
transition: box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1),transform .4s cubic-bezier(.25,.8,.25,1);
PS:也许有一些jQuery我没有看到。这可以通过框阴影来实现。单击鼠标时,圆原点在鼠标下的定位需要JS
li{
字号:2em;
背景:rgba(51,51,254,0.8);
列表样式类型:无;
显示:内联块;
线高:2米;
宽度:6em;
文本对齐:居中;
颜色:#fff;
位置:相对位置;
溢出:隐藏;
}
a{color:#fff;}
a:以后{
内容:'';
位置:绝对位置;
边界半径:50%;
高度:10em;宽度:10em;
顶部:-4em;左侧:-2em;
盒影:嵌入0.5em rgba(255255,0.2);
过渡:框阴影0.8s;
}
a:焦点:之后{
盒影:嵌入0.0em rgba(255255255,0.2);
}
我以前在我的一些项目中使用过这种代码
使用jQuery,我们不仅可以将效果定位到静态,还可以添加span
元素onclick
。我添加了评论,因此更容易理解
jQuery
$("div").click(function (e) {
// Remove any old one
$(".ripple").remove();
// Setup
var posX = $(this).offset().left,
posY = $(this).offset().top,
buttonWidth = $(this).width(),
buttonHeight = $(this).height();
// Add the element
$(this).prepend("<span class='ripple'></span>");
// Make it round!
if(buttonWidth >= buttonHeight) {
buttonHeight = buttonWidth;
} else {
buttonWidth = buttonHeight;
}
// Get the center of the element
var x = e.pageX - posX - buttonWidth / 2;
var y = e.pageY - posY - buttonHeight / 2;
// Add the ripples CSS and start the animation
$(".ripple").css({
width: buttonWidth,
height: buttonHeight,
top: y + 'px',
left: x + 'px'
}).addClass("rippleEffect");
});
jQuery(function($) {
// MAD-RIPPLE // (jQ+CSS)
$(document).on("mousedown", "[data-ripple]", function(e) {
var $self = $(this);
if($self.is(".btn-disabled")) {
return;
}
if($self.closest("[data-ripple]")) {
e.stopPropagation();
}
var initPos = $self.css("position"),
offs = $self.offset(),
x = e.pageX - offs.left,
y = e.pageY - offs.top,
dia = Math.min(this.offsetHeight, this.offsetWidth, 100), // start diameter
$ripple = $('<div/>', {class : "ripple",appendTo : $self });
if(!initPos || initPos==="static") {
$self.css({position:"relative"});
}
$('<div/>', {
class : "rippleWave",
css : {
background: $self.data("ripple"),
width: dia,
height: dia,
left: x - (dia/2),
top: y - (dia/2),
},
appendTo : $ripple,
one : {
animationend : function(){
$ripple.remove();
}
}
});
});
});
你可以在的帮助下得到同样的效果,用它做起来很容易。你所要做的就是在你想要效果的地方添加一个类
<a href="#" class="btn waves-effect waves-light">Submit</a>
如果您想使用纯CSS,请检查以下代码:使用jQuery和CSS3打开它:材料设计中的涟漪效应
要产生UX涟漪效应,基本上您需要:
- 将
元素附加到任何元素,以包含涟漪圈(您不想改变原始元素溢出,也不想看到涟漪效应超出所需容器)oveflow:hidden
- 将波纹波半透明径向元素附加到溢出容器中
- 获取单击坐标和CSS3动画涟漪元素的缩放和不透明度
- 收听
事件并销毁ripple容器animationend
基本守则: 基本上,将
数据涟漪
(默认为白色涟漪)或数据涟漪=“#000”
添加到所需元素:
<a data-ripple> EDIT </a>
<div data-ripple="rgba(0,0,0, 0.3)">Lorem ipsum</div>
jQuery
$("div").click(function (e) {
// Remove any old one
$(".ripple").remove();
// Setup
var posX = $(this).offset().left,
posY = $(this).offset().top,
buttonWidth = $(this).width(),
buttonHeight = $(this).height();
// Add the element
$(this).prepend("<span class='ripple'></span>");
// Make it round!
if(buttonWidth >= buttonHeight) {
buttonHeight = buttonWidth;
} else {
buttonWidth = buttonHeight;
}
// Get the center of the element
var x = e.pageX - posX - buttonWidth / 2;
var y = e.pageY - posY - buttonHeight / 2;
// Add the ripples CSS and start the animation
$(".ripple").css({
width: buttonWidth,
height: buttonHeight,
top: y + 'px',
left: x + 'px'
}).addClass("rippleEffect");
});
jQuery(function($) {
// MAD-RIPPLE // (jQ+CSS)
$(document).on("mousedown", "[data-ripple]", function(e) {
var $self = $(this);
if($self.is(".btn-disabled")) {
return;
}
if($self.closest("[data-ripple]")) {
e.stopPropagation();
}
var initPos = $self.css("position"),
offs = $self.offset(),
x = e.pageX - offs.left,
y = e.pageY - offs.top,
dia = Math.min(this.offsetHeight, this.offsetWidth, 100), // start diameter
$ripple = $('<div/>', {class : "ripple",appendTo : $self });
if(!initPos || initPos==="static") {
$self.css({position:"relative"});
}
$('<div/>', {
class : "rippleWave",
css : {
background: $self.data("ripple"),
width: dia,
height: dia,
left: x - (dia/2),
top: y - (dia/2),
},
appendTo : $ripple,
one : {
animationend : function(){
$ripple.remove();
}
}
});
});
});
人员设置
点击涟漪
数据波动
数据涟漪=“rgba(0,0,0,0.4)”
我的同僚们,我的精英们,我的临时雇员
编辑
这里是一个只使用CSS的实现,即不需要javascript
资料来源:
正文{
背景:#fff;
}
钮扣{
位置:相对位置;
溢出:隐藏;
填充:16px 32px;
}
按钮:之后{
内容:'';
显示:块;
位置:绝对位置;
左:50%;
最高:50%;
宽度:120px;
高度:120px;
左边距:-60px;
利润上限:-60px;
背景#3f51b5;
边界半径:100%;
不透明度:.6;
变换:比例(0);
}
@关键帧波纹{
0% {
变换:比例(0);
}
20% {
变换:比例(1);
}
100% {
不透明度:0;
变换:比例(1);
}
}
按钮:不(:活动):之后{
动画:ripple 1s放松;
}
/*修复页面加载时无需用户输入的初始动画运行。
*/
按钮:之后{
可见性:隐藏;
}
按钮:焦点:之后{
能见度:可见;
}
按钮
实现javascript
+babel
-
@keyframes impulse {
from {
opacity: .3;
transform: scale(0);
}
to {
opacity: 0;
transform: scale(1);
}
}
<div class="impulse" data-color="#3f1dcb" data-active="false">
<div class="panel"></div>
</div>
let impulses = document.querySelectorAll('.impulse');
let impulseAll = Array.from( impulses );
impulseAll.forEach( Impulse.install );
javascript
-
class ImpulseStyleFactory {
static ANIMATION_DEFAULT_DURATION = 1;
static ANIMATION_DEFAULT_SIZE = 300;
static ANIMATION_RATIO = ImpulseStyleFactory.ANIMATION_DEFAULT_DURATION / ImpulseStyleFactory.ANIMATION_DEFAULT_SIZE;
static circleImpulseStyle( x, y, size, color = `#fff`, duration = 1 ){
return {
width: `${ size }px`,
height: `${ size }px`,
background: color,
borderRadius: `50%`,
display: `inline-block`,
pointerEvents: `none`,
position: `absolute`,
top: `${ y - size / 2 }px`,
left: `${ x - size / 2 }px`,
animation: `impulse ${ duration }s`,
};
}
}
class Impulse {
static service = new Impulse();
static install( container ) {
Impulse.service.containerRegister( container );
}
static destroy( container ){
Impulse.service.containerUnregister( container );
}
static applyToElement( {x, y}, container ){
Impulse.service.createImpulse( x, y, container );
}
constructor(){
this.impulse_clickHandler = this.impulse_clickHandler.bind(this);
this.impulse_animationEndHandler = this.impulse_animationEndHandler.bind(this);
this.actives = new Map();
}
containerRegister( container ){
container.addEventListener('click', this.impulse_clickHandler);
}
containerUnregister( container ){
container.removeEventListener('click', this.impulse_clickHandler);
}
createImpulse( x, y, container ){
let { clientWidth, clientHeight } = container;
let impulse = document.createElement('div');
impulse.addEventListener('animationend', this.impulse_animationEndHandler);
let size = Math.max( clientWidth, clientHeight ) * 2;
let color = container.dataset.color;
Object.assign(impulse.style, ImpulseStyleFactory.circleImpulseStyle(
x, y, size, color
));
if( this.actives.has( container ) ){
this.actives.get( container )
.add( impulse );
}else{
this.actives.set( container, new Set( [ impulse ] ) );
}
container.dataset.active = true;
container.appendChild( impulse );
}
impulse_clickHandler({ layerX, layerY, currentTarget: container }){
this.createImpulse( layerX, layerY, container );
}
impulse_animationEndHandler( {currentTarget: impulse} ){
let { parentNode: container } = impulse;
this.actives.get( container )
.delete( impulse );
if( ! this.actives.get( container ).size ){
this.actives.delete( container );
container.dataset.active = false;
}
container.removeChild(impulse);
}
}
css
-
@keyframes impulse {
from {
opacity: .3;
transform: scale(0);
}
to {
opacity: 0;
transform: scale(1);
}
}
<div class="impulse" data-color="#3f1dcb" data-active="false">
<div class="panel"></div>
</div>
let impulses = document.querySelectorAll('.impulse');
let impulseAll = Array.from( impulses );
impulseAll.forEach( Impulse.install );
使用该命令—
html
-
@keyframes impulse {
from {
opacity: .3;
transform: scale(0);
}
to {
opacity: 0;
transform: scale(1);
}
}
<div class="impulse" data-color="#3f1dcb" data-active="false">
<div class="panel"></div>
</div>
let impulses = document.querySelectorAll('.impulse');
let impulseAll = Array.from( impulses );
impulseAll.forEach( Impulse.install );
生命示例pulse.install
(pulse在单击的坐标中创建,添加处理程序事件单击
)-
类脉冲样式工厂{
静态动画\默认\持续时间=1;
静态动画\默认\大小=300;
静态动画\u比率=PulseStyleFactory.ANIMATION\u DEFAULT\u持续时间/PulseStyleFactory.ANIMATION\u DEFAULT\u大小;
静态循环脉冲样式(x,y,大小,颜色=`fff`,持续时间=1){
返回{
宽度:`${size}px`,
高度:`${size}px`,
背景:颜色,
边界半径:`50%`,
显示:`inline block`,
pointerEvents:`none`,
位置:`绝对',
顶部:`${y-size/2}px`,
左:`${x-size/2}px`,
动画:`Pulse${duration}s`,
};
}
}
阶级冲动{
静态服务=新脉冲();
静态安装(容器){
脉冲服务容器注册器(容器);
}
静态销毁(容器){
脉冲.服务.容器注册器(容器);
}
静态applyToElement({x,y},容器){
创建脉冲(x,y,容器);
}
构造函数(){
this.pulse\u clickHandler=this.pulse\u clickHandler.bind(this);
this.pulse\u animationEndHandler=this.pulse\u animationEndHandler.bind(this);
this.actives=新映射();
}
集装箱登记员(集装箱){
container.addEventListener('click',this.pulse\u clickHandler);
}
集装箱登记员(集装箱){
container.removeEventListener('click',this.pulse\u clickHandler);
}
createImpulse(x、y、容器){
设{clientWidth,clientHeight}=容器;
让pulse=document.createElement('div');
pulse.addEventListener('animationend',this.pulse\u animationEndHandler);
设size=Math.max(clientWidth,clientHeight)*2;
让color=container.dataset.color;
Object.assign(pulse.style,pulseStyleFactory.circleImpulseStyle(