mirror of
https://github.com/mdbootstrap/mdb-ui-kit.git
synced 2024-11-25 19:14:09 +03:00
Rewritten ripples effect, now is standalone.
The ripples effect provided by some jQuery spaghetti now is a standalone plain javascript script, there was some improvements with this new version, for example now multiple ripples are possible.
This commit is contained in:
parent
1a4277d0cd
commit
1023f8f6f9
|
@ -70,12 +70,17 @@ Remember to use the proper HTML markup to get radio and checkboxes styled correc
|
||||||
|
|
||||||
# Plugins
|
# Plugins
|
||||||
|
|
||||||
Material Design for Bootstrap comes with styling support for various Bootstrap plugins, at the moment only one plugin is supported but others will come:
|
Material Design for Bootstrap comes with styling support for various external scripts, at the moment only two scripts are supported but others will come:
|
||||||
|
|
||||||
### SnackbarJS
|
### SnackbarJS
|
||||||
|
|
||||||
Create snackbars and toasts with [SnackbarJS plugin](https://github.com/FezVrasta/snackbarjs), the default toast style is the squared one (snackbar style), if you like to use the rounded style (toast style) please add the `toast` class to the `style` option of SnackbarJS.
|
Create snackbars and toasts with [SnackbarJS plugin](https://github.com/FezVrasta/snackbarjs), the default toast style is the squared one (snackbar style), if you like to use the rounded style (toast style) please add the `toast` class to the `style` option of SnackbarJS.
|
||||||
|
|
||||||
|
### RipplesJS
|
||||||
|
|
||||||
|
This is part of Material Design for Bootstrap project and is a plain Javascript script which creates the ripple effect on click of the defined elements.
|
||||||
|
At the moment RipplesJS has not an own repository but probably in future it will have one.
|
||||||
|
|
||||||
|
|
||||||
# Compatibility
|
# Compatibility
|
||||||
|
|
||||||
|
|
|
@ -315,44 +315,6 @@ h6,
|
||||||
.btn-group-flat {
|
.btn-group-flat {
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
.ripple-wrapper {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 1;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
.ripple {
|
|
||||||
position: absolute;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
margin-left: -10px;
|
|
||||||
margin-top: -10px;
|
|
||||||
border-radius: 100%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.05);
|
|
||||||
-webkit-transform: scale(1);
|
|
||||||
-ms-transform: scale(1);
|
|
||||||
transform: scale(1);
|
|
||||||
-webkit-transform-origin: 50%;
|
|
||||||
-ms-transform-origin: 50%;
|
|
||||||
transform-origin: 50%;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.ripple.ripple-on {
|
|
||||||
-webkit-transition: opacity 0.15s ease-in 0s, -webkit-transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
|
|
||||||
-ms-transition: opacity 0.15s ease-in 0s, -ms-transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
|
|
||||||
-moz-transition: opacity 0.15s ease-in 0s, -moz-transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
|
|
||||||
transition: opacity 0.15s ease-in 0s, transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
.ripple.ripple-out {
|
|
||||||
-webkit-transition: opacity 1s linear 0s !important;
|
|
||||||
transition: opacity 0.8s linear 0s !important;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.form-horizontal .checkbox {
|
.form-horizontal .checkbox {
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
42
css-compiled/ripples.css
Normal file
42
css-compiled/ripples.css
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* Generated by less 1.7.0 */
|
||||||
|
.withripple {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.ripple-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.ripple {
|
||||||
|
position: absolute;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-left: -10px;
|
||||||
|
margin-top: -10px;
|
||||||
|
border-radius: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
-ms-transform: scale(1);
|
||||||
|
transform: scale(1);
|
||||||
|
-webkit-transform-origin: 50%;
|
||||||
|
-ms-transform-origin: 50%;
|
||||||
|
transform-origin: 50%;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.ripple.ripple-on {
|
||||||
|
-webkit-transition: opacity 0.15s ease-in 0s, -webkit-transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
|
||||||
|
-ms-transition: opacity 0.15s ease-in 0s, -ms-transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
|
||||||
|
-moz-transition: opacity 0.15s ease-in 0s, -moz-transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
|
||||||
|
transition: opacity 0.15s ease-in 0s, transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.ripple.ripple-out {
|
||||||
|
-webkit-transition: opacity 1s linear 0s !important;
|
||||||
|
transition: opacity 0.8s linear 0s !important;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
|
@ -26,9 +26,6 @@ body, h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
|
||||||
// Buttons
|
// Buttons
|
||||||
@import "buttons.less";
|
@import "buttons.less";
|
||||||
|
|
||||||
// Ripple effect
|
|
||||||
@import "ripple.less";
|
|
||||||
|
|
||||||
// Checkboxes
|
// Checkboxes
|
||||||
@import "checkboxes.less";
|
@import "checkboxes.less";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
// main: material.less
|
// out: ../css-compiled/ripples.css
|
||||||
|
|
||||||
|
.withripple {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
.ripple-wrapper {
|
.ripple-wrapper {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
|
@ -1,9 +1,8 @@
|
||||||
$(function (){
|
/* globals ripples */
|
||||||
// with ripple elements
|
|
||||||
var withRipple = ".btn:not('.btn-link'), .navbar a, .nav-tabs a";
|
|
||||||
|
|
||||||
// Add ripple elements to material buttons
|
$(function (){
|
||||||
$(withRipple).append("<div class=ripple-wrapper><div class=ripple></div></div>");
|
|
||||||
|
ripples.init(".btn:not(.btn-link), .navbar a, .nav-tabs a, .withripple");
|
||||||
|
|
||||||
// Add fake-checkbox to material checkboxes
|
// Add fake-checkbox to material checkboxes
|
||||||
$(".checkbox label input").after("<span class=ripple></span><span class=check></span><span class=box></span>");
|
$(".checkbox label input").after("<span class=ripple></span><span class=check></span><span class=box></span>");
|
||||||
|
@ -25,74 +24,6 @@ $(function (){
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
var mouseDown = false;
|
|
||||||
$(document).mousedown(function() {
|
|
||||||
mouseDown = true;
|
|
||||||
}).mouseup(function() {
|
|
||||||
mouseDown = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Material buttons engine
|
|
||||||
$(document).on("mousedown", withRipple, function(e){
|
|
||||||
// Cache elements
|
|
||||||
var $self = $(this),
|
|
||||||
$rippleWrapper = $self.find(".ripple-wrapper"),
|
|
||||||
$ripple = $self.find(".ripple");
|
|
||||||
|
|
||||||
// Remove previous animation
|
|
||||||
$ripple.attr("class", "ripple");
|
|
||||||
$rippleWrapper.stop(true, true);
|
|
||||||
|
|
||||||
// Get mouse position
|
|
||||||
var parentOffset = $self.offset();
|
|
||||||
var relX = e.pageX - parentOffset.left;
|
|
||||||
var relY = e.pageY - parentOffset.top;
|
|
||||||
|
|
||||||
// Move ripple to the click position
|
|
||||||
$ripple.attr({"style": "top: " + relY + "px; left:" + relX + "px"});
|
|
||||||
|
|
||||||
// Start the animation
|
|
||||||
$rippleWrapper.attr("class", "ripple-wrapper").data("animating", true);
|
|
||||||
var scaleVal = "scale(" + Math.round($rippleWrapper.width() / 10) + ")";
|
|
||||||
$ripple.attr("class", "ripple ripple-on").css({
|
|
||||||
"-ms-transform": scaleVal,
|
|
||||||
"-moz-transform": scaleVal,
|
|
||||||
"-webkit-transform": scaleVal,
|
|
||||||
"transform": scaleVal
|
|
||||||
});
|
|
||||||
setTimeout(function() {
|
|
||||||
$rippleWrapper.attr("class", "ripple-wrapper").data("animating", false).trigger("rippleEnd");
|
|
||||||
}, 500);
|
|
||||||
})
|
|
||||||
.on("rippleEnd", withRipple, function() {
|
|
||||||
if (!mouseDown) {
|
|
||||||
var $self = $(this),
|
|
||||||
$rippleWrapper = $self.find(".ripple-wrapper"),
|
|
||||||
$ripple = $self.find(".ripple");
|
|
||||||
|
|
||||||
rippleOut($ripple, $rippleWrapper);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.on("mouseup mouseleave", withRipple, function() {
|
|
||||||
var $self = $(this),
|
|
||||||
$rippleWrapper = $self.find(".ripple-wrapper"),
|
|
||||||
$ripple = $self.find(".ripple");
|
|
||||||
|
|
||||||
if (!$rippleWrapper.data("animating")) {
|
|
||||||
rippleOut($ripple, $rippleWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
var rippleOut = function($ripple, $rippleWrapper) {
|
|
||||||
$ripple.attr("class", "ripple ripple-on ripple-out");
|
|
||||||
$rippleWrapper.fadeOut(800, function() {
|
|
||||||
$rippleWrapper.attr("class", "ripple-wrapper").attr("style", "");
|
|
||||||
$ripple.attr("class", "ripple").attr("style", "");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Material inputs engine (ripple effect)
|
// Material inputs engine (ripple effect)
|
||||||
$(document).on("click", ".checkbox label, .radio label", function() {
|
$(document).on("click", ".checkbox label, .radio label", function() {
|
||||||
var $ripple = $(this).find(".ripple"),
|
var $ripple = $(this).find(".ripple"),
|
||||||
|
|
110
scripts/ripples.js
Normal file
110
scripts/ripples.js
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/* globals CustomEvent */
|
||||||
|
var ripples = {
|
||||||
|
init : function(withRipple) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Helper to bind events on dynamically created elements
|
||||||
|
var bind = function(event, selector, callback) {
|
||||||
|
document.addEventListener(event, function(e) {
|
||||||
|
var target = (typeof e.detail !== "number") ? e.detail : e.target;
|
||||||
|
|
||||||
|
if (target.matches(selector)) {
|
||||||
|
callback(e, target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var rippleStart = function(e, target) {
|
||||||
|
|
||||||
|
// Init variables
|
||||||
|
var $rippleWrapper = (target.matches(".ripple-wrapper")) ? target : target.parentNode,
|
||||||
|
$el = $rippleWrapper.parentNode,
|
||||||
|
$ripple = document.createElement("div"),
|
||||||
|
elPos = $el.getBoundingClientRect(),
|
||||||
|
mousePos = {x: e.clientX - elPos.left, y: e.clientY - elPos.top},
|
||||||
|
scale = "transform:scale(" + Math.round($rippleWrapper.offsetWidth / 5) + ")",
|
||||||
|
rippleEnd = new CustomEvent("rippleEnd", {detail: $ripple}),
|
||||||
|
refreshElementStyle;
|
||||||
|
|
||||||
|
// Set ripple class
|
||||||
|
$ripple.className = "ripple";
|
||||||
|
|
||||||
|
// Move ripple to the mouse position
|
||||||
|
$ripple.setAttribute("style", "left:" + mousePos.x + "px; top:" + mousePos.y + "px;");
|
||||||
|
|
||||||
|
// Insert new ripple into ripple wrapper
|
||||||
|
$rippleWrapper.appendChild($ripple);
|
||||||
|
|
||||||
|
// Make sure the ripple has the class applied (ugly hack but it works)
|
||||||
|
refreshElementStyle = window.getComputedStyle($ripple).opacity;
|
||||||
|
|
||||||
|
// Let other funtions know that this element is animating
|
||||||
|
$ripple.dataset.animating = 1;
|
||||||
|
|
||||||
|
// Set scale value to ripple and animate it
|
||||||
|
$ripple.className = "ripple ripple-on";
|
||||||
|
$ripple.setAttribute("style", $ripple.getAttribute("style") + ["-ms-" + scale,"-moz-" + scale,"-webkit-" + scale,scale].join(";"));
|
||||||
|
|
||||||
|
// This function is called when the animation is finished
|
||||||
|
setTimeout(function() {
|
||||||
|
|
||||||
|
// Let know to other functions that this element has finished the animation
|
||||||
|
$ripple.dataset.animating = 0;
|
||||||
|
document.dispatchEvent(rippleEnd);
|
||||||
|
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var rippleOut = function($ripple) {
|
||||||
|
// Clear previous animation
|
||||||
|
$ripple.className = "ripple ripple-on ripple-out";
|
||||||
|
|
||||||
|
// Let ripple fade out (with CSS)
|
||||||
|
setTimeout(function() {
|
||||||
|
$ripple.remove();
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper, need to know if mouse is up or down
|
||||||
|
var mouseDown = false;
|
||||||
|
document.body.onmousedown = function() {
|
||||||
|
mouseDown = true;
|
||||||
|
};
|
||||||
|
document.body.onmouseup = function() {
|
||||||
|
mouseDown = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Append ripple wrapper if not exists already
|
||||||
|
var rippleInit = function(e, target) {
|
||||||
|
|
||||||
|
if (target.getElementsByClassName("ripple-wrapper").length === 0) {
|
||||||
|
target.className += " withripple";
|
||||||
|
var $rippleWrapper = document.createElement("div");
|
||||||
|
$rippleWrapper.className = "ripple-wrapper";
|
||||||
|
target.appendChild($rippleWrapper);
|
||||||
|
rippleStart(e, $rippleWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Events handler
|
||||||
|
// init RippleJS and start ripple effect on mousedown
|
||||||
|
bind("mousedown", withRipple, rippleInit);
|
||||||
|
// start ripple effect on mousedown
|
||||||
|
bind("mousedown", ".ripple-wrapper, .ripple", rippleStart);
|
||||||
|
// if animation ends and user is not holding mouse then destroy the ripple
|
||||||
|
bind("rippleEnd", ".ripple-wrapper, .ripple", function(e, $ripple) {
|
||||||
|
if (!mouseDown) {
|
||||||
|
rippleOut($ripple);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Destroy ripple when mouse is not holded anymore if the ripple still exists
|
||||||
|
bind("mouseup", ".ripple-wrapper, .ripple", function(e, $ripple) {
|
||||||
|
if ($ripple.dataset.animating != 1) {
|
||||||
|
rippleOut($ripple);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user