From acd2508b7aac0a89348a61fe2fa007b5ca681ff3 Mon Sep 17 00:00:00 2001 From: hu de yi Date: Fri, 5 Jan 2024 15:49:45 +0800 Subject: [PATCH] map mousemove event add time Threshold for performance (#2138) * map mousemove event add time Threshold for performance * update for spec * stopPropagation * spec --- src/core/Browser.js | 1 + src/core/util/dom.js | 14 +++++++++++++- src/map/Map.DomEvents.js | 7 ++++++- src/map/Map.js | 6 ++++-- src/map/handler/Map.GeometryEvents.js | 16 ++++++++++++---- test/geometry/event/GeometryEventSpec.js | 23 +++++++++++++++++++++++ 6 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/core/Browser.js b/src/core/Browser.js index af9bb1da5..285d0d8bc 100644 --- a/src/core/Browser.js +++ b/src/core/Browser.js @@ -82,6 +82,7 @@ if (!IS_NODE) { } Browser = { + isTest: false, ie: ie, ielt9: ie && !document.addEventListener, edge: 'msLaunchUri' in navigator && !('documentMode' in document), diff --git a/src/core/util/dom.js b/src/core/util/dom.js index 645079702..009de2ae4 100644 --- a/src/core/util/dom.js +++ b/src/core/util/dom.js @@ -8,7 +8,7 @@ import Browser from '../Browser'; import { IS_NODE } from './env'; -import { isString, isNil } from './common'; +import { isString, isNil, now } from './common'; import { splitWords } from './strings'; import Point from '../../geo/Point'; import Size from '../../geo/Size'; @@ -525,3 +525,15 @@ export const off = removeDomEvent; export function isMoveEvent(type) { return type && (type === 'mousemove' || type === 'touchmove'); } + +export const MOUSEMOVE_EVENT_TIMETHRESHOLD = 48; + +export function mousemoveEventTimeThresholdJudge(target, mousemoveTimeThreshold) { + const currentTime = now(); + const TIME = mousemoveTimeThreshold || MOUSEMOVE_EVENT_TIMETHRESHOLD; + if (target._mousemoveTime && currentTime - target._mousemoveTime < TIME) { + return false; + } + target._mousemoveTime = currentTime; + return true; +} diff --git a/src/map/Map.DomEvents.js b/src/map/Map.DomEvents.js index 4cd7189bf..381e735d1 100644 --- a/src/map/Map.DomEvents.js +++ b/src/map/Map.DomEvents.js @@ -1,10 +1,12 @@ +import Browser from '../core/Browser'; import { now, extend } from '../core/util'; import { addDomEvent, removeDomEvent, preventDefault, getEventContainerPoint, - isMoveEvent + isMoveEvent, + mousemoveEventTimeThresholdJudge } from '../core/util/dom'; import Map from './Map'; @@ -221,6 +223,9 @@ Map.include(/** @lends Map.prototype */ { } const clickTimeThreshold = this.options['clickTimeThreshold']; const type = e.type; + if (isMoveEvent(type) && !Browser.isTest && !mousemoveEventTimeThresholdJudge(this, this.options['mousemoveTimeThreshold'])) { + return; + } const isMouseDown = type === 'mousedown' || (type === 'touchstart' && (!e.touches || e.touches.length === 1)); // prevent default contextmenu if (isMouseDown) { diff --git a/src/map/Map.js b/src/map/Map.js index 08a1aa839..f74359780 100644 --- a/src/map/Map.js +++ b/src/map/Map.js @@ -23,7 +23,7 @@ import Coordinate from '../geo/Coordinate'; import Layer from '../layer/Layer'; import Renderable from '../renderer/Renderable'; import SpatialReference from './spatial-reference/SpatialReference'; -import { computeDomPosition } from '../core/util/dom'; +import { computeDomPosition, MOUSEMOVE_EVENT_TIMETHRESHOLD } from '../core/util/dom'; import EPSG9807 from '../geo/projection/Projection.EPSG9807.js'; const TEMP_COORD = new Coordinate(0, 0); @@ -89,6 +89,7 @@ const REDRAW_OPTIONS_PROPERTIES = ['centerCross', 'fog', 'fogColor', 'debugSky'] * @property {Boolean} [options.cameraInfiniteFar=false] - Increase camera far plane to infinite. Enable this option may reduce map's performance. * @property {Boolean} [options.stopRenderOnOffscreen=true] - whether to stop map rendering when container is offscreen * @property {Boolean} [options.originLatitudeForAltitude=40] - default latitude for map.altitudeToPoint method + * @property {Number} [options.mousemoveTimeThreshold=48] - mousemove event interval time(ms) * @memberOf Map * @instance */ @@ -149,7 +150,8 @@ const options = { //for plugin layer,such as threelayer 'supportPluginEvent': true, - 'switchDragButton': false + 'switchDragButton': false, + 'mousemoveTimeThreshold': MOUSEMOVE_EVENT_TIMETHRESHOLD }; /** diff --git a/src/map/handler/Map.GeometryEvents.js b/src/map/handler/Map.GeometryEvents.js index 82e2336c8..dd26f5767 100644 --- a/src/map/handler/Map.GeometryEvents.js +++ b/src/map/handler/Map.GeometryEvents.js @@ -1,8 +1,9 @@ import { now } from '../../core/util'; -import { on, off, getEventContainerPoint, preventDefault, stopPropagation, isMoveEvent } from '../../core/util/dom'; +import { on, off, getEventContainerPoint, preventDefault, stopPropagation, isMoveEvent, mousemoveEventTimeThresholdJudge } from '../../core/util/dom'; import Handler from '../../handler/Handler'; import Geometry from '../../geometry/Geometry'; import Map from '../Map'; +import Browser from '../../core/Browser'; const EVENTS = /** @@ -204,6 +205,11 @@ class MapGeometryEventsHandler extends Handler { } let oneMoreEvent = null; const eventType = type || domEvent.type; + if (isMoveEvent(eventType) && !Browser.isTest && !mousemoveEventTimeThresholdJudge(this, map.options['mousemoveTimeThreshold'])) { + stopPropagation(domEvent); + return; + } + // ignore click lasted for more than 300ms. const isMousedown = eventType === 'mousedown' || (eventType === 'touchstart' && domEvent.touches && domEvent.touches.length === 1); if (isMousedown) { @@ -279,9 +285,11 @@ class MapGeometryEventsHandler extends Handler { if (!geometryCursorStyle && geometry.options['cursor']) { geometryCursorStyle = geometry.options['cursor']; } - if (!geometry.listens('mousemove') && !geometry.listens('mouseover') && !geometry.listens('mouseenter')) { - return false; - } + //always return true for mouseout mouseleave + return true; + // if (!geometry.listens('mousemove') && !geometry.listens('mouseover') && !geometry.listens('mouseenter')) { + // return false; + // } } else if (!geometry.listens(eventToFire) && !geometry.listens(oneMoreEvent)) { return false; } diff --git a/test/geometry/event/GeometryEventSpec.js b/test/geometry/event/GeometryEventSpec.js index 1eb1a5748..326f6866e 100644 --- a/test/geometry/event/GeometryEventSpec.js +++ b/test/geometry/event/GeometryEventSpec.js @@ -461,4 +461,27 @@ describe('Geometry.Events', function () { } test(); }); + + it('#2103 mouseout when no others mouse events', function (done) { + var circle = new maptalks.Circle(map.getCenter(), 10); + circle.addTo(layer); + var domPosition = GET_PAGE_POSITION(container); + var point = map.coordinateToContainerPoint(center).add(domPosition); + circle.on('mouseout', function (param) { + expect(param.type).to.be.eql('mouseout'); + done(); + }); + + happen.mousemove(eventContainer, { + 'clientX': point.x, + 'clientY': point.y + }); + + setTimeout(() => { + happen.mousemove(eventContainer, { + 'clientX': point.x + 100, + 'clientY': point.y + 100 + }); + }, 50); + }); });