\#0 你看,这漂亮的动画!
点击涟漪动画太棒啦!
为了练手,我突然就想自己用原生方法实现一个简单的.
来,让我们一起开始动手写一个.
\#1 先来一个按钮
先创建一个按钮:
<button id="clickme" class="my-btn">Click Me</button>
写一些样式:
clickme-2.my-btn{
background-color: #e91e63;border: none;color: white;padding: 10px 14px 8px 14px;border-radius: 2px;font-weight: 500;text-transform: uppercase;}
<button id="clickme" class="my-btn">Click Me</button>
<style>
.my-btn{
background-color: #e91e63;
border: none;
color: white;
padding: 10px 14px 8px 14px;
border-radius: 2px;
font-weight: 500;
text-transform: uppercase;
}
</style>
好了,简单的按钮创建好了.
\#2 涟漪开始!
先造一个涟漪:
<div class="ripple-wave" style="width:50px;height:50px"></div>
<style>
.ripple-wave {
position: absolute;
border-radius: 50%;
display: block;
background-color: black;
transition-duration: 3s;
opacity: 0.3;
transform: scale(1);
transition-property: transform, opacity;
pointer-events: none;
}
</style>
放进按钮里,顺便做一些调整:
clickme-3.my-btn{background-color: #e91e63;border: none;color: white;padding: 10px 14px 8px 14px;border-radius: 2px;font-weight: 500;text-transform: uppercase;}#test-2.ripple-wave {position: absolute;border-radius: 50%;display: block;background-color: white;transition-duration: 3s;opacity: 0.3;transform: scale(1);transition-property: transform, opacity;pointer-events: none;}#clickme-3.ripple{overflow:hidden;position:relative;outline:none;}
<button id="clickme" class="my-btn ripple"><div class="ripple-wave" style="width:50px;height:50px"></div>Click Me</button>
<style>
.my-btn{
background-color: #e91e63;
border: none;
color: white;
padding: 10px 14px 8px 14px;
border-radius: 2px;
font-weight: 500;
text-transform: uppercase;
}
.ripple{
overflow:hidden;
outline:none;
position:relative;
}
.ripple-wave {
position: absolute;
border-radius: 50%;
display: block;
background-color: black;
transition-duration: 3s;
opacity: 0.3;
transform: scale(1);
transition-property: transform, opacity;
pointer-events: none;
}
</style>
什么调整?
由于需要将涟漪在按钮内进行绝对定位,所以设置按钮为相对定位:position:relative;
.
同时为了放在涟漪溢出按钮,所以设置overflow:hidden
.
顺便把涟漪改成白色.
\#3 接下来?
接下来不得不让JavaScript介入了.
首先看看我们理想中的效果:
那就分成3个过程:
- 按下时在鼠标指针下创建涟漪,使其缓慢扩散.
- 松手时使涟漪快速扩散,并让其过渡消失.
- 过渡消失后移除涟漪元素.
\#4 涟漪开始! (JavaScript.ver)
JavaScript:
let createWaveHandler = (e)=>{
// 获得目标元素
let target = e.target;
// 创建空div
let wave = document.createElement("div");
// 计算涟漪的宽高,应为目标元素的最长边
let wh = (target.offsetWidth > e.srcElement.offsetHeight ? e.srcElement.offsetWidth.toString() : e.srcElement.offsetHeight.toString()) + "px"
// 计算涟漪位置
let x = (e.offsetX - parseInt(wh) / 2).toString() + "px";
let y = (e.offsetY - parseInt(wh) / 2).toString() + "px";
// 设置涟漪属性
wave.classList.add("ripple-wave");
wave.style.top = y;
wave.style.left = x;
wave.style.height = wh;
wave.style.width = wh;
// 将涟漪放入目标元素
target.appendChild(wave);
// 异步设置涟漪扩张属性,使其以动画方式展现
// 直接设置会使过渡动画无法展示
setTimeout(() => {
wave.style.transform = "scale(3)"
});
}
CSS:
.ripple-wave {
position: absolute;
border-radius: 50%;
display: block;
background-color: white;
/* 低速动画 */
transition-duration: 3s;
opacity: 0.3;
/* 开局隐藏 */
transform: scale(0);
transition-property: transform, opacity;
/* 防止触发事件 */
pointer-events: none;
}
\#5 涟漪退散!
JavaScript:
let removeWaveHandler = (e) =>{
let target = e.target;
target.childNodes.forEach((v) => {
if (v.nodeName == "DIV" && v.classList.contains("ripple-wave")) {
v.classList.add("ripple-wave-end");
setTimeout(() => {
v.remove();
}, 1000);
}
})
}
CSS:
.ripple-wave.ripple-wave-end {
/* 淡出 */
opacity: 0;
/* 使变大动画加速溢出 */
transform: scale(5)!important;
/* 高速动画 */
transition-duration: 1s;
}
\#6 收尾!
document.getElementById("clickme").addEventListener("mousedown",createWaveHandler);
document.getElementById("clickme").addEventListener("mouseup",removeWaveHandler);
\#7 然后?
看成品!
<button id="clickme" class="my-btn ripple">Click Me</button>
<style>
.my-btn {
background-color:
#e91e63;
border: none;
color: white;
padding: 10px 14px 8px 14px;
border-radius: 2px;
font-weight: 500;
text-transform: uppercase;
}
.ripple {
overflow: hidden;
position: relative;
outline: none;
}
.ripple-wave {
position: absolute;
border-radius: 50%;
display: block;
background-color: white;
transition-duration: 3s;
opacity: 0.3;
transform: scale(0);
transition-property: transform, opacity;
pointer-events: none;
}
.ripple-wave.ripple-wave-end {
opacity: 0;
transform: scale(5) !important;
transition-duration: 1s;
}
</style>
<script>
let createWaveHandler = (e) => {
let target = e.target;
let wave = document.createElement("div");
let wh = (target.offsetWidth > e.srcElement.offsetHeight ? e.srcElement.offsetWidth.toString() : e
.srcElement.offsetHeight.toString()) + "px"
let x = (e.offsetX - parseInt(wh) / 2).toString() + "px";
let y = (e.offsetY - parseInt(wh) / 2).toString() + "px";
wave.classList.add("ripple-wave");
wave.style.top = y;
wave.style.left = x;
wave.style.height = wh;
wave.style.width = wh;
target.appendChild(wave);
setTimeout(() => {
wave.style.transform = "scale(3)"
});
}
let removeWaveHandler = (e) => {
let target = e.target;
target.childNodes.forEach((v) => {
if (v.nodeName == "DIV" && v.classList.contains("ripple-wave")) {
v.classList.add("ripple-wave-end");
setTimeout(() => {
v.remove();
}, 1000)
}
})
}
document.getElementById("clickme").addEventListener("mousedown", createWaveHandler);
document.getElementById("clickme").addEventListener("mouseup", removeWaveHandler);
</script>
HB!!