JBrowse 2 · Build Your Own examples

Scalebar and gridlines

Drag across the scalebar to zoom, hover to read the base.

View source — 158 lines
import { useState } from 'react'

import { usePalette } from '@jbrowse/core/ui/PaletteContext'
import {
  EmbedProvider,
  Gridlines,
  RegionSeams,
  Scalebar,
  TrackStack,
  useRubberband,
} from '@jbrowse/display-ui/embed'
import { useCreateViewState } from '@jbrowse/react-linear-genome-view2'
import { observer } from 'mobx-react'

import type { LinearGenomeViewModel } from '@jbrowse/react-linear-genome-view2'

const PointerGuide = observer(function PointerGuide({
  view,
  x,
}: {
  view: LinearGenomeViewModel
  x: number
}) {
  const palette = usePalette()
  const { refName, coord, oob } = view.pxToBp(x)
  return oob ? null : (
    <div
      data-testid="pointer-guide"
      style={{
        position: 'absolute',
        top: 0,
        bottom: 0,
        left: 0,
        zIndex: 4,
        pointerEvents: 'none',
        transform: `translateX(${x}px)`,
      }}
    >
      <div
        style={{
          position: 'absolute',
          top: 0,
          bottom: 0,
          width: 1,
          background: palette.text.primary,
        }}
      />
      <span
        style={{
          position: 'absolute',
          top: 2,
          left: Math.min(Math.max(-x, -60), view.width - x - 120),
          width: 120,
          textAlign: 'center',
          fontSize: '0.7rem',
          lineHeight: '16px',
          whiteSpace: 'nowrap',
          color: palette.text.primary,
          background: palette.background.paper,
          boxShadow: `0 0 0 1px ${palette.divider}`,
        }}
      >
        {refName}:{coord.toLocaleString('en-US')}
      </span>
    </div>
  )
})

const Demo = observer(function Demo({ view }: { view: LinearGenomeViewModel }) {
  const palette = usePalette()
  const { range, props } = useRubberband(view)
  const [pointerX, setPointerX] = useState<number>()
  return (
    <div
      onPointerMove={event => {
        setPointerX(
          event.clientX - event.currentTarget.getBoundingClientRect().left,
        )
      }}
      onPointerLeave={() => {
        setPointerX(undefined)
      }}
    >
      <TrackStack view={view}>
        <Gridlines view={view} />
        <Scalebar
          view={view}
          data-testid="scalebar"
          style={{ cursor: 'crosshair', touchAction: 'none' }}
          {...props}
        />
        <RegionSeams view={view} />
        {range ? (
          <div
            data-testid="rubberband"
            style={{
              position: 'absolute',
              top: 0,
              bottom: 0,
              left: range.left,
              width: range.right - range.left,
              zIndex: 4,
              pointerEvents: 'none',
              background: `color-mix(in srgb, ${palette.primary.main} 20%, transparent)`,
            }}
          />
        ) : pointerX === undefined ? null : (
          <PointerGuide view={view} x={pointerX} />
        )}
      </TrackStack>
    </div>
  )
})

const ScalebarAndGridlines = observer(function ScalebarAndGridlines() {
  const state = useCreateViewState({
    assembly: {
      name: 'hg38',
      uri: 'https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz',
      refNameAliases: {
        uri: 'https://jbrowse.org/genomes/GRCh38/hg38_aliases.txt',
      },
    },
    tracks: [
      {
        trackId: 'hg38_phylop',
        name: 'phyloP 100-way conservation',
        uri: 'https://jbrowse.org/demos/phylop/hg38.phyloP100way.brca1.bw',
        displayDefaults: {
          height: 100,
          encoding: { color: { value: '#3a7ca5' } },
        },
      },
      {
        trackId: 'hg38_genes',
        name: 'RefSeq curated genes',
        uri: 'https://jbrowse.org/ucsc/hg38/ncbiRefSeqCurated.gff.gz',
        index: 'https://jbrowse.org/ucsc/hg38/ncbiRefSeqCurated.gff.gz.csi',
        displayDefaults: { height: 120 },
      },
    ],
    configuration: { preferences: { scrollZoom: true } },
    view: {
      loc: 'chr17:43,044,295..43,060,000 chr17:43,100,000..43,125,364',
      tracks: ['hg38_phylop', 'hg38_genes'],
    },
  })
  if (!state) {
    return null
  }
  return (
    <EmbedProvider session={state.session}>
      <Demo view={state.session.view} />
    </EmbedProvider>
  )
})

export default ScalebarAndGridlines