Last active
August 5, 2016 15:16
-
-
Save JounQin/50b8310a14b9215126f420cbab4785a6 to your computer and use it in GitHub Desktop.
基于 jQuery 使用 transform(translate) 进行拖拽,附赠一个随机倒数的功能
This file contains 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
/** | |
* Created by JounQin on 16/6/2. | |
*/ | |
+function ($) { | |
function trueType(input) { | |
var output = Object.prototype.toString.call(input); | |
return output.substring(8, output.length - 1); | |
} | |
$.each(['Object', 'Array', 'Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Null', 'Undefined'], function (index, value) { | |
$['is' + value] = function (input) { | |
return trueType(input) === value; | |
} | |
}); | |
+function () { | |
var EVENTS = [{ | |
start: 'mousedown', | |
move: 'mousemove', | |
end: 'mouseup' | |
}, { | |
start: 'touchstart', | |
move: 'touchmove', | |
end: 'touchend' | |
}], | |
touchSupport = !!(('ontouchstart' in window && | |
navigator.userAgent.toLowerCase().match(/mobile|tablet/)) || | |
(window.DocumentTouch && document instanceof window.DocumentTouch) || | |
(window.navigator['msPointerEnabled'] && | |
window.navigator['msMaxTouchPoints'] > 0) || //IE 10 | |
(window.navigator['pointerEnabled'] && | |
window.navigator['maxTouchPoints'] > 0) || //IE >=11 | |
false); | |
$.EVENT = EVENTS[+touchSupport]; | |
$.extend({ | |
touchSupport: touchSupport, | |
originalEvent: function (e) { | |
return touchSupport ? e.originalEvent.changedTouches[0] : e.originalEvent; | |
} | |
}); | |
}(); | |
$.fn.extend({ | |
translate: function (x, y, z) { | |
var argv = arguments; | |
if (this.length > 1) { | |
return this.each(function () { | |
var $this = $(this); | |
$this.translate.apply($this, argv); | |
}); | |
} | |
var args; | |
if (argv.length === 1 && x !== null && $.isObject(x) && (args = x)) { | |
x = args.x; | |
y = args.y; | |
z = args.z; | |
} | |
var translate = this.getTranslate3d(); | |
null == x || (translate.x = x); | |
null == y || (translate.y = y); | |
null == z || (translate.z = z); | |
return this.css({ | |
transform: 'translate3d(' + translate.x + 'px,' + translate.y + 'px,' + translate.z + 'px)' | |
}); | |
}, | |
getTranslate: function () { | |
var matrix = this.css('transform'); | |
if (!matrix.indexOf('matrix3d')) { | |
var translate = this.getTranslate3d(); | |
return { | |
x: translate.x, | |
y: translate.y | |
}; | |
} else if (-1 === matrix.indexOf('matrix')) { | |
return {x: 0, y: 0}; | |
} | |
var matrixArr = matrix.substring(7, matrix.length - 1).split(','); | |
return { | |
x: +matrixArr[4], | |
y: +matrixArr[5] | |
} | |
}, | |
getTranslate3d: function () { | |
var matrix = this.css('transform'); | |
if (-1 === matrix.indexOf('matrix3d')) { | |
return $.extend({z: 0}, this.getTranslate()); | |
} | |
var matrixArr = matrix.substring(9, matrix.length - 1).split(','); | |
return { | |
x: +matrixArr[12], | |
y: +matrixArr[13], | |
z: +matrixArr[14] | |
} | |
}, | |
moveTranslate: function () { | |
var DEFAULT_OPTIONS = { | |
x: true, | |
y: true, | |
start: $.EVENT.start, | |
move: $.EVENT.move, | |
end: $.EVENT.end + ' mouseleave', | |
speed: 1, | |
events: {} | |
}, | |
$document = $(document); | |
return function (options) { | |
var len = this.length; | |
if (!len) return this; | |
if (len > 1) return this.each(function () { | |
$(this).moveTranslate(options); | |
}); | |
var target = this[0], | |
$el = $.touchSupport ? this : $document; | |
if (target === document || target === window) throw new Error('should not use this function on document or window!'); | |
if ('destroy' === options || options && options.destroy) { | |
$el.off(target.move, target.eMove); | |
$el.off(target.end, target.eEnd); | |
return this.off(target.start, target.eStart); | |
} | |
options = $.extend({}, DEFAULT_OPTIONS, options); | |
var self = this, | |
events = options.events, | |
eventParam = { | |
relatedTarget: target | |
}, | |
wrapEvent = function (e, params) { | |
return $.extend(e, eventParam, params); | |
}, | |
startEvent, | |
moveStartEvent = $.Event('translate.move.start', eventParam), | |
movingEvent, | |
moveEndEvent, | |
endEvent = $.Event('translate.end', eventParam), | |
start = target.start = options.start, | |
move = target.move = options.move, | |
end = target.end = options.end, | |
eStart = target.eStart = function (e) { | |
e.preventDefault(); | |
var oe = $.originalEvent(e), | |
clientX = oe.clientX, | |
clientY = oe.clientY, | |
startParam = wrapEvent({ | |
clientX: clientX, | |
clientY: clientY | |
}); | |
delete target.notTriggerClick; | |
if (events.start && false === events.start($.extend(e, startParam))) return target._donNotMove = true; | |
self.trigger(startEvent = $.Event('translate.start', startParam)); | |
if (startEvent.isDefaultPrevented()) return target._donNotMove = true; | |
target._clientX = clientX; | |
target._clientY = clientY; | |
target._translate = $(target).getTranslate3d(); | |
target._translating = true; | |
}, | |
eMove = target.eMove = function (e) { | |
var originalTranslate = target._translate; | |
if (!target._translating || target._donNotMove) return; | |
if (events.moveStart && false === events.moveStart(wrapEvent(e))) return; | |
self.trigger(moveStartEvent); | |
if (moveStartEvent.isDefaultPrevented()) return; | |
var oe = $.originalEvent(e), | |
clientX = oe.clientX, | |
clientY = oe.clientY, | |
originalClientX = target._clientX, | |
originalClientY = target._clientY, | |
changedX = clientX - originalClientX, | |
changedY = clientY - originalClientY, | |
originalTranslateX = originalTranslate.x, | |
originalTranslateY = originalTranslate.y, | |
$target = $(target); | |
if (changedX || changedY) { | |
// 移动时不触发 click 事件 | |
target.notTriggerClick = true; | |
} | |
if (!originalTranslate) return; | |
var translateX = options.x ? originalTranslateX + options.speed * changedX : originalTranslateX, | |
translateY = options.y ? originalTranslateY + options.speed * changedY : originalTranslateY, | |
translateZ = originalTranslate.z, | |
movingParam = wrapEvent({ | |
translateX: translateX, | |
translateY: translateY, | |
changedX: changedX, | |
changedY: changedY, | |
clientX: clientX, | |
clientY: clientY | |
}), | |
moveEndParam; | |
if (events.moving && false === events.moving($.extend(e, movingParam))) return; | |
self.trigger(movingEvent = $.Event('translate.moving', movingParam)); | |
if (movingEvent.isDefaultPrevented()) return; | |
translateX = movingEvent.translateX; | |
translateY = movingEvent.translateY; | |
$target.css({ | |
transform: 'translate3d(' + translateX + 'px,' + translateY + 'px,' + translateZ + 'px)' | |
}); | |
moveEndParam = wrapEvent({ | |
translateX: translateX, | |
translateY: translateY | |
}); | |
if (events.moveEnd && false === events.moveEnd($.extend(e, moveEndParam))) return; | |
self.trigger(moveEndEvent = $.Event('translate.move.end', moveEndParam)); | |
}, | |
eEnd = target.eEnd = function (e) { | |
delete target._translating; | |
if (!target._translate || !target.notTriggerClick) return; | |
if (events.end && false === events.end(wrapEvent(e))) return; | |
self.trigger(endEvent); | |
if (endEvent.isDefaultPrevented()) return; | |
delete target._clientX; | |
delete target._clientY; | |
delete target._translate; | |
delete target._donNotMove; | |
}; | |
$el.on(move, eMove).on(end, eEnd); | |
return self.on(start, eStart); | |
} | |
}(), | |
randomText: function () { | |
var randomInteger = function (num, noZero) { | |
var output = ''; | |
for (var i = 0; i < num; i++) { | |
output += noZero ? Math.ceil(Math.random() * 9) : Math.floor(Math.random() * 10); | |
} | |
return output; | |
}, | |
randomDecimal = function (integerNum, decimalNum) { | |
var output = randomInteger(integerNum); | |
null == decimalNum || (output += '.' + randomInteger(decimalNum)); | |
return output; | |
}, | |
DEFAULT_OPTIONS = { | |
totalDelay: 1500, | |
intervalDelay: 10 | |
}; | |
return function (text, totalDelay, intervalDelay, random) { | |
var argv = arguments; | |
if (this.length > 1) { | |
return this.each(function () { | |
var $this = $(this); | |
$this.randomText.apply($this, argv); | |
}); | |
} | |
var args; | |
if (argv.length === 1 && $.isObject(text) && (args = text)) { | |
text = args.text; | |
totalDelay = args.totalDelay; | |
intervalDelay = args.intervalDelay; | |
random = args.random; | |
} | |
text = text + ''; | |
null == totalDelay && (totalDelay = DEFAULT_OPTIONS.totalDelay); | |
null == intervalDelay && (intervalDelay = DEFAULT_OPTIONS.intervalDelay); | |
var len = text.length; | |
random = random || function () { | |
var pointIndex = text.indexOf('.'); | |
return function () { | |
return -1 === pointIndex ? randomInteger(len) : randomDecimal(pointIndex, len - pointIndex - 1); | |
} | |
}(); | |
var intervalStart = +new Date, | |
i = 0, | |
intervalId = setInterval(function () { | |
var duration = +new Date - intervalStart; | |
if (duration >= totalDelay) { | |
clearInterval(intervalId); | |
return this.text(text); | |
} | |
var randomText = random.call(text, text), | |
index = len - i + 1; | |
null == randomText && (randomText = ''); | |
randomText = randomText.toString().substr(0, index) + text.substr(index); | |
duration > totalDelay / len * i && i++; | |
this.text(randomText); | |
}.bind(this), intervalDelay); | |
return this; | |
} | |
}() | |
}); | |
}(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment