mirror of
https://github.com/videojs/video.js.git
synced 2025-02-04 11:43:27 +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 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)]
|
* 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)]
|
* 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){
|
init: function(player, options){
|
||||||
vjs.Component.call(this, player, options);
|
vjs.Component.call(this, player, options);
|
||||||
|
|
||||||
var touchstart = false;
|
this.emitTapEvents();
|
||||||
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.on('tap', this.onClick);
|
||||||
this.on('click', this.onClick);
|
this.on('click', this.onClick);
|
||||||
this.on('focus', this.onFocus);
|
this.on('focus', this.onFocus);
|
||||||
this.on('blur', this.onBlur);
|
this.on('blur', this.onBlur);
|
||||||
|
@ -864,35 +864,61 @@ vjs.Component.prototype.onResize;
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
vjs.Component.prototype.emitTapEvents = function(){
|
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
|
// Track the start time so we can determine how long the touch lasted
|
||||||
touchStart = 0;
|
touchStart = 0;
|
||||||
|
firstTouch = null;
|
||||||
|
|
||||||
|
// Maximum movement allowed during a touch event to still be considered a tap
|
||||||
|
tapMovementThreshold = 22;
|
||||||
|
|
||||||
this.on('touchstart', function(event) {
|
this.on('touchstart', function(event) {
|
||||||
|
// 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"
|
// Record start time so we can detect a tap vs. "touch and hold"
|
||||||
touchStart = new Date().getTime();
|
touchStart = new Date().getTime();
|
||||||
// Reset couldBeTap tracking
|
// Reset couldBeTap tracking
|
||||||
couldBeTap = true;
|
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(){
|
noTap = function(){
|
||||||
couldBeTap = false;
|
couldBeTap = false;
|
||||||
};
|
};
|
||||||
// TODO: Listen to the original target. http://youtu.be/DujfpXOKUp8?t=13m8s
|
// TODO: Listen to the original target. http://youtu.be/DujfpXOKUp8?t=13m8s
|
||||||
this.on('touchmove', noTap);
|
|
||||||
this.on('touchleave', noTap);
|
this.on('touchleave', noTap);
|
||||||
this.on('touchcancel', noTap);
|
this.on('touchcancel', noTap);
|
||||||
|
|
||||||
// When the touch ends, measure how long it took and trigger the appropriate
|
// When the touch ends, measure how long it took and trigger the appropriate
|
||||||
// event
|
// event
|
||||||
this.on('touchend', function(event) {
|
this.on('touchend', function(event) {
|
||||||
|
firstTouch = null;
|
||||||
// Proceed only if the touchmove/leave/cancel event didn't happen
|
// Proceed only if the touchmove/leave/cancel event didn't happen
|
||||||
if (couldBeTap === true) {
|
if (couldBeTap === true) {
|
||||||
// Measure how long the touch lasted
|
// Measure how long the touch lasted
|
||||||
touchTime = new Date().getTime() - touchStart;
|
touchTime = new Date().getTime() - touchStart;
|
||||||
// The touch needs to be quick in order to consider it a tap
|
// The touch needs to be quick in order to consider it a tap
|
||||||
if (touchTime < 250) {
|
if (touchTime < 250) {
|
||||||
|
event.preventDefault(); // Don't let browser turn this into a click
|
||||||
this.trigger('tap');
|
this.trigger('tap');
|
||||||
// It may be good to copy the touchend event object and change the
|
// 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
|
// 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(){
|
test('should emit a tap event', function(){
|
||||||
expect(1);
|
expect(2);
|
||||||
|
|
||||||
// Fake touch support. Real touch support isn't needed for this test.
|
// Fake touch support. Real touch support isn't needed for this test.
|
||||||
var origTouch = vjs.TOUCH_ENABLED;
|
var origTouch = vjs.TOUCH_ENABLED;
|
||||||
@ -267,13 +267,27 @@ test('should emit a tap event', function(){
|
|||||||
comp.on('tap', function(){
|
comp.on('tap', function(){
|
||||||
ok(true, 'Tap event emitted');
|
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');
|
comp.trigger('touchend');
|
||||||
|
|
||||||
// This second test should not trigger another tap event because
|
// A touchmove with a lot of movement should not trigger a tap
|
||||||
// a touchmove is happening
|
vjs.trigger(comp.el(), {type: 'touchstart', touches: [
|
||||||
comp.trigger('touchstart');
|
{ pageX: 0, pageY: 0 }
|
||||||
comp.trigger('touchmove');
|
]});
|
||||||
|
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');
|
comp.trigger('touchend');
|
||||||
|
|
||||||
// Reset to orignial value
|
// Reset to orignial value
|
||||||
|
Loading…
x
Reference in New Issue
Block a user