mirror of
https://github.com/videojs/video.js.git
synced 2025-01-10 23:30:03 +02:00
Made tap events on mobile less sensitive to touch moves. closes #1111
This commit is contained in:
parent
ef25557577
commit
dbff62e3f0
@ -13,6 +13,7 @@ CHANGELOG
|
||||
* Added a more informative and styled fallback message for non-html5 browsers [[view](https://github.com/videojs/video.js/pull/1181)]
|
||||
* Added the option to provide an array of child components instead of an object [[view](https://github.com/videojs/video.js/pull/1093)]
|
||||
* Fixed casing on webkitRequestFullscreen [[view](https://github.com/videojs/video.js/pull/1101)]
|
||||
* Made tap events on mobile less sensitive to touch moves [[view](https://github.com/videojs/video.js/pull/1111)]
|
||||
|
||||
--------------------
|
||||
|
||||
|
@ -15,23 +15,9 @@ vjs.Button = vjs.Component.extend({
|
||||
init: function(player, options){
|
||||
vjs.Component.call(this, player, options);
|
||||
|
||||
var touchstart = false;
|
||||
this.on('touchstart', function(event) {
|
||||
// Stop click and other mouse events from triggering also
|
||||
event.preventDefault();
|
||||
touchstart = true;
|
||||
});
|
||||
this.on('touchmove', function() {
|
||||
touchstart = false;
|
||||
});
|
||||
var self = this;
|
||||
this.on('touchend', function(event) {
|
||||
if (touchstart) {
|
||||
self.onClick(event);
|
||||
}
|
||||
event.preventDefault();
|
||||
});
|
||||
this.emitTapEvents();
|
||||
|
||||
this.on('tap', this.onClick);
|
||||
this.on('click', this.onClick);
|
||||
this.on('focus', this.onFocus);
|
||||
this.on('blur', this.onBlur);
|
||||
|
@ -864,35 +864,61 @@ vjs.Component.prototype.onResize;
|
||||
* @private
|
||||
*/
|
||||
vjs.Component.prototype.emitTapEvents = function(){
|
||||
var touchStart, touchTime, couldBeTap, noTap;
|
||||
var touchStart, firstTouch, touchTime, couldBeTap, noTap,
|
||||
xdiff, ydiff, touchDistance, tapMovementThreshold;
|
||||
|
||||
// Track the start time so we can determine how long the touch lasted
|
||||
touchStart = 0;
|
||||
firstTouch = null;
|
||||
|
||||
// Maximum movement allowed during a touch event to still be considered a tap
|
||||
tapMovementThreshold = 22;
|
||||
|
||||
this.on('touchstart', function(event) {
|
||||
// Record start time so we can detect a tap vs. "touch and hold"
|
||||
touchStart = new Date().getTime();
|
||||
// Reset couldBeTap tracking
|
||||
couldBeTap = true;
|
||||
// If more than one finger, don't consider treating this as a click
|
||||
if (event.touches.length === 1) {
|
||||
firstTouch = event.touches[0];
|
||||
// Record start time so we can detect a tap vs. "touch and hold"
|
||||
touchStart = new Date().getTime();
|
||||
// Reset couldBeTap tracking
|
||||
couldBeTap = true;
|
||||
}
|
||||
});
|
||||
|
||||
this.on('touchmove', function(event) {
|
||||
// If more than one finger, don't consider treating this as a click
|
||||
if (event.touches.length > 1) {
|
||||
couldBeTap = false;
|
||||
} else if (firstTouch) {
|
||||
// Some devices will throw touchmoves for all but the slightest of taps.
|
||||
// So, if we moved only a small distance, this could still be a tap
|
||||
xdiff = event.touches[0].pageX - firstTouch.pageX;
|
||||
ydiff = event.touches[0].pageY - firstTouch.pageY;
|
||||
touchDistance = Math.sqrt(xdiff * xdiff + ydiff * ydiff);
|
||||
if (touchDistance > tapMovementThreshold) {
|
||||
couldBeTap = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
noTap = function(){
|
||||
couldBeTap = false;
|
||||
};
|
||||
// TODO: Listen to the original target. http://youtu.be/DujfpXOKUp8?t=13m8s
|
||||
this.on('touchmove', noTap);
|
||||
this.on('touchleave', noTap);
|
||||
this.on('touchcancel', noTap);
|
||||
|
||||
// When the touch ends, measure how long it took and trigger the appropriate
|
||||
// event
|
||||
this.on('touchend', function(event) {
|
||||
firstTouch = null;
|
||||
// Proceed only if the touchmove/leave/cancel event didn't happen
|
||||
if (couldBeTap === true) {
|
||||
// Measure how long the touch lasted
|
||||
touchTime = new Date().getTime() - touchStart;
|
||||
// The touch needs to be quick in order to consider it a tap
|
||||
if (touchTime < 250) {
|
||||
event.preventDefault(); // Don't let browser turn this into a click
|
||||
this.trigger('tap');
|
||||
// It may be good to copy the touchend event object and change the
|
||||
// type to tap, if the other event properties aren't exact after
|
||||
|
@ -255,7 +255,7 @@ test('should use a defined content el for appending children', function(){
|
||||
});
|
||||
|
||||
test('should emit a tap event', function(){
|
||||
expect(1);
|
||||
expect(2);
|
||||
|
||||
// Fake touch support. Real touch support isn't needed for this test.
|
||||
var origTouch = vjs.TOUCH_ENABLED;
|
||||
@ -267,13 +267,27 @@ test('should emit a tap event', function(){
|
||||
comp.on('tap', function(){
|
||||
ok(true, 'Tap event emitted');
|
||||
});
|
||||
comp.trigger('touchstart');
|
||||
|
||||
// A touchstart followed by touchend should trigger a tap
|
||||
vjs.trigger(comp.el(), {type: 'touchstart', touches: [{}]});
|
||||
comp.trigger('touchend');
|
||||
|
||||
// This second test should not trigger another tap event because
|
||||
// a touchmove is happening
|
||||
comp.trigger('touchstart');
|
||||
comp.trigger('touchmove');
|
||||
// A touchmove with a lot of movement should not trigger a tap
|
||||
vjs.trigger(comp.el(), {type: 'touchstart', touches: [
|
||||
{ pageX: 0, pageY: 0 }
|
||||
]});
|
||||
vjs.trigger(comp.el(), {type: 'touchmove', touches: [
|
||||
{ pageX: 100, pageY: 100 }
|
||||
]});
|
||||
comp.trigger('touchend');
|
||||
|
||||
// A touchmove with not much movement should still allow a tap
|
||||
vjs.trigger(comp.el(), {type: 'touchstart', touches: [
|
||||
{ pageX: 0, pageY: 0 }
|
||||
]});
|
||||
vjs.trigger(comp.el(), {type: 'touchmove', touches: [
|
||||
{ pageX: 10, pageY: 10 }
|
||||
]});
|
||||
comp.trigger('touchend');
|
||||
|
||||
// Reset to orignial value
|
||||
|
Loading…
Reference in New Issue
Block a user