vue可视化-D3.js绘制聚类热图

聚类热图一般情况下,多通过Python或R进行绘制,由于客户需求,需要在图形上进行一些交互操作,于是乎决定通过D3.js进行绘制

  • 准备工作

引入d3.js

vue 复制代码
import * as d3 from "d3";//这里使用的是6.7.0

准备数据

vue 复制代码
data(){
    return {
        dataGroup: [
            {
                "group": "ENSG00000167900",
                "variable": "a",
                "value": "0.611586075"
            },
            {
                "group": "ENSG00000117399",
                "variable": "a",
                "value": "0.632157568"
            },
            
            ...//数据量大,这里省略
            
            {
                "group": "ENSG00000276043",
                "variable": "f",
                "value": "-0.432913538"
            },
            {
                "group": "ENSG00000088325",
                "variable": "f",
                "value": "-0.449567023"
            },
            {
                "group": "ENSG00000112984",
                "variable": "f",
                "value": "-0.439659798"
            }
        ],
        sampleClusterData: {
            "children": [
                    {
                        "children": [
                            {
                                "name": "e"
                            },
                            {
                                "children": [
                                    {
                                        "name": "d"
                                    },
                                    {
                                        "name": "f"
                                    }
                                ],
                                "name": "node1"
                            }
                        ],
                        "name": "node2"
                    },
                    {
                        "children": [
                            {
                                "name": "b"
                            },
                            {
                                "children": [
                                    {
                                        "name": "a"
                                    },
                                    {
                                        "name": "c"
                                    }
                                ],
                                "name": "node3"
                            }
                        ],
                        "name": "node4"
                    }
                ],
                "name": "node5"
            },
            geneClusterData: {
                "name": "node19",
                "children": [
                    {
                        "name": "ENSG00000282885"
                    },
                    {
                        "name": "node18",
                        "children": [
                            {
                                "name": "node16",
                                "children": [
                                    {
                                        "name": "node3",
                                        "children": [
                                            {
                                                "name": "ENSG00000148773"
                                            },
                                            {
                                                "name": "ENSG00000183856"
                                            }
                                        ]
                                    },
                                    {
                                        "name": "node13",
                                        "children": [
                                            {
                                                "name": "ENSG00000167900"
                                            },
                                            {
                                                "name": "ENSG00000117399"
                                            }
                                        ]
                                    }
                                ]
                            },
                            {
                                "name": "node17",
                                "children": [
                                    {
                                        "name": "ENSG00000276043"
                                    },
                                    {
                                        "name": "node15",
                                        "children": [
                                            {
                                                "name": "node9",
                                                "children": [
                                                    {
                                                        "name": "ENSG00000237649"
                                                    },
                                                    {
                                                        "name": "node7",
                                                        "children": [
                                                            {
                                                                "name": "ENSG00000106333"
                                                            },
                                                            {
                                                                "name": "node5",
                                                                "children": [
                                                                    {
                                                                        "name": "ENSG00000013810"
                                                                    },
                                                                    {
                                                                        "name": "ENSG00000127564"
                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    }
                                                ]
                                            },
                                            {
                                                "name": "node14",
                                                "children": [
                                                    {
                                                        "name": "node10",
                                                        "children": [
                                                            {
                                                                "name": "ENSG00000171848"
                                                            },
                                                            {
                                                                "name": "node4",
                                                                "children": [
                                                                    {
                                                                        "name": "ENSG00000089685"
                                                                    },
                                                                    {
                                                                        "name": "ENSG00000166508"
                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    },
                                                    {
                                                        "name": "node12",
                                                        "children": [
                                                            {
                                                                "name": "node1",
                                                                "children": [
                                                                    {
                                                                        "name": "ENSG00000088325"
                                                                    },
                                                                    {
                                                                        "name": "ENSG00000112984"
                                                                    }
                                                                ]
                                                            },
                                                            {
                                                                "name": "node11",
                                                                "children": [
                                                                    {
                                                                        "name": "node6",
                                                                        "children": [
                                                                            {
                                                                                "name": "ENSG00000186185"
                                                                            },
                                                                            {
                                                                                "name": "node2",
                                                                                "children": [
                                                                                    {
                                                                                        "name": "ENSG00000111206"
                                                                                    },
                                                                                    {
                                                                                        "name": "ENSG00000166851"
                                                                                    }
                                                                                ]
                                                                            }
                                                                        ]
                                                                    },
                                                                    {
                                                                        "name": "node8",
                                                                        "children": [
                                                                            {
                                                                                "name": "ENSG00000011426"
                                                                            },
                                                                            {
                                                                                "name": "ENSG00000131747"
                                                                            }
                                                                        ]
                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
    }
}
  1. 创建一个容器
html 复制代码
<div id="my_dataviz"></div>
  1. 设置图形的尺寸和边距
js 复制代码
const margin = {
                top: 80,
                right: 140,
                bottom: 30,
                left: 100
            },
                width = 600 - margin.left - margin.right,
                height = 600 - margin.top - margin.bottom;
  1. 将SVG对象附加到页面主体
js 复制代码
const svg = d3.select("#my_dataviz")
                .append("svg")
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
                .append("g")
                .attr("id", "content")
                .attr("transform", `translate(${margin.left}, ${margin.top})`);
  1. 将sampleClusterData和geneClusterData分别处理
js 复制代码
function cluster(dataset, type) {
    let xArr = [];
    let yArr = [];
    let tree = data => {
        const root = d3.hierarchy(data)
            .sort((a, b) => (a.height - b.height) || a.data.name.localeCompare(b.data.name));
      if (type == 'y') {
          return d3.cluster().size([height, 80]).separation(() => 2)(root);
      } else {
          return d3.cluster().size([width, 50]).separation(() => 2)(root);
      }
const root = tree(dataset);

let x0 = Infinity;
let x1 = -x0;
root.each(d => {
    if (d.x > x1) {
        x1 = d.x;
    }
    if (d.x < x0) {
        x0 = d.x
    }
    if (type == 'x') {
       d.x = (d.y ^= d.x ^= d.y) ^ d.x;
    }
});

    if (type == 'y') {
        const g = svg.append("g")
            .attr("font-family", "sans-serif")
            .attr("font-size", 10)
            .attr("transform", `translate(-80,0)`);

        g.append("g")
            .attr("fill", "none")
            .attr("stroke", "#555")
            .attr("stroke-opacity", 0.4)
            .attr("stroke-width", 1.5)
            .selectAll("path")
            .data(root.links())
            .join("path")
            .attr("d", d => `M${d.target.y},${d.target.x}
                            L${d.source.y},${d.target.x}
                            ${d.source.y},${d.source.x}
                            ${d.source.y},${d.source.x}`);

        g.append("g")
            .attr("stroke-linejoin", "round")
            .attr("stroke-width", 3)
            .selectAll("g")
            .data(root.descendants().reverse())
            .join("g")
            .attr("transform", d => {
                if (!d.children) {
                    yArr.push(d.data.name)
                }
                return `translate(${d.y},${d.x})`
            });
        return yArr
    } else {
        const g = svg.append("g")
            .attr("font-family", "sans-serif")
            .attr("font-size", 10)
            .attr("transform", `translate(0,-50)`);
        g.append("g")
            .attr("fill", "none")
            .attr("stroke", "#555")
            .attr("stroke-opacity", 0.4)
            .attr("stroke-width", 1.5)
            .selectAll("path")
            .data(root.links())
            .join("path")
            .attr("d", d => `M${d.target.y},${d.target.x}
                            L${d.target.y},${d.source.x}
                            ${d.source.y},${d.source.x}
                            ${d.source.y},${d.source.x}`);

        g.append("g")
            .attr("stroke-linejoin", "round")
            .attr("stroke-width", 3)
            .selectAll("g")
            .data(root.descendants().reverse())
            .join("g")
            .attr("transform", d => {
                if (!d.children) {
                    xArr.push(d.data.name)
                }
                return `translate(${d.y},${d.x})`
            });
        return xArr
    }
}
  1. 构建X轴Y轴并渲染sampleClusterData和geneClusterData处理后的数据
js 复制代码
// 行和列的标签->称为"group"和"variable"列的唯一标识符。
const myGroups = Array.from(new Set(this.dataGroup.map(d => d.group)))
const myVars = Array.from(new Set(this.dataGroup.map(d => d.variable)))
cluster(this.sampleClusterData, "x");
cluster(this.geneClusterData, "y");
// 构建X刻度和轴:
const x = d3.scaleBand()
    .range([0, width])
    .domain(myVars)
    .padding(0.005);
svg.append("g")
    .style("font-size", 15)
    .attr("transform", `translate(0, ${height})`)
    .call(d3.axisBottom(x).tickSize(0))
    .select(".domain").remove()

// 建立Y刻度和轴:
const y = d3.scaleBand()
    .range([height, 0])
    .domain(myGroups)
    .padding(0.005);
svg.append("g")
    .style("font-size", 15)
    .attr("transform", `translate(${width}, 0)`)
    .call(d3.axisRight(y).tickSize(0))
    .select(".domain").remove()
  1. 建立颜色刻度、创建工具提示
js 复制代码
// 建立颜色刻度
const myColor = d3.scaleSequential()
    .interpolator(d3.interpolateInferno)
    .domain([-1, 1])

// 创建工具提示
const tooltip = d3.select("#my_dataviz")
    .append("div")
    .style("opacity", 0)
    .attr("class", "tooltip")
    .style("background-color", "white")
    .style("border", "solid")
    .style("border-width", "2px")
    .style("border-radius", "5px")
    .style("padding", "5px")

// 当用户悬停/移动/离开单元格时更改工具提示的三个函数
const mouseover = function (event, d) {
    tooltip
        .style("opacity", 1)
    d3.select(this)
        .style("stroke", "#666")
        .style("opacity", 1)
}
const mousemove = function (event, d) {
    tooltip
        .html("The exact value of<br>this cell is: " + d.value)
        .style("left", (event.x) / 2 + "px")
        .style("top", (event.y) / 2 + "px")
}
const mouseleave = function (event, d) {
    tooltip
        .style("opacity", 0)
    d3.select(this)
        .style("stroke", "none")
        .style("opacity", 0.8)
}
  1. 渲染dataGroup为矩形
js 复制代码
svg.selectAll()
   .data(this.dataGroup)
   .join("rect")
   .attr("x", function (d) {
       return x(d.variable)
   })
   .attr("y", function (d) {
       return y(d.group)
   })
   .attr("width", x.bandwidth())
   .attr("height", y.bandwidth())
   .style("fill", function (d) {
       return myColor(d.value)
   })
   .style("stroke-width", 2)
   .style("stroke", "none")
   .style("opacity", 0.8)
   .on("mouseover", mouseover)
   .on("mousemove", mousemove)
   .on("mouseleave", mouseleave)
相关推荐
如若12311 分钟前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~1 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语1 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport1 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg1 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww1 小时前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
m0_748254881 小时前
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
前端·vue.js·elementui
星就前端叭2 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
m0_748234522 小时前
前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)
前端·webpack·node.js
Web阿成2 小时前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript