Navigate & control
Navigate to a region, lock down zoom and pan, and toggle tracks from your own code.
Disable zoom and side scroll
For a dashboard or report where the page — not the view — should own scroll and
zoom, a small inline plugin overrides the view model’s scrollTo and zoomTo
with no-ops. JBrowse plugins can wrap any state-model action, so this needs no
change to the embedded component; register it through the plugins option.
The lock covers wheel zoom and click-drag side-scroll and leaves the rest of the
view interactive — but it is not only a gesture lock. navTo and moveTo reach
the view through those same two actions, so a locked view also stops responding
to location and navToLocString: pin its starting scale and offset in a
defaultSession instead.
Every header control routes through those two actions too, so the pan arrows,
zoom buttons, zoom slider and search box go inert while still looking live. This
demo sets hideHeader: true so they are not offered; the MiniControls that
replaces the header keeps two zoom buttons, which stay inert.
If nothing in the view needs to be interactive, don’t lock a live one:
export it to SVG, or render one ahead of
time with the @jbrowse/img CLI,
and put that image on the page.
See inline plugins for the general pattern.
View source — 66 lines
import Plugin from '@jbrowse/core/Plugin'
import { extendViewType } from '@jbrowse/core/pluggableElementTypes'
import { types } from '@jbrowse/mobx-state-tree'
import {
JBrowseLinearGenomeView,
useCreateViewState,
} from '@jbrowse/react-linear-genome-view2'
import type PluginManager from '@jbrowse/core/PluginManager'
class MyPlugin extends Plugin {
name = 'MyPlugin'
install(pluginManager: PluginManager) {
// #region extend
extendViewType(pluginManager, 'LinearGenomeView', stateModel =>
types.compose(
stateModel,
types.model().actions(() => ({
zoomTo: () => {},
scrollTo: () => {},
})),
),
)
// #endregion
}
configure() {}
}
export default function WithDisableZoomAndSideScroll() {
const state = useCreateViewState({
assembly: {
name: 'volvox',
uri: 'https://jbrowse.org/genomes/volvox/volvox.2bit',
},
tracks: [
{
type: 'FeatureTrack',
trackId: 'volvox_gff3',
name: 'Volvox genes',
assemblyNames: ['volvox'],
adapter: {
type: 'Gff3TabixAdapter',
uri: 'https://jbrowse.org/code/jb2/main/test_data/volvox/volvox.sort.gff3.gz',
},
},
],
plugins: [MyPlugin],
// every header control routes through zoomTo/scrollTo, so with those
// stubbed the pan arrows, zoom buttons, slider and search box are all
// inert. MiniControls takes the header's place and keeps two zoom buttons
defaultSession: {
name: 'disable-zoom-and-side-scroll',
view: {
id: 'linearGenomeView',
type: 'LinearGenomeView',
hideHeader: true,
},
},
// the lock is not only a gesture lock: navTo/moveTo reach the view through
// the same two actions, so this picks the displayed region but the view
// opens at its default scale rather than on this window. A view that has to
// start somewhere specific wants its bpPerPx/offsetPx on the view above
location: 'ctgA:1105..1221',
})
return <JBrowseLinearGenomeView viewState={state} />
}Show a track programmatically
state.session.view.showTrack('my-track-id') opens a track in response to
something at runtime — a button, a search hit, a prop — rather than at first
mount. hideTrack is its counterpart. For tracks that should be open on first
paint, list them in init instead.
For a track that isn’t in the tracks config at all (a file the user just
picked, a hit from your own search service), register its config on the session
first:
state.session.addTrackConf(trackConf)
state.session.view.showTrack(trackConf.trackId)
addTrackConf takes the same shape as the tracks prop, dedupes by trackId,
and is what the built-in “add track” form uses. Session-added tracks round-trip
through saved sessions.
View source — 61 lines
import {
JBrowseLinearGenomeView,
useCreateViewState,
} from '@jbrowse/react-linear-genome-view2'
import { observer } from 'mobx-react'
import type { ViewModel } from '@jbrowse/react-linear-genome-view2'
const TRACK_ID = 'volvox_gff3'
// `view.tracks` is observable, so an `observer` button knows whether the track
// is open without subscribing to anything — no callback, no local copy of the
// state that can fall out of step with the track selector's own checkbox.
const ToggleTrack = observer(function ToggleTrack({
viewState,
}: {
viewState: ViewModel
}) {
const { view } = viewState.session
const open = !!view.getTrack(TRACK_ID)
return (
<button
onClick={() => {
// showTrack API: https://jbrowse.org/jb2/docs/models/lineargenomeview/#action-showtrack
if (open) {
view.hideTrack(TRACK_ID)
} else {
view.showTrack(TRACK_ID)
}
}}
>
{open ? 'Hide' : 'Show'} the genes track
</button>
)
})
export default function WithShowTrack() {
const state = useCreateViewState({
assembly: {
name: 'volvox',
uri: 'https://jbrowse.org/genomes/volvox/volvox.2bit',
},
tracks: [
{
trackId: TRACK_ID,
name: 'Volvox genes',
uri: 'https://jbrowse.org/code/jb2/main/test_data/volvox/volvox.sort.gff3.gz',
},
],
// the view opens with the track closed, since this page is about opening it
// from your own code. For a track that should be open on first paint, put
// its id in `init.tracks` instead of calling showTrack at construction
init: { loc: 'ctgA:1105..1221' },
})
return (
<div>
<ToggleTrack viewState={state} />
<JBrowseLinearGenomeView viewState={state} />
</div>
)
}