Created
August 13, 2016 06:33
-
-
Save jrainlau/89a5a6e9c5d8bc8b05b75c5a6f19d286 to your computer and use it in GitHub Desktop.
ripple-effect
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Ripple</title> | |
<style> | |
.ripple-effect { | |
position: relative; | |
background-color: red; | |
} | |
.ripple { | |
display: inline-block; | |
position: absolute; | |
top: 0; | |
left: 0; | |
border-radius: 50%; | |
opacity: 0; | |
background-color: #000; | |
} | |
.ripple-container { | |
display: inline-block; | |
position: absolute; | |
top: 0; | |
left: 0; | |
overflow: hidden; | |
} | |
.ripple.is-animating { | |
transition: width .4s cubic-bezier(0, 0, 0.2, 1), height .4s cubic-bezier(0, 0, 0.2, 1), opacity 0.6s cubic-bezier(0, 0, 0.2, 1), -webkit-transform .4s cubic-bezier(0, 0, 0.2, 1); | |
transition: transform .4s cubic-bezier(0, 0, 0.2, 1), width .4s cubic-bezier(0, 0, 0.2, 1), height .4s cubic-bezier(0, 0, 0.2, 1), opacity 0.6s cubic-bezier(0, 0, 0.2, 1); | |
transition: transform .4s cubic-bezier(0, 0, 0.2, 1), width .4s cubic-bezier(0, 0, 0.2, 1), height .4s cubic-bezier(0, 0, 0.2, 1), opacity 0.6s cubic-bezier(0, 0, 0.2, 1), -webkit-transform .4s cubic-bezier(0, 0, 0.2, 1); } | |
} | |
</style> | |
</head> | |
<body> | |
<div class="ripple-effect" style="height: 50px;width: 100px;"></div> | |
<script> | |
(function () { | |
var utils = { | |
registerEventHandler: function (element, eventType, handler) { | |
if(element.addEventListener) { | |
element.addEventListener(eventType, handler, false) | |
} else if(element.attachEvent) { | |
element.addEventListener('on' + eventType, function (event) { | |
handler.call(element, event) | |
}) | |
} | |
}, | |
addClass: function (element, className) { | |
if(utils.hasClass(element, className)) return | |
element.className = (element.className || "") + " " + className | |
}, | |
removeClass: function (element, className) { | |
var names = (element.className || "").split(/\s+/) | |
var resultArray = [] | |
for(var i = 0, len = names.length;i < len;i++) { | |
if(names[i] !== className) resultArray.push(names[i]) | |
} | |
element.className = resultArray.join(' ') | |
}, | |
hasClass: function (element, className) { | |
var currentClassNames = (element.className || "").split(/\s+/) | |
return utils.arrayIndexOf(currentClassNames, className) >= 0 ? true : false | |
}, | |
arrayIndexOf: function (array, item) { | |
if(typeof array.indexOf === 'function') { | |
return array.indexOf(item) | |
} else { | |
for(var i = 0, len = array.length;i < len;i++) { | |
if(array[i] === item) { | |
return i | |
} | |
} | |
} | |
return -1 | |
}, | |
reqAnimate: function (animate) { | |
return window.requestAnimationFrame(animate) || window.mozRequestAnimationFrame(animate) || window.webkitRequestAnimationFrame(animate) || window.msRequestAnimationFrame(animate) || window.setTimeout(animate, 1000/60) | |
} | |
} | |
var rippleClassName = 'ripple-effect' | |
function Ripple(element) { | |
if(!(this instanceof Ripple)) { | |
return new Ripple(element) | |
} | |
this._ele = element | |
this.init() | |
} | |
Ripple._Const = { | |
FRAME_COUNT: 1 | |
} | |
Ripple.prototype.init = function () { | |
this._rippleContainer = document.createElement('span')// 有overflow hidden的样式,控制波纹的边界 | |
this._rippleElement = document.createElement('span')// 波纹 | |
utils.addClass(this._rippleContainer, 'ripple-container') | |
utils.addClass(this._rippleElement, 'ripple') | |
this._rippleContainer.appendChild(this._rippleElement) | |
this._ele.appendChild(this._rippleContainer) | |
this._frameCount = Ripple._Const.FRAME_COUNT// 控制点击之后在哪个刷新周期内产生波纹 | |
utils.registerEventHandler(this._ele, 'mousedown', this.downHandler.bind(this)) | |
utils.registerEventHandler(this._ele, 'mouseup', this.upHandler.bind(this)) | |
} | |
Ripple.prototype.downHandler = function (e) { | |
this.initRipple(e) | |
this.startRipple() | |
} | |
Ripple.prototype.upHandler = function (e) { | |
this._rippleElement.style.opacity = '0' | |
} | |
/** | |
* 初始化位置,大小 | |
**/ | |
Ripple.prototype.initRipple = function (e) { | |
var rect, x, y, scaleStr, radius | |
rect = this._ele.getBoundingClientRect() | |
x = e.clientX - rect.left, | |
y = e.clientY - rect.top | |
this._offset = 'translate(' + x + 'px, ' + y + 'px)' | |
radius = Math.sqrt(rect.width*rect.width + rect.height*rect.height) | |
scaleStr = 'scale(0.001, 0.001)' | |
var transformStr = this._offset + ' translate(-50%, -50%)' + ' ' + scaleStr | |
this._rippleElement.style.width = radius*2 + 'px' | |
this._rippleElement.style.height = radius*2 + 'px' | |
this._rippleElement.style.transform = transformStr | |
this._rippleElement.style.msTransform = transformStr | |
this._rippleElement.style.mozTransform = transformStr | |
this._rippleElement.style.opacity = '0.4' | |
utils.removeClass(this._rippleElement, 'is-animating') | |
this._rippleContainer.style.width = rect.width + 'px' | |
this._rippleContainer.style.height = rect.height + 'px' | |
} | |
Ripple.prototype.startRipple = function () { | |
this.animationHandler = function () { | |
if(this._frameCount-- > 0) { | |
utils.reqAnimate(this.animationHandler.bind(this)) | |
} else { | |
// 开始动画 | |
var transformStr = this._offset + ' translate(-50%, -50%)' + ' ' + 'scale(1, 1)' | |
this._rippleElement.style.transform = transformStr | |
this._rippleElement.style.msTransform = transformStr | |
this._rippleElement.style.transform = transformStr | |
utils.addClass(this._rippleElement, 'is-animating') | |
this._frameCount = Ripple._Const.FRAME_COUNT | |
} | |
}; | |
this.animationHandler.bind(this)() | |
} | |
function upgradeElements() { | |
var eles = document.querySelectorAll('.' + rippleClassName) | |
for(var i = 0, len = eles.length; i < len; i++) { | |
Ripple(eles[i]) | |
} | |
} | |
utils.registerEventHandler(window, 'load', function () { | |
upgradeElements() | |
}) | |
})() | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment