Skip to content

Instantly share code, notes, and snippets.

@JounQin
Last active August 5, 2016 15:16
Show Gist options
  • Save JounQin/50b8310a14b9215126f420cbab4785a6 to your computer and use it in GitHub Desktop.
Save JounQin/50b8310a14b9215126f420cbab4785a6 to your computer and use it in GitHub Desktop.
基于 jQuery 使用 transform(translate) 进行拖拽,附赠一个随机倒数的功能
/**
* 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