1
0
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:
Jon Zepernick 2014-05-06 17:22:29 -07:00 committed by Steve Heffernan
parent ef25557577
commit dbff62e3f0
4 changed files with 55 additions and 28 deletions

View File

@ -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)]
--------------------

View File

@ -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);

View File

@ -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

View File

@ -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