-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathripple.js
More file actions
151 lines (126 loc) · 6.25 KB
/
ripple.js
File metadata and controls
151 lines (126 loc) · 6.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
var Ripple = {
bind: function(el, binding){
// Default values.
var props = {
event: 'mousedown',
transition: 600
};
setProps(Object.keys(binding.modifiers),props);
el.addEventListener(props.event, function(event) {
rippler(event, el, binding.value);
});
var bg = binding.value || Ripple.color || 'rgba(0, 0, 0, 0.35)';
var zIndex = Ripple.zIndex || '9999';
function rippler(event, el) {
var target = el;
// Get border to avoid offsetting on ripple container position
var targetBorder = parseInt((getComputedStyle(target).borderWidth).replace('px', ''));
// Get necessary variables
var rect = target.getBoundingClientRect(),
left = rect.left,
top = rect.top,
width = target.offsetWidth,
height = target.offsetHeight,
dx = event.clientX - left,
dy = event.clientY - top,
maxX = Math.max(dx, width - dx),
maxY = Math.max(dy, height - dy),
style = window.getComputedStyle(target),
radius = Math.sqrt((maxX * maxX) + (maxY * maxY)),
border = (targetBorder > 0 ) ? targetBorder : 0;
// Create the ripple and its container
var ripple = document.createElement("div"),
rippleContainer = document.createElement("div");
rippleContainer.className = 'ripple-container';
ripple.className = 'ripple';
//Styles for ripple
ripple.style.marginTop= '0px';
ripple.style.marginLeft= '0px';
ripple.style.width= '1px';
ripple.style.height= '1px';
ripple.style.transition= 'all ' + props.transition + 'ms cubic-bezier(0.4, 0, 0.2, 1)';
ripple.style.borderRadius= '50%';
ripple.style.pointerEvents= 'none';
ripple.style.position= 'relative';
ripple.style.zIndex= zIndex;
ripple.style.backgroundColor = bg;
//Styles for rippleContainer
rippleContainer.style.position= 'absolute';
rippleContainer.style.left = 0 - border + 'px';
rippleContainer.style.top = 0 - border + 'px';
rippleContainer.style.height = '0';
rippleContainer.style.width = '0';
rippleContainer.style.pointerEvents = 'none';
rippleContainer.style.overflow = 'hidden';
// Store target position to change it after
var storedTargetPosition = ((target.style.position).length > 0) ? target.style.position : getComputedStyle(target).position;
// Change target position to relative to guarantee ripples correct positioning
if (storedTargetPosition !== 'relative') {
target.style.position = 'relative';
}
rippleContainer.appendChild(ripple);
target.appendChild(rippleContainer);
ripple.style.marginLeft = dx + "px";
ripple.style.marginTop = dy + "px";
// No need to set positioning because ripple should be child of target and to it's relative position.
// rippleContainer.style.left = left + (((window.pageXOffset || document.scrollLeft) - (document.clientLeft || 0)) || 0) + "px";
// rippleContainer.style.top = top + (((window.pageYOffset || document.scrollTop) - (document.clientTop || 0)) || 0) + "px";
rippleContainer.style.width = width + "px";
rippleContainer.style.height = height + "px";
rippleContainer.style.borderTopLeftRadius = style.borderTopLeftRadius;
rippleContainer.style.borderTopRightRadius = style.borderTopRightRadius;
rippleContainer.style.borderBottomLeftRadius = style.borderBottomLeftRadius;
rippleContainer.style.borderBottomRightRadius = style.borderBottomRightRadius;
rippleContainer.style.direction = 'ltr';
setTimeout(function() {
ripple.style.width = radius * 2 + "px";
ripple.style.height = radius * 2 + "px";
ripple.style.marginLeft = dx - radius + "px";
ripple.style.marginTop = dy - radius + "px";
}, 0);
function clearRipple() {
setTimeout(function() {
ripple.style.backgroundColor = "rgba(0, 0, 0, 0)";
}, 250);
// Timeout set to get a smooth removal of the ripple
setTimeout(function() {
rippleContainer.parentNode.removeChild(rippleContainer);
}, 850);
el.removeEventListener('mouseup', clearRipple, false);
el.removeEventListener('dragstart', clearRipple, false);
// After removing event set position to target to it's original one
// Timeout it's needed to avoid jerky effect of ripple jumping out parent target
setTimeout(function () {
var clearPosition = true;
for(var i = 0; i < target.childNodes.length; i++) {
if(target.childNodes[i].className === 'ripple-container') {
clearPosition = false;
}
}
if(clearPosition) {
if(storedTargetPosition !== 'static') {
target.style.position = storedTargetPosition;
} else {
target.style.position = '';
}
}
}, props.transition + 250)
}
if(event.type === 'mousedown') {
el.addEventListener('mouseup', clearRipple, false);
el.addEventListener('dragstart', clearRipple, false);
} else {
clearRipple();
}
}
}
};
function setProps(modifiers,props) {
modifiers.forEach(function(item) {
if(isNaN(Number(item)))
props.event = item;
else
props.transition = item;
});
}
export default Ripple;