前言
在生物信息学项目中,经常需要查看测序数据在基因组上的比对情况。
传统方式通常使用桌面版 IGV(Integrative Genomics Viewer),但对于 Web 系统来说,用户更希望直接在浏览器中查看 BAM 文件,而无需额外下载软件。
本文记录如何在 Vue3 + Pinia + Element Plus 项目中集成 IGV.js,实现:
- BAM 文件在线浏览
- 基因区域快速跳转
- 动态切换样本
- Token 权限认证
- Dialog 弹窗展示
最终效果:
- 点击位点直接打开 IGV
- 自动定位到指定基因区域
- 显示 BAM 比对结果
- 支持不同样本切换
一、什么是 IGV.js
IGV.js 是 Broad Institute 开源的 Web 版基因组浏览器。
官网:
GitHub:
主要特点:
-
纯前端运行
-
无需后端解析 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 版基因组可视化平台。