Vue3 + Pinia 集成 IGV.js 实现 BAM 文件在线浏览

前言

在生物信息学项目中,经常需要查看测序数据在基因组上的比对情况。

传统方式通常使用桌面版 IGV(Integrative Genomics Viewer),但对于 Web 系统来说,用户更希望直接在浏览器中查看 BAM 文件,而无需额外下载软件。

本文记录如何在 Vue3 + Pinia + Element Plus 项目中集成 IGV.js,实现:

  • BAM 文件在线浏览
  • 基因区域快速跳转
  • 动态切换样本
  • Token 权限认证
  • Dialog 弹窗展示

最终效果:

  • 点击位点直接打开 IGV
  • 自动定位到指定基因区域
  • 显示 BAM 比对结果
  • 支持不同样本切换

一、什么是 IGV.js

IGV.js 是 Broad Institute 开源的 Web 版基因组浏览器。

官网:

igv.org/

GitHub:

github.com/igvteam/igv...

主要特点:

  • 纯前端运行

  • 无需后端解析 BAM

  • 支持:

    • BAM / BAI
    • CRAM
    • VCF
    • BED
    • GFF
    • BigWig
  • 支持 hg19、hg38 等参考基因组

  • 支持 locus 定位

  • 支持动态加载 Track


二、安装

复制代码
npm install igv

三、Pinia 封装 IGV Store

为了避免页面频繁创建和销毁 IGV Browser,可以统一放入 Pinia 中管理。

igv.js

js 复制代码
import { defineStore } from "pinia";
import igv from "igv";
import { getToken } from "@/utils/auth.js";

export const useIgvStore = defineStore("igv", () => {

    let browser = null;

    async function init(dom, libraryCode, value) {

        if (browser) return browser;

        browser = await igv.createBrowser(dom, {
            genome: "hg38",
            locus: value,
            tracks: [
                {
                    name: "BAM",
                    type: "alignment",
                    format: "bam",
                    url:
                        import.meta.env.VITE_APP_BASE_URL +
                        `/analysis/locusScreening/bam/${libraryCode}`,
                    indexURL:
                        import.meta.env.VITE_APP_BASE_URL +
                        `/analysis/locusScreening/bai/${libraryCode}`,
                    headers: {
                        Authorization: "Bearer " + getToken()
                    }
                }
            ]
        });
    }

    async function loadTrack(libraryCode) {

        if (!browser) return;

        const track = {
            name: "BAM",
            type: "alignment",
            format: "bam",
            url:
                import.meta.env.VITE_APP_BASE_URL +
                `/analysis/locusScreening/bam/${libraryCode}`,
            indexURL:
                import.meta.env.VITE_APP_BASE_URL +
                `/analysis/locusScreening/bai/${libraryCode}`,
            headers: {
                Authorization: "Bearer " + getToken()
            }
        };
        browser.removeTrackByName("BAM");
        await browser.loadTrack(track);
    }
    function goto(locus) {
        if (browser) {
            browser.search(locus);
        }
    }
    function destroy() {
        if (browser) {
            browser.dispose();
            browser = null;
        }
    }
    return {
        browser,
        init,
        loadTrack,
        goto,
        destroy
    };
});

四、核心功能解析

1. 初始化浏览器

ini 复制代码
browser = await igv.createBrowser(dom, {
    genome: "hg38",
    locus: value,
});

参数说明:

参数 说明
genome 参考基因组
locus 初始定位区域
tracks 初始轨道

例如:

vbnet 复制代码
locus: "chr8:127736588-127739371"

打开后会直接定位到:

复制代码
chr8
127736588
127739371

区域。


2. BAM 轨道加载

lua 复制代码
{
    name: "BAM",
    type: "alignment",
    format: "bam"
}

IGV.js 会自动识别:

复制代码
BAM + BAI

并读取对应区域的数据。


3. Token 权限认证

很多项目中的 BAM 文件接口需要登录后才能访问。

IGV.js 支持自定义 Header:

css 复制代码
headers: {
    Authorization: "Bearer " + getToken()
}

这样就可以直接访问受保护资源。


4. 动态切换样本

例如:

arduino 复制代码
await loadTrack("sample001");
await loadTrack("sample002");

内部实现:

csharp 复制代码
browser.removeTrackByName("BAM");

await browser.loadTrack(track);

这样无需重新创建浏览器。

用户体验更好。


5. 跳转基因区域

ini 复制代码
browser.search(locus);

封装:

c 复制代码
goto("chr7:55191822-55200000");

即可快速定位。

常用于:

  • 表格点击位点
  • VCF变异列表
  • SNP详情

直接联动 IGV。


五、Dialog 弹窗封装

为了避免占满整个页面,可以放在 Element Plus Dialog 中。

打开弹窗

ini 复制代码
function open({ libraryCode, locus }) {

    libraryCodeRef.value = libraryCode;

    locusInput.value = locus;

    visible.value = true;
}

调用:

php 复制代码
igvDialogRef.value.open({
    libraryCode: row.libraryCode,
    locus: row.locus
});

Dialog 打开后初始化

ini 复制代码
@opened="igvInit"
csharp 复制代码
async function igvInit() {

    igvStore.destroy();

    await igvStore.init(
        igvDiv.value,
        libraryCodeRef.value,
        locusInput.value
    );
}

原因:

Element Dialog 动画未结束时:

ini 复制代码
clientWidth = 0

会导致 IGV 渲染异常。

因此推荐:

复制代码
opened

事件中初始化。


六、样式优化

为了适应后台管理系统布局:

css 复制代码
.igv-show-overlay .el-dialog {
    width: 100% !important;
    height: calc(100vh - 94px);
}

实现:

复制代码
顶部保留导航栏
左侧保留菜单栏
中间全屏展示 IGV

效果类似:

┌───────────────────────┐

│ Header │

├───────┬───────────────┤

│ Menu │ IGV │

│ │ │

│ │ │

└───────┴───────────────┘


七、后端接口设计

BAM:

bash 复制代码
GET /analysis/locusScreening/bam/{libraryCode}

返回:

复制代码
xxx.bam

BAI:

bash 复制代码
GET /analysis/locusScreening/bai/{libraryCode}

返回:

复制代码
xxx.bam.bai

注意:

必须支持:

makefile 复制代码
Accept-Ranges: bytes

否则 IGV 无法进行随机读取。

例如 SpringBoot:

vbscript 复制代码
response.setHeader("Accept-Ranges", "bytes");

java 复制代码
@GetMapping("/bam/{libraryCode}")
public ResponseEntity<Resource> getBam(@PathVariable String libraryCode) {
    File file = FileUtil.getFile(tumorAnalysisProperties.getBamPath() + File.separator + libraryCode + ".final.bam");
    if (!file.exists()) {
        return ResponseEntity.notFound().build();
    }
    Resource resource = new FileSystemResource(file);
    return ResponseEntity.ok()
            .header("Accept-Ranges", "bytes").body(resource);
}

@GetMapping("/bai/{libraryCode}")
public ResponseEntity<Resource> getBai(@PathVariable String libraryCode) {
    File file = FileUtil.getFile(tumorAnalysisProperties.getBamPath() + File.separator + libraryCode + ".final.bam.bai");
    if (!file.exists()) {
        return ResponseEntity.notFound().build();
    }
    return ResponseEntity.ok()
            .header("Accept-Ranges", "bytes")
            .body(new FileSystemResource(file));
}

八、常见问题

1. BAM 能下载但 IGV 不显示

检查:

复制代码
BAM
BAI
参考基因组

是否一致。

例如:

复制代码
hg38 BAM
hg19 Reference

会直接无法定位。


2. 出现 Range 请求错误

检查服务器是否支持:

css 复制代码
206 Partial Content

IGV 大文件依赖 Range 请求。


3. Dialog 打开空白

不要在:

复制代码
mounted

初始化。

改为:

css 复制代码
@opened

初始化。


4. 多次打开越来越卡

记得销毁:

ini 复制代码
browser.dispose();

否则会残留大量 DOM 和监听器。


九、总结

通过 Vue3 + Pinia + IGV.js,可以非常方便地实现在线基因浏览功能。

本文实现了:

✅ BAM 在线浏览

✅ BAI 索引支持

✅ Token 认证

✅ Pinia 状态管理

✅ 动态切换样本

✅ 基因区域跳转

✅ Element Plus Dialog 集成

对于变异筛查、肿瘤分析、WES/WGS 平台、遗传病分析系统等场景,都具有较高的实用价值。

后续还可以扩展:

  • VCF Track
  • BED Annotation
  • Gene Track
  • BigWig Coverage
  • 多样本对比
  • 截图导出
  • 位点联动分析

打造完整的 Web 版基因组可视化平台。

相关推荐
孟陬1 小时前
Claude Code 巧思 `Ctrl+S` 暂存键
前端·后端
雪隐1 小时前
个人电脑玩AI-06让5060 Ti给你打工——不光能画画,Qwen3-TTS还能学人说话,连我老板都信了!
人工智能·后端·python
Oneslide2 小时前
openEuler 17.1GB Everything ISO 离线本地 DNF 源搭建教程
后端
小月土星2 小时前
JavaScript 快速排序:从 pivot、双指针到分治思想
javascript·算法·面试
小月土星2 小时前
JavaScript 递归入门:从 1 到 n 求和,再到数组扁平化
javascript·算法·面试
蝎子莱莱爱打怪2 小时前
那不是我的黑历史,那是我的来时路啊!😭😭
后端·程序员
用户298698530142 小时前
Java 实现 Word 文档文本与图片提取的方法
java·后端
蝎子莱莱爱打怪2 小时前
XZLL-IM干货系列 04|Netty 长连接实战:Pipeline 怎么排、心跳怎么跳、连接怎么管
后端·微服务·面试
Csvn2 小时前
Rsync 文件同步与增量备份 — 运维的数据守门员
后端