javascript - 将两个 javascript 视觉效果添加到 html 页面
问题描述
我正在尝试将两个 d3 视觉效果添加到我的 index.html 页面,但一次只显示一个视觉效果。两种视觉效果使用相同的代码,唯一的区别是使用的数据。它们单独运行良好,但我无法让它们一起出现在同一页面上。
var margins = {
top: 20,
bottom: 300,
left: 30,
right: 100
};
var height = 800;
var width = 500;
var totalWidth = width + margins.left + margins.right;
var totalHeight = height + margins.top + margins.bottom;
var svg = d3.select('body')
.append('svg')
.attr('width', totalWidth)
.attr('height', totalHeight);
var graphGroup = svg.append('g')
.attr('transform', "translate(" + margins.left + "," + margins.top + ")");
var levels = [
[
{id: 'Gaia'},
{id:'Ouranos', parents:['Gaia']}
],
[
{id:'Aphrodite', parents:['Ouranos']},
{id: 'Themis', parents: ['Gaia', 'Ouranos']},
{id: 'Mnemosyne', parents: ['Gaia', 'Ouranos']},
{id: 'Hyperion', parents: ['Gaia', 'Ouranos']},
{id: 'Thea', parents: ['Gaia', 'Ouranos']},
{id: 'Crius', parents: ['Gaia', 'Ouranos']},
{id: 'Oceanus', parents: ['Gaia', 'Ouranos']},
{id: 'Tethys', parents: ['Gaia', 'Ouranos']},
{id: 'Iapetus', parents: ['Gaia', 'Ouranos']},
{id: 'Coeus', parents: ['Gaia', 'Ouranos']},
{id: 'Phoebe', parents: ['Gaia','Ouranos']},
{id: 'Kronos', parents: ['Gaia', 'Ouranos']},
{id: 'Rhea', parents: ['Gaia', 'Ouranos']},
],
[
{id: 'Pleione', parents:['Oceanus','Tethys']},
{id:'Atlas',parents:['Iapetus']},
{id:'Semele'},
{id:'Maia', parents:['Pleione','Atlas']},
{id:'Leto',parents:['Coeus','Phoebe']},
{id:'Zeus',parents:['Kronos','Rhea']},
{id:'Hera',parents:['Kronos','Rhea']},
{id:'Poseidon',parents:['Kronos','Rhea']},
{id:'Amphitrite'},
{id:'Hestia',parents:['Kronos','Rhea']},
{id:'Hades',parents:['Kronos','Rhea']},
{id:'Demeter',parents:['Kronos','Rhea']},
],
[
{id:'Dionysus',parents:['Semele','Zeus']},
{id:'Hermes',parents:['Maia','Zeus']},
{id:'Apollo',parents:['Leto','Zeus']},
{id:'Artemis',parents:['Leto','Zeus']},
{id:'Athena',parents:['Zeus']},
{id:'Ares',parents:['Zeus','Hera']},
{id:'Hephaistos',parents:['Zeus','Hera']},
{id:'Hebe',parents:['Zeus','Hera']},
{id:'Triton',parents:['Poseidon','Amphitrite']},
{id:'Benthesikyme',parents:['Poseidon','Amphitrite']},
{id:'Rhodos',parents:['Poseidon','Amphitrite']},
{id:'Persephone',parents:['Zeus','Demeter']},
{id:'Zagreus', parents:['Hades','Persephone']},
{id:'Macaria', parents:['Hades','Persephone']}
]
]
// precompute level depth
levels.forEach((l, i) => l.forEach(n => n.level = i));
var nodes = levels.reduce(((a, x) => a.concat(x)), []);
var nodes_index = {};
nodes.forEach(d => nodes_index[d.id] = d);
// objectification
nodes.forEach(d => {
d.parents = (d.parents === undefined ? [] : d.parents).map(p => nodes_index[p])
})
// precompute bundles
levels.forEach((l, i) => {
var index = {}
l.forEach(n => {
if (n.parents.length == 0) {
return
}
var id = n.parents.map(d => d.id).sort().join('--')
if (id in index) {
index[id].parents = index[id].parents.concat(n.parents)
} else {
index[id] = {
id: id,
parents: n.parents.slice(),
level: i
}
}
n.bundle = index[id]
})
l.bundles = Object.keys(index).map(k => index[k])
l.bundles.forEach((b, i) => b.i = i)
})
var links = []
nodes.forEach(d => {
d.parents.forEach(p => links.push({
source: d,
bundle: d.bundle,
target: p
}))
})
var bundles = levels.reduce(((a, x) => a.concat(x.bundles)), [])
// reverse pointer from parent to bundles
bundles.forEach(b => b.parents.forEach(p => {
if (p.bundles_index === undefined) {
p.bundles_index = {}
}
if (!(b.id in p.bundles_index)) {
p.bundles_index[b.id] = []
}
p.bundles_index[b.id].push(b)
}))
nodes.forEach(n => {
if (n.bundles_index !== undefined) {
n.bundles = Object.keys(n.bundles_index).map(k => n.bundles_index[k])
} else {
n.bundles_index = {}
n.bundles = []
}
n.bundles.forEach((b, i) => b.i = i)
})
links.forEach(l => {
if (l.bundle.links === undefined) {
l.bundle.links = []
}
l.bundle.links.push(l)
})
// layout
const padding = 20
const node_height = 22
const node_width = 70
const bundle_width = 14
const level_y_padding = 16
const metro_d = 4
const c = 16
const min_family_height = 16
nodes.forEach(n => n.height = (Math.max(1, n.bundles.length) - 1) * metro_d)
var x_offset = padding
var y_offset = padding
levels.forEach(l => {
x_offset += l.bundles.length * bundle_width
y_offset += level_y_padding
l.forEach((n, i) => {
n.x = n.level * node_width + x_offset
n.y = node_height + y_offset + n.height / 2
y_offset += node_height + n.height
})
})
var i = 0
levels.forEach(l => {
l.bundles.forEach(b => {
b.x = b.parents[0].x + node_width + (l.bundles.length - 1 - b.i) * bundle_width
b.y = i * node_height
})
i += l.length
})
links.forEach(l => {
l.xt = l.target.x
l.yt = l.target.y + l.target.bundles_index[l.bundle.id].i * metro_d - l.target.bundles.length * metro_d / 2 + metro_d / 2
l.xb = l.bundle.x
l.xs = l.source.x
l.ys = l.source.y
})
// compress vertical space
var y_negative_offset = 0
levels.forEach(l => {
y_negative_offset += -min_family_height + d3.min(l.bundles, b => d3.min(b.links, link => (link.ys - c) - (link.yt + c))) || 0
l.forEach(n => n.y -= y_negative_offset)
})
// very ugly, I know
links.forEach(l => {
l.yt = l.target.y + l.target.bundles_index[l.bundle.id].i * metro_d - l.target.bundles.length * metro_d / 2 + metro_d / 2
l.ys = l.source.y
l.c1 = l.source.level - l.target.level > 1 ? node_width + c : c
l.c2 = c
})
const cluster = d3.cluster()
.size([width, height]);
const root = d3.hierarchy(links);
cluster(root);
let oValues = Object.values(root)[0];
let linkks = oValues.map(x => x.bundle.links);
linkks.forEach((linkk) => {
//nodeG1 are nodes that have children
let nodeG1 = svg.append("g")
.selectAll("circle")
.data(linkk)
.join("circle")
.attr("cx", d => d.target.x)
.attr("cy", d => d.target.y)
.attr("fill", "lightblue")
.attr("stroke", (d) => {
return '#' + Math.floor(16777215 * Math.sin(3 * Math.PI / (5 * (parseInt(d.target.level) + 1)))).toString(16);
})
.attr("r", 6);
//nodeG11 are nodes that have parents
let nodeG11 = svg.append("g")
.selectAll("circle")
.data(linkk)
.join("circle")
.attr("cx", d => d.source.x)
.attr("cy", d => d.source.y)
.attr("fill", "gray")
.attr("stroke", (d) => {
return '#' + Math.floor(16777215 * Math.sin(3 * Math.PI / (5 * (parseInt(d.source.level) + 1)))).toString(16);
})
.attr("r", 6);
let nodeG2 = svg.append("g")
.attr("font-family", "papyrus")
.attr("font-size", 16)
.selectAll("text")
.data(linkk)
.join("text")
.attr("class", "text")
.attr("x", d => d.target.x + padding)
.attr("y", d => d.target.y)
.text(d => d.target.id )
.attr("fill", (d) => {
return '#' + 0;
});
let nodeG22 = svg.append("g")
.attr("font-family", "papyrus")
.attr("font-size", 16)
.selectAll("text")
.data(linkk)
.join("text")
.attr("class", "text")
.attr("x", d => d.source.x + padding)
.attr("y", d => d.source.y)
.text(d => d.source.id )
.attr("fill", (d) => {
return '#' + 0;
});
let nodeG = svg.append('g')
.attr('class', 'node')
.selectAll("path")
.data(linkk)
.join('path')
.attr("class", "link")
.attr("d", d3.linkHorizontal()
.source(d => [d.xs, d.ys])
.target(d => [d.xt, d.yt]))
.attr("fill", "none")
.attr("stroke-opacity", 10)
.attr("stroke-width", .75)
.attr("stroke", (d) => {
return '#' + Math.floor(16776960 * Math.sin(3 * Math.PI / (4 * parseInt(d.source.level)))).toString(16);
});
});
path {
display: block;
z-index: 0;
}
text,
circle {
display: block;
z-index: 1000;
}
<!DOCTYPE html>
<link rel="stylesheet" type="text/css" href="greek.css"/>
<link rel="stylesheet" type="text/css" href="main.css"/>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Here</title>
</head>
<body style="background-color: antiquewhite;">
<center>
<h style="font-size:50px">Greek and Norse Gods: </h>
</center>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="greek.js"></script>
<script src="norse.js"></script>
</body>
</html>
解决方案
看起来只有一个 svg 元素。我认为您将两个树结构附加到相同的 svg 和元素,并用第二个覆盖第一个。尝试创建两个 svg 元素并分别附加希腊和挪威节点。没有机会测试它,但是,也许它有帮助。
推荐阅读
- python - 正则表达式:从文本中提取一些信息
- here-api - 如何理解 HERE-API 请求结果中的代码
- javascript - Html 和 Javascript 发送带有文本元素的电子邮件
- jenkins - Jenkins 管道在网站中发送 zip 文件
- docker - 如何在 docker go 客户端中创建具有内存限制的容器
- sql - 更新不同的数据类型列
- node.js - Eslint - Prefer Object destructing (prefer destructing)
- molecule - 失败时如何不销毁容器
- hapijs - 如何在 Hapi/Glue/Compose 中使用密码?
- python - 使用先前索引进行 for 循环计算的问题