@lipme/vuenomics-visualization-components

Vue 3 and D3 components to display genomics data (genes, coverage, alignments, variants, sequences, BED regions) as synchronized, zoomable tracks.
4,722
Install
npm install @lipme/vuenomics-visualization-components
Latest Version:1.0.0
Vue:3
Last Updated:Oct 20, 2026
Links: Repository  ·  npm
Maintainer: needy_olive

Vuenomics Visualization Components

Vue 3 and D3 components to display genomics data (genes, coverage, alignments, variants, sequences, BED regions) as synchronized, zoomable tracks.

Upgrading from 0.x? See MIGRATION.md.

Install

npm install @lipme/vuenomics-visualization-components

Requirements: Vue 3.5+ (peer dependency). The package is published as ES modules only; Node.js 20.19+ can also require() it.

import {
  GenomeAxis,
  GffViewer,
  CovViewer,
  BamViewer,
  VcfViewer,
  VcfMatrixViewer,
  FastaViewer,
  BedViewer
} from '@lipme/vuenomics-visualization-components'
import '@lipme/vuenomics-visualization-components/style.css'

Or register every component globally with the plugin:

import VuenomicsComponents from '@lipme/vuenomics-visualization-components'
app.use(VuenomicsComponents)

The types of the props, events and loaders (Variant, GffFeature, CoverageData, BedFeature, AxisSettings…) are exported from the package root.

Quick start

Tracks are placed inside a GenomeAxis, which draws the coordinates, gives the tracks their width and margins, and keeps their zoom in sync:

<template>
  <GenomeAxis
    :domain="[6380000, 6420000]"
    :right-boundary="7000000"
    :settings="{ width: 1000 }"
    @update-domain="(domain) => console.log('displayed region', domain)"
  >
    <GffViewer :data="genes" :height="200" track-name="Genes" />
    <CovViewer :data="{ forward: coverage }" track-name="Coverage" />
    <VcfViewer :data="variants" track-name="Variants" />
  </GenomeAxis>
</template>
  • Tracks zoom with the mouse wheel and pan by dragging; ctrl+drag on the axis selects a region.
  • Each GenomeAxis synchronizes only its own tracks: several independent browsers can live on the same page.
  • Every track has a height prop (in pixels) and an optional trackName. Their width and margins are those of the axis.

Common events

Event Payload Emitted by
updateDomain [start, end] the axis and every track, at the end of a zoom, pan or brush gesture (the axis for gestures made on any of its tracks, a track for gestures made on it)
featureSelect the feature GffViewer (ctrl+click, since a click starts a pan), BamViewer, VcfViewer, VcfMatrixViewer, BedViewer
featureHover the feature, or null the same tracks

Loading data from indexed files

The loaders read a region from bgzipped, indexed files served over HTTP (range requests). Each file is opened once: its index and header are downloaded on the first request only, and the readers are only loaded when a loader is first used.

import { getVcf, getFasta, getGff, clearDataCache } from '@lipme/vuenomics-visualization-components'

// coordinates: 0-based start, end excluded
const variants = await getVcf('https://example.org/data.vcf.gz', 'chr1', 10000, 20000)
const sequence = await getFasta('https://example.org/genome.fa.gz', 'chr1', 10000, 20000)
const features = await getGff('https://example.org/genes.gff3.gz', 'chr1', 10000, 20000)
clearDataCache() // forget the opened files, e.g. after they changed on the server

The last argument is an optional options object:

  • tbiUrl (getVcf, getGff), faiUrl and gziUrl (getFasta): URLs of the indexes. They default to the file URL followed by .tbi, .fai and .gzi.
  • signal: an AbortSignal, to cancel the load of a region that is no longer displayed.
const controller = new AbortController()
getVcf(url, 'chr1', 10000, 20000, { tbiUrl: `${url}.tbi`, signal: controller.signal })
controller.abort()

Serve the files without Content-Encoding: gzip (some servers add it for .gz files, which breaks range requests): the .bgz extension avoids it.

getGff returns the GFF3 features with their child features. The GffViewer also needs the level (row) of each feature, in its place field.

Components

GenomeAxis

Prop Type Default Description
domain [number, number] required Displayed region. Setting it again resets the view after a zoom.
rightBoundary number required End of the sequence: panning stops there.
leftBoundary number 0 Start of the sequence.
maxRange number 1000000 Largest region displayed by zooming out.
settings Partial<AxisSettings> { width: 800, height: 40, marginLeft: 20, marginRight: 20 } Size of the axis; width and the margins are also those of its tracks.

Slots: default (the tracks) and screenshot, whose screenshotFunction prop saves the axis and its tracks as a PNG image.

<GenomeAxis :domain="region" :right-boundary="chromosomeLength">
  <!-- tracks -->
  <template #screenshot="{ screenshotFunction }">
    <button @click="screenshotFunction">Take a screenshot</button>
  </template>
</GenomeAxis>

GffViewer

Displays GFF3 features and their child features (mRNA, CDS, UTRs…).

Prop Type Default Description
data PlacedGffFeature[] required GFF3 features (as returned by getGff) with their level in place.
colorService FeatureColors colors by feature type Colors of the features, e.g. a ColorService of @lipme/gffcolors, which colors the CDS from the annotations. TypeColors (exported) takes custom colors by type.
labelFunc (feature: PlacedGffFeature) => string the ID, or the Name Label of the features.
height number 300
<GffViewer
  :data="genes"
  :color-service="new TypeColors({ gene: 'teal', mRNA: 'orange', unknown: 'gray' })"
/>

CovViewer

Displays the coverage of the forward strand, and optionally of the reverse strand (negative scores).

Prop Type Default Description
data { forward: CoverageType[]; reverse?: CoverageType[] } required Intervals { start, end, score } (0-based start, end excluded).
coverageColors { forward: string; reverse: string } { forward: 'blue', reverse: 'red' }
height number 150

BamViewer

Draws alignments on a canvas, with their insertions, deletions and mismatches.

Prop Type Default Description
data BamData required { bams, indels?, mismatches?, gaps? }, each item with its level in place.
alignmentColors AlignmentColors { alignments: 'steelblue', inserts: 'silver', dels: 'black', mismatches: 'crimson' }
height number 300

VcfViewer

Displays variants, colored by type (SNV, insertion, deletion) or by a coloring strategy.

Prop Type Default Description
data Variant[] required Variants, e.g. returned by getVcf.
vcfSettings Partial<VCFSettings> { vcfHeight: 10, dataConcentration: 15, fontSize: 12, labelPosition: 20, vcfMinWidth: 2, maxConcentration: 100, textColor: 'black' } dataConcentration: number of levels, as a percentage of the number of variants; labels are displayed below maxConcentration visible variants.
variantColors VariantColors { snv: 'green', del: 'red', ins: 'blue', unknown: 'black' }
coloringStrategy ColoringStrategyType Colors from the INFO fields, see below. Variants without a color from the strategy keep their type color.
labelFunc (variant: ModifiedVariant) => string type, REF and ALT
height number 300

Two coloring strategies are provided:

import { colorByThreshold, colorByValue } from '@lipme/vuenomics-visualization-components'

// color of the largest of the HET, HOM, NC and WT INFO fields
const byGenotypes = {
  colorInfo: { HET: 'green', HOM: 'blue', NC: 'black', WT: 'red' },
  strategy: colorByThreshold
}
// color of the first regular expression matching the value of an INFO field
const byEffect = {
  field: 'ANN',
  colorInfo: {
    high: { regex: '\\|HIGH\\|', color: 'crimson' },
    low: { regex: '\\|LOW\\|', color: 'gray' }
  },
  strategy: colorByValue
}

VcfMatrixViewer

Displays the genotype of each sample for each variant.

Prop Type Default Description
data Variant[] required Variants with a GENOTYPES() method, like those returned by getVcf.
samplesName string[] required Samples displayed, one per row.
genotypeColors MatrixColorsSettings { '0/0': 'orange', './.': 'red', '1/1': 'indigo', '0/1': 'green', unknown: 'black' } Color of each genotype, with the color of the others (unknown).
vcfSettings Partial<VcfMatrixSettings> { vcfHeight: 10, vcfMinWidth: 2, textColor: 'black' }
height number 300

FastaViewer

Displays a sequence and its complement when the visible region is small enough.

Prop Type Default Description
data string required Sequence, e.g. returned by getFasta.
fastaSettings Partial<FastaSettings> { startPosition: 0, maxSize: 1000, warningMessage: 'Fasta data is too big to be displayed' } startPosition: 1-based position of the first base of data; the sequence is displayed when the visible region is shorter than maxSize, and warningMessage otherwise.
nucleotideColors NucleotideColors { A: 'red', T: 'blue', C: 'green', G: 'yellow', N: 'white' }
height number 300

BedViewer

Displays BED regions, colored by score (or by strand without score), with strand arrows.

Prop Type Default Description
data BedFeature[] required { chromStart, chromEnd, name, strand, score?, place } (0-based start, end excluded; strand 1, -1 or unknown).
bedSettings Partial<BedSettings> { minScore: 0, maxScore: 1000, textColor: 'black', fontSize: 12, labelPosition: 20, minWidth: 2, bedHeight: 10 } Scores from minScore to maxScore get the colors of scoreColors.
scoreColors [string, string] ['blue', 'yellow']
strandColors { '+': string; '-': string; unknown: string } { '+': 'green', '-': 'red', unknown: 'gray' }
labelFunc (feature: BedFeature) => string the name
height number 300

Development

VSCode with the Vue extension is recommended.

Command
npm run dev Demo page (src/views/BaseView.vue) with every component and mock data.
npm run preview Builds the demo into dist-demo and serves it.
npm run build Type-checks and builds the library into dist.
npm run lint / lint:check
npm run test:unit Vitest.
npm run test:component Cypress component tests.
npm run test:e2e Cypress tests of the built demo.
npm run generate-mock-data Regenerates public/mock-data (requires bgzip, tabix and samtools).

Mock data:

  • src/mocks/*.json: genes, coverage, alignments and GFF colors.
  • public/mock-data/: a synthetic bgzipped FASTA (.fai, .gzi), a tabix-indexed VCF and a tabix-indexed GFF3, read through HTTP range requests with the same loaders as an application. Restart npm run dev after regenerating them.

The bgzipped files use the .bgz extension: static servers usually send Content-Encoding: gzip for .gz files, which makes the browser decompress the requested byte ranges and breaks the indexed readers. The public/ folder is not copied into the library build.

Related Packages

vue-svg-tracks

Vue component for displaying tracks

2,109
vue-phylogram

Vue component for displaying phylogenetic trees

1,100 5
@d3plus/vue

Vue 3 components for d3plus visualizations.

732 1,615
@litt1e-p/graphi

a high performance d3.js graph tree data visualization

385 1
@opendata-ai/openchart-vue

Vue 3 components for openchart: , , ,

25,183 33

Version History

Version Released Vue License
1.0.0 ^3.5.0
0.2.0 ^3.4.29
0.1.46 ^3.4.29
0.1.45 ^3.4.29
0.1.44 ^3.4.29