Skip to content

Commit

Permalink
perf: Add mouseup and mousedown events
Browse files Browse the repository at this point in the history
These percolate through to features.
  • Loading branch information
manthey committed May 3, 2023
1 parent 9acb4f0 commit 0261f45
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 7 deletions.
57 changes: 57 additions & 0 deletions src/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,28 @@ geo_event.mousemove = 'geo_mousemove';
*/
geo_event.mouseclick = 'geo_mouseclick';

/**
* Triggered on `mouseup` events. The event object extends
* {@link geo.mouseState}.
*
* @event geo.event.mouseup
* @type {(geo.event.base|geo.mouseState)}
* @property {geo.mouseButtons} buttonsDown The buttons that were down at the
* start of the up action.
*/
geo_event.mouseup = 'geo_mouseup';

/**
* Triggered on `mousedown` events. The event object extends
* {@link geo.mouseState}.
*
* @event geo.event.mousedown
* @type {(geo.event.base|geo.mouseState)}
* @property {geo.mouseButtons} buttonsDown The buttons that were down at the
* end of the down action.
*/
geo_event.mousedown = 'geo_mousedown';

/**
* Triggered on every `mousemove` during a brushing selection.
* The event object extends {@link geo.brushSelection}.
Expand Down Expand Up @@ -485,6 +507,41 @@ geo_event.feature = {
* @property {geo.event} sourceEvent The underlying event that trigger this.
*/
mouseclick_order: 'geo_feature_mouseclick_order',
/**
* The event is the feature version of {@link geo.event.mousedown}.
*
* @event geo.event.feature.mousedown
* @type {geo.event.base}
* @property {object} data The feature data the mouse is above.
* @property {number} index The index of the feature data the mouse is above.
* @property {object} extra Extra information about the feature and mouse
* location.
* @property {geo.mouseState} mouse The mouse state.
* @property {number} eventID a monotonically increasing event number. All
* features that the mouse goes down on simultaneously will have the same
* `eventID`.
* @property {boolean} top True if this is the topmost data element.
* @property {geo.event} sourceEvent The underlying event that trigger this.
*/
mousedown: 'geo_feature_mousedown',
/**
* The event is the feature version of {@link geo.event.mouseup}.
*
* @event geo.event.feature.mouseup
* @type {geo.event.base}
* @property {object} data The feature data the mouse is above.
* @property {number} index The index of the feature data the mouse is above.
* @property {object} extra Extra information about the feature and mouse
* location.
* @property {geo.mouseState} mouse The mouse state. The buttons are before
* the up action occurs.
* @property {number} eventID a monotonically increasing event number. All
* features that the mouse goes up on simultaneously will have the same
* `eventID`.
* @property {boolean} top True if this is the topmost data element.
* @property {geo.event} sourceEvent The underlying event that trigger this.
*/
mouseup: 'geo_feature_mouseup',
/**
* This event is fired for each data component of a feature under a brush
* that has just finished its selection.
Expand Down
52 changes: 49 additions & 3 deletions src/feature.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ var feature = function (arg) {
m_this._unbindMouseHandlers();

m_this.geoOn(geo_event.mousemove, m_this._handleMousemove);
m_this.geoOn(geo_event.mousedown, m_this._handleMousedown);
m_this.geoOn(geo_event.mouseup, m_this._handleMouseup);
m_this.geoOn(geo_event.mouseclick, m_this._handleMouseclick);
m_this.geoOn(geo_event.brushend, m_this._handleBrushend);
m_this.geoOn(geo_event.brush, m_this._handleBrush);
Expand All @@ -172,6 +174,8 @@ var feature = function (arg) {
*/
this._unbindMouseHandlers = function () {
m_this.geoOff(geo_event.mousemove, m_this._handleMousemove);
m_this.geoOff(geo_event.mousedown, m_this._handleMousedown);
m_this.geoOff(geo_event.mouseup, m_this._handleMouseup);
m_this.geoOff(geo_event.mouseclick, m_this._handleMouseclick);
m_this.geoOff(geo_event.brushend, m_this._handleBrushend);
m_this.geoOff(geo_event.brush, m_this._handleBrush);
Expand Down Expand Up @@ -238,20 +242,46 @@ var feature = function (arg) {
};
};

/**
* Private mousedown handler. This uses `pointSearch` to determine which
* features the mouse is over, then fires appropriate events.
*
* @param {geo.event} evt The event that triggered this handler.
* @fires geo.event.feature.mousedown
*/
this._handleMousedown = function (evt) {
this._handleMousemove(evt, geo_event.feature.mousedown);
};

/**
* Private mouseup handler. This uses `pointSearch` to determine which
* features the mouse is over, then fires appropriate events.
*
* @param {geo.event} evt The event that triggered this handler.
* @fires geo.event.feature.mouseup
*/
this._handleMouseup = function (evt) {
this._handleMousemove(evt, geo_event.feature.mouseup);
};

/**
* Private mousemove handler. This uses `pointSearch` to determine which
* features the mouse is over, then fires appropriate events.
*
* @param {geo.event} evt The event that triggered this handler.
* @param {string} [updown] If "mouseup" or "mousedown", fire that event
* instead of mouseon.
* @fires geo.event.feature.mouseover_order
* @fires geo.event.feature.mouseover
* @fires geo.event.feature.mouseout
* @fires geo.event.feature.mousemove
* @fires geo.event.feature.mouseoff
* @fires geo.event.feature.mouseon
* @fires geo.event.feature.mouseup
* @fires geo.event.feature.mousedown
*/
this._handleMousemove = function (evt) {
var mouse = m_this.layer().map().interactor().mouse(),
this._handleMousemove = function (evt, updown) {
var mouse = evt && evt.mouse ? evt.mouse : m_this.layer().map().interactor().mouse(),
data = m_this.data(),
over = m_this.pointSearch(mouse.geo),
newFeatures = [], oldFeatures = [], lastTop = -1, top = -1, extra;
Expand All @@ -277,6 +307,23 @@ var feature = function (arg) {
});
}

feature.eventID += 1;

if (updown) {
over.index.forEach((i, idx) => {
m_this.geoTrigger(updown, {
data: data[i],
index: i,
extra: extra[i],
mouse: mouse,
eventID: feature.eventID,
top: idx === over.length - 1,
sourceEvent: evt
}, true);
});
return;
}

// Get the index of the element that was previously on top
if (m_selectedFeatures.length) {
lastTop = m_selectedFeatures[m_selectedFeatures.length - 1];
Expand All @@ -290,7 +337,6 @@ var feature = function (arg) {
return over.index.indexOf(i) < 0;
});

feature.eventID += 1;
// Fire events for mouse in first.
newFeatures.forEach(function (i, idx) {
m_this.geoTrigger(geo_event.feature.mouseover, {
Expand Down
8 changes: 8 additions & 0 deletions src/mapInteractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,7 @@ var mapInteractor = function (args) {
* @param {jQuery.Event} evt The event that triggered this.
* @fires geo.event.brushstart
* @fires geo.event.actiondown
* @fires geo.event.mousedown
*/
this._handleMouseDown = function (evt) {
var action, actionRecord;
Expand All @@ -1109,6 +1110,9 @@ var mapInteractor = function (args) {
m_this._getMouseButton(evt);
m_this._getMouseModifiers(evt);

console.log(JSON.stringify(m_this.mouse().buttons)); // DWM::
m_this.map().geoTrigger(geo_event.mousedown, m_this.mouse());

if (m_options.click.enabled &&
(!m_mouse.buttons.left || m_options.click.buttons.left) &&
(!m_mouse.buttons.right || m_options.click.buttons.right) &&
Expand Down Expand Up @@ -1538,6 +1542,7 @@ var mapInteractor = function (args) {
* @fires geo.event.brushend
* @fires geo.event.actionselection
* @fires geo.event.actionup
* @fires geo.event.mouseup
* @fires geo.event.select
* @fires geo.event.zoomselect
* @fires geo.event.unzoomselect
Expand Down Expand Up @@ -1625,6 +1630,9 @@ var mapInteractor = function (args) {
if (m_clickMaybe) {
m_this._handleMouseClick(evt);
}
var details = m_this.mouse();
details.buttonsDown = m_clickMaybe.buttons;
m_this.map().geoTrigger(geo_event.mouseup, details);
};

/**
Expand Down
18 changes: 14 additions & 4 deletions tutorials/tiled-pixelmap/index.pug
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ block mainTutorial
}
}).draw();
pixelmap.geoOn(geo.event.feature.mouseclick, function (evt) {
// ignore clicks with a shift; this prevents conflicting interaction in
// the next step
if (evt.mouse.modifiers.shift) {
return;
}
// use the index of the superpixel rather than its border, regardless of
// which was clicked.
var index = evt.index - evt.index % 2;
Expand All @@ -121,8 +126,8 @@ block mainTutorial
map.interactor().removeAction(geo.geo_action.zoomselect);
// if the mouse moves, decide whether we should handle it
var newValue = undefined;
pixelmap.geoOn(geo.event.feature.mousemove, function (evt) {
// if shift or the left button aren't down, stop setting values
function onOver(evt) {
// for movement, if shift or the left button aren't down, stop setting values
if (!evt.mouse.modifiers.shift || !evt.mouse.buttons.left) {
newValue = undefined;
return;
Expand All @@ -131,7 +136,7 @@ block mainTutorial
var index = evt.index - evt.index % 2;
var data = pixelmap.data();
// if we just started a movement with shift, update the value and record it
if (newValue === undefined) {
if (newValue === undefined || evt.event === geo.event.feature.mousedown) {
data[index] = data[index + 1] = (data[index] + 1) % 4;
newValue = data[index];
pixelmap.indexModified(index, index + 1).draw();
Expand All @@ -141,4 +146,9 @@ block mainTutorial
data[index] = data[index + 1] = newValue;
pixelmap.indexModified(index, index + 1).draw();
}
});
}
// An alternative would be to bind on mousemove instead of mousedown and
// mouseover and leave the click handler; this requires movement to start
// setting values, whereas mousedown doesn't require mouse movement.
pixelmap.geoOn(geo.event.feature.mousedown, onOver);
pixelmap.geoOn(geo.event.feature.mouseover, onOver);

0 comments on commit 0261f45

Please sign in to comment.