From 13feeff4f6bd998090c00867468b39cf7abadfb8 Mon Sep 17 00:00:00 2001 From: Matthew Chase Whittemore Date: Wed, 4 May 2016 19:51:10 -0400 Subject: [PATCH 1/2] synthetic click to catch small drags --- bench/lib/mouse_draw.js | 11 ++++++---- bench/lib/mouse_trace.js | 10 ++++++++- src/events.js | 39 ++++++++++++++++++++--------------- src/lib/euclidean_distance.js | 4 ++++ src/lib/mode_handler.js | 3 --- src/modes/direct_select.js | 7 ++----- src/modes/simple_select.js | 4 ++-- test/line.test.js | 4 ++-- test/point.test.js | 4 ++-- test/polygon.test.js | 6 +++--- test/utils.js | 5 +++++ 11 files changed, 58 insertions(+), 39 deletions(-) create mode 100644 src/lib/euclidean_distance.js diff --git a/bench/lib/mouse_draw.js b/bench/lib/mouse_draw.js index db837d3aeb5..887c29ae8f8 100644 --- a/bench/lib/mouse_draw.js +++ b/bench/lib/mouse_draw.js @@ -7,21 +7,24 @@ module.exports = function(start, map) { var events = mouseEvents(map); - events.push('mousemove', { + events.push('mousedown', { x: start.x, y: start.y }); - events.push('click', { + events.push('mousemove', { x: start.x, y: start.y - }, true); + }); for (var i=0; i { - return dragging; - }, function(e) { + this.on('drag', () => dragging, function(e) { e.originalEvent.stopPropagation(); if (coordPos === null) { setupCoordPos(); @@ -66,8 +64,7 @@ module.exports = function(ctx, opts) { numCoords = null; startPos = null; }); - this.on('click', noFeature, function(e) { - e.originalEvent.stopPropagation(); + this.on('click', noFeature, function() { ctx.events.changeMode('simple_select'); }); this.on('trash', () => selectedCoordPaths.length > 0, function() { diff --git a/src/modes/simple_select.js b/src/modes/simple_select.js index 5b43aa8ecb2..d61ad9ab2f4 100644 --- a/src/modes/simple_select.js +++ b/src/modes/simple_select.js @@ -65,7 +65,7 @@ module.exports = function(ctx, startingSelectedFeatureIds) { var isSelected = selectedFeaturesById[id] !== undefined; if (isSelected && !isShiftDown(e)) { - this.on('mouseup', readyForDirectSelect, directSelect); + this.on('click', readyForDirectSelect, directSelect); } else if (isSelected && isShiftDown(e)) { delete selectedFeaturesById[id]; @@ -94,7 +94,7 @@ module.exports = function(ctx, startingSelectedFeatureIds) { }); this.on('drag', () => dragging, function(e) { - this.off('mouseup', readyForDirectSelect, directSelect); + this.off('click', readyForDirectSelect, directSelect); e.originalEvent.stopPropagation(); if (featureCoords === null) { buildFeatureCoords(); diff --git a/test/line.test.js b/test/line.test.js index 4c2e69d62cc..7a00ed429cf 100644 --- a/test/line.test.js +++ b/test/line.test.js @@ -1,7 +1,7 @@ import test from 'tape'; import mapboxgl from 'mapbox-gl-js-mock'; import GLDraw from '../'; -import { accessToken, createMap, features } from './utils'; +import { accessToken, createMap, features, click } from './utils'; var feature = features.line; @@ -20,7 +20,7 @@ test('Line draw class', function lineDrawClass(t){ for (var i = 0; i < coords.length; i++) { let c = coords[i]; - map.fire('click', { + click(map, { lngLat: { lng: c[0], lat: c[1] diff --git a/test/point.test.js b/test/point.test.js index f2bd93d0671..497d16461c5 100644 --- a/test/point.test.js +++ b/test/point.test.js @@ -1,7 +1,7 @@ import test from 'tape'; import mapboxgl from 'mapbox-gl-js-mock'; import GLDraw from '../'; -import { createMap } from './utils'; +import { createMap, click } from './utils'; test('Point geometry class', t => { var map = createMap(); @@ -10,7 +10,7 @@ test('Point geometry class', t => { map.on('load', function() { Draw.changeMode('draw_point'); - map.fire('click', { + click(map, { lngLat: { lng: 10, lat: 10 diff --git a/test/polygon.test.js b/test/polygon.test.js index 8e33bbf29c7..700e454c930 100644 --- a/test/polygon.test.js +++ b/test/polygon.test.js @@ -1,7 +1,7 @@ import test from 'tape'; import mapboxgl from 'mapbox-gl-js-mock'; import GLDraw from '../'; -import {createMap, features } from './utils'; +import {createMap, features, click } from './utils'; var feature = features.polygon; @@ -15,7 +15,7 @@ test('Polygon geometry class', t => { let coords = feature.geometry.coordinates[0]; for (var i = 0; i < coords.length-1; i++) { var c = coords[i]; - map.fire('click',{ + click(map, { lngLat: { lng: c[0], lat: c[1] @@ -27,7 +27,7 @@ test('Polygon geometry class', t => { }); } - map.fire('click', { + click(map, { lngLat: { lng: coords[coords.length - 2][0], lat: coords[coords.length - 2][1] diff --git a/test/utils.js b/test/utils.js index 1ad886fbbf1..50cdb0144c4 100644 --- a/test/utils.js +++ b/test/utils.js @@ -10,6 +10,11 @@ export function createMap() { return map; } +export function click(map, payload) { + map.fire('mousedown', payload); + map.fire('mouseup', payload); +} + export const features = { line: { From 1aa3bafea8bc5a3059e3de5c3e6c880fc8565a56 Mon Sep 17 00:00:00 2001 From: Matthew Chase Whittemore Date: Thu, 5 May 2016 11:53:52 -0400 Subject: [PATCH 2/2] don't drag until it cannot be a click --- src/events.js | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/events.js b/src/events.js index ac0c4009591..61ea86fa462 100644 --- a/src/events.js +++ b/src/events.js @@ -13,21 +13,38 @@ var modes = { const closeTolerance = 4; const tolerance = 12; +const isClick = (start, end) => { + start.point = start.point || end.point; + start.time = start.time || end.time; + var moveDistance = euclideanDistance(start.point, end.point); + return moveDistance < closeTolerance || (moveDistance < tolerance && (end.time - start.time) < 500); +}; + module.exports = function(ctx) { - var isDown = false; + var mouseDownInfo = { + isDown: false + }; var events = {}; var currentModeName = 'simple_select'; var currentMode = ModeHandler(modes.simple_select(ctx), ctx); events.drag = function(event) { - ctx.ui.setClass({mouse: 'drag'}); - currentMode.drag(event); + if (isClick(mouseDownInfo, { + point: event.point, + time: new Date().getTime() + })) { + event.originalEvent.stopPropagation(); + } + else { + ctx.ui.setClass({mouse: 'drag'}); + currentMode.drag(event); + } }; events.mousemove = function(event) { - if (isDown) { + if (mouseDownInfo.isDown) { events.drag(event); } else { @@ -37,29 +54,27 @@ module.exports = function(ctx) { } }; - var mouseDownStart = {}; events.mousedown = function(event) { - mouseDownStart = { + mouseDownInfo = { + isDown: true, time: new Date().getTime(), point: event.point }; - isDown = true; var target = findTargetAt(event, ctx); event.featureTarget = target; currentMode.mousedown(event); }; events.mouseup = function(event) { - isDown = false; + mouseDownInfo.isDown = false; var target = findTargetAt(event, ctx); event.featureTarget = target; - var endTime = new Date().getTime(); - - var moveDistance = mouseDownStart.point ? euclideanDistance(mouseDownStart.point, event.point) : false; - - if (moveDistance !== false && (moveDistance < closeTolerance || (moveDistance < tolerance && (endTime - mouseDownStart.time) < 500))) { + if (isClick(mouseDownInfo, { + point: event.point, + time: new Date().getTime() + })) { currentMode.click(event); } else {