Skip to content

Commit

Permalink
Merge pull request #302 from zakandrewking/testing-performance-mobile…
Browse files Browse the repository at this point in the history
…-pan-zoom

Performance improvements for pan & zoom
  • Loading branch information
zakandrewking authored Jul 15, 2019
2 parents e5e07ce + 1cfd348 commit 521bbd3
Show file tree
Hide file tree
Showing 12 changed files with 265 additions and 268 deletions.
34 changes: 17 additions & 17 deletions docs/escher-python.ipynb

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions docs/tips-and-tricks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,23 @@ other subsystems.

.. _escher.github.io: https://www.github.com/escher/escher.github.io/
.. _`BiGG Database`: http://bigg.ucsd.edu

Escher performance with large maps
----------------------------------

Escher works best with maps that have less than about 200 reactions. If you are
working with more reactions, we recommend splitting your map into multiple small
maps. A trick for splitting up a map is to first select the reactions you want
to keep, then choose "Edit > Invert Selection" and then "Edit > Delete".

If you really want to work with larger maps, the following can help improve
performance:

- Turn off tooltips in the settings menu, especially tooltips over Objects
- Try the "Use 3D Transform" option in the settings menu. Depending on your
browser, this can increase responsiveness when moving around the map.
- Turn off labels, gene reaction rules, and/or secondary metabolites in the
settings menu.

We are always trying to make Escher faster, so let us know if you find any
unexpected performance issues.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"d3-request": "^1.0.3",
"d3-scale": "^1.0.4",
"d3-selection": "^1.0.3",
"d3-zoom": "^1.1.1",
"d3-zoom": "^1.7.3",
"file-saver": "^1.3.3",
"immutability-helper": "^2.4.0",
"mousetrap": "^1.5.3",
Expand Down
135 changes: 63 additions & 72 deletions src/Behavior.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as d3Selection from 'd3-selection'

const d3Select = d3Selection.select
const d3Mouse = d3Selection.mouse
const d3Touch = d3Selection.touch

/**
* Behavior. Defines the set of click and drag behaviors for the map, and keeps
Expand All @@ -29,48 +30,28 @@ export default class Behavior {
this.textLabelMousedown = null
this.textLabelClick = null
this.selectableDrag = this.emptyBehavior
this.nodeMouseover = null
this.nodeMouseout = null
this.labelMousedown = null
this.labelMouseover = this.emptyBehavior
this.labelMouseout = null
this.labelTouch = null
this.objectMouseover = this.emptyBehavior
this.objectTouch = null
this.objectMouseout = null

this.nodeLabelMouseover = null
this.nodeLabelTouch = null
this.nodeLabelMouseout = null
this.reactionLabelMouseover = null
this.reactionLabelTouch = null
this.reactionLabelMouseout = null
this.geneLabelMouseover = null
this.geneLabelTouch = null
this.geneLabelMouseout = null

this.nodeObjectMouseover = null
this.nodeObjectMouseout = null
this.reactionObjectMouseover = null
this.reactionObjectMouseout = null

this.bezierDrag = this.emptyBehavior
this.bezierMouseover = null
this.bezierMouseout = null
this.reactionLabelDrag = this.emptyBehavior
this.nodeLabelDrag = this.emptyBehavior
this.dragging = false
this.turnEverythingOn()
}

/**
* Toggle everything except rotation mode and text mode.
*/
turnEverythingOn () {
this.toggleSelectableClick(true)
this.toggleSelectableDrag(true)
this.toggleLabelDrag(true)
this.toggleLabelMouseover(true)
this.toggleLabelTouch(true)
this.toggleObjectMouseover(true)
this.toggleObjectTouch(true)
}

/**
* Toggle everything except rotation mode and text mode.
*/
turnEverythingOff () {
this.toggleSelectableClick(false)
this.toggleSelectableDrag(false)
this.toggleLabelDrag(false)
this.toggleLabelMouseover(false)
this.toggleLabelTouch(false)
this.toggleObjectMouseover(false)
this.toggleObjectTouch(false)
}

averageLocation (nodes) {
Expand Down Expand Up @@ -345,48 +326,40 @@ export default class Behavior {
*/
toggleLabelMouseover (onOff) {
if (onOff === undefined) {
onOff = this.labelMouseover === this.emptyBehavior
onOff = this.nodeLabelMouseover === null
}

if (onOff) {
// Show/hide tooltip.
// @param {String} type - 'reactionLabel' or 'nodeLabel'
// @param {Object} d - D3 data for DOM element
this.labelMouseover = (type, d) => {
const getMouseover = type => d => {
if (!this.dragging) {
this.map.callback_manager.run('show_tooltip', null, type, d)
}
}

this.labelMouseout = () => {
const mouseout = () => {
this.map.callback_manager.run('delay_hide_tooltip')
}
this.nodeLabelMouseover = getMouseover('node_label')
this.nodeLabelTouch = getMouseover('node_label')
this.nodeLabelMouseout = mouseout
this.reactionLabelMouseover = getMouseover('reaction_label')
this.reactionLabelTouch = getMouseover('reaction_label')
this.reactionLabelMouseout = mouseout
this.geneLabelMouseover = getMouseover('gene_label')
this.geneLabelTouch = getMouseover('gene_label')
this.geneLabelMouseout = mouseout
} else {
this.labelMouseover = this.emptyBehavior
}
}

/**
* With no argument, toggle the tooltips upon touching of labels.
* @param {Boolean} onOff - The new on/off state. If this argument is not
* provided, then toggle the state.
*/
toggleLabelTouch (onOff) {
if (onOff === undefined) {
onOff = this.labelTouch === null
}

if (onOff) {
// Show/hide tooltip.
// @param {String} type - 'reactionLabel' or 'nodeLabel'
// @param {Object} d - D3 data for DOM element
this.labelTouch = (type, d) => {
if (!this.dragging) {
this.map.callback_manager.run('show_tooltip', null, type, d)
}
}
} else {
this.labelTouch = null
this.nodeLabelMouseover = null
this.nodeLabelTouch = null
this.nodeLabelMouseout = null
this.reactionLabelMouseover = null
this.reactionLabelTouch = null
this.reactionLabelMouseout = null
this.geneLabelMouseover = null
this.geneLabelTouch = null
this.geneLabelMouseout = null
}
}

Expand All @@ -396,24 +369,42 @@ export default class Behavior {
*/
toggleObjectMouseover (onOff) {
if (onOff === undefined) {
onOff = this.objectMouseover === this.emptyBehavior
onOff = this.nodeObjectMouseover === null
}

if (onOff) {
// Show/hide tooltip.
// @param {String} type - 'reaction_object' or 'node_object'
// @param {Object} d - D3 data for DOM element
this.objectMouseover = (type, d) => {
if (!this.dragging) {
this.map.callback_manager.run('show_tooltip', null, type, d)
const getMouseover = type => {
const behavior = this
return function (d) {
if (!behavior.dragging) {
if (type === 'reaction_object') {
const mouseEvent = d3Mouse(this)
// Add the current mouse position to the segment's datum
const newD = Object.assign(
{}, d, { xPos: mouseEvent[0], yPos: mouseEvent[1] }
)
behavior.map.callback_manager.run('show_tooltip', null, type, newD)
} else {
behavior.map.callback_manager.run('show_tooltip', null, type, d)
}
}
}
}

this.objectMouseout = () => {
const mouseout = () => {
this.map.callback_manager.run('delay_hide_tooltip')
}
this.nodeObjectMouseover = getMouseover('node_object')
this.nodeObjectMouseout = mouseout
this.reactionObjectMouseover = getMouseover('reaction_object')
this.reactionObjectMouseout = mouseout
} else {
this.objectMouseover = this.emptyBehavior
this.nodeObjectMouseover = null
this.nodeObjectMouseout = null
this.reactionObjectMouseover = null
this.reactionObjectMouseout = null
}
}

Expand Down
15 changes: 13 additions & 2 deletions src/Builder.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ class Builder {
this.zoom_container.setScrollBehavior(val)
})

// Reactive tooltip settings
this.settings.streams.enable_tooltips.onValue(val => {
this._updateTooltipSetting(val)
})

// Make a container for other map-related tools that will be reset on map load
// TODO only create these once in the Builder constructor
this.mapToolsContainer = this.selection.append('div')
Expand Down Expand Up @@ -386,6 +391,9 @@ class Builder {
this._setupStatus(this.map)
this.map.set_status('Loading map ...')

// Connect tooltips
this._updateTooltipSetting(this.settings.get('enable_tooltips'))

// Set the data for the map
if (shouldUpdateData) {
this._updateData(false, true)
Expand Down Expand Up @@ -766,8 +774,6 @@ class Builder {
}
this.map.behavior.toggleSelectableClick(mode === 'build' || mode === 'brush') // XX
this.map.behavior.toggleLabelDrag(mode === 'brush') // XX
// this.map.behavior.toggleLabelMouseover(true)
// this.map.behavior.toggleLabelTouch(true)
this.map.behavior.toggleTextLabelEdit(mode === 'text') // XX
this.map.behavior.toggleBezierDrag(mode === 'brush') // XX

Expand Down Expand Up @@ -1077,6 +1083,11 @@ class Builder {
map.callback_manager.set('set_status', status => this.status_bar.html(status))
}

_updateTooltipSetting (setting) {
this.map.behavior.toggleLabelMouseover(setting && setting.includes('label'))
this.map.behavior.toggleObjectMouseover(setting && setting.includes('object'))
}

/**
* Define keyboard shortcuts
*/
Expand Down
Loading

0 comments on commit 521bbd3

Please sign in to comment.