我有一組 D3js 弧形圖,它們運行良好,直到我讓它們只有在使用選單選擇時才可見。將文本包裝在標簽上的函式,名為 wrap() 的函式正在處理加載頁面時可見的圖形,但現在其余部分不呼叫 wrap() 函式,因此標簽文本太寬了。我是在用于選擇圖形的函式中呼叫了 wrap() 函式,還是我的語法不正確?
為了提供更少的代碼,我洗掉了與不是前兩個圖表的所有內容。我曾嘗試使用選擇選單上的選項按鈕之一在 onclick 中呼叫 wrap() 函式,并將其包含在 if/else 陳述句中,但均無效。這是小提琴和代碼,在此先感謝!
https://jsfiddle.net/arkatark/ygakxn4z/3/
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://d3js.org/d3.v4.js"></script>
<style>
text {
font-family: Gotham Narrow, sans-serif;
}
.intro {
font-family: Gotham Narrow, sans-serif;
font-size: 2em;
max-width: 700px;
text-align: center;
margin-left: auto;
margin-right: auto;
}
.container {
position: absolute;
top: 10%;
left: 50%;
margin-top: -50px;
margin-left: -50px;
width: 590px;
}
#graph1822 {
margin-left: auto;
margin-right: auto;
margin-bottom: 100px;
margin-top: 0px;
border-style: solid;
width: 580px;
}
#graph1823,
#graph1824,
#graph1825,
#graph1826,
#graph1827 {
margin-left: auto;
margin-right: auto;
margin-bottom: 100px;
margin-top: 0px;
border-style: solid;
display: none;
width: 580px;
}
#my_dataviz {
margin-left: auto;
margin-right: auto;
margin-bottom: 100px;
margin-top: 0px;
}
label {
font-family: Gotham Narrow, sans-serif;
}
select {
width: 55px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div >
<div >
<h4 >
Arc Diagram of Colonial Secretaries' Correspondence
</h4>
</div>
<div >
<div id="my_dataviz"></div>
<label for="dropdown">Choose a year:</label>
<select id="dropdown">
<option value="0">1822</option>
<option value="1">1823</option>
<option value="2">1824</option>
<option value="3">1825</option>
<option value="4">1826</option>
<option value="5">1827</option>
</select>
<div id="graph1822"></div>
<div id="graph1823"></div>
<div id="graph1824"></div>
<div id="graph1825"></div>
<div id="graph1826"></div>
<div id="graph1827"></div>
</div>
</div>
<script>
// set the dimensions and margins of the graph
var el = document.getElementById("dropdown");
el.addEventListener("change", function() {
var elems = document.querySelectorAll('#graph1822, #graph1823 ,#graph1824 ,#graph1825, #graph1826, #graph1827')
for (var i = 0; i < elems.length; i ) {
elems[i].style.display = 'none'
}
if (this.selectedIndex === 0) {
document.querySelector('#graph1822').style.display = 'block';
document.querySelector('#dropdown').style.outlineColor = '#E9D8A6';
} else if (this.selectedIndex === 1) {
document.querySelector('#graph1823').style.display = 'block';
document.querySelector('#graph1822').style.display = 'none';
document.querySelector('#dropdown').style.outlineColor = '#E9B006';
} else if (this.selectedIndex === 2) {
document.querySelector('#graph1824').style.display = 'block';
document.querySelector('#graph1822').style.display = 'none';
document.querySelector('#dropdown').style.outlineColor = '#BB3E03';
} else if (this.selectedIndex === 3) {
document.querySelector('#graph1825').style.display = 'block';
document.querySelector('#graph1822').style.display = 'none';
document.querySelector('#dropdown').style.outlineColor = '#005F73';
} else if (this.selectedIndex === 4) {
document.querySelector('#graph1825').style.display = 'block';
document.querySelector('#graph1822').style.display = 'none';
document.querySelector('#dropdown').style.outlineColor = '#0A9396';
} else if (this.selectedIndex === 5) {
document.querySelector('#graph1825').style.display = 'block';
document.querySelector('#graph1822').style.display = 'none';
document.querySelector('#dropdown').style.outlineColor = '#BCE6E6';
}
}, false);
// DIAGRAM 1822 //
(function() {
var margin = {
top: 30,
right: 60,
bottom: 30,
left: 60
},
width = 580 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#graph1822")
.append("svg")
.attr("width", width margin.left margin.right)
.attr("height", height margin.top margin.bottom)
.append("g")
.attr("transform",
"translate(" margin.left "," margin.top ")")
// Read data
d3.json("https://raw.githubusercontent.com/arkatark/colsec/main/nodes.json", function(data) {
// List of node names
var allNodes = data.nodes1.map(function(d) {
return d.name
})
// A linear scale to position the nodes on the X axis
var x = d3.scalePoint()
.range([0, width])
.domain(allNodes)
var color = d3.scaleOrdinal().domain([1, 10])
.range(["#E9D8A6", "#E9B006", "#E9B006", "#BB3E03", "#005F73", "#0A9396", "#BCE6E6"]);
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s /).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
x = text.attr("x"),
y = text.attr("y"),
dy = 0, //parseFloat(text.attr("dy")),
tspan = text.text(null)
.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", dy "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", lineNumber * lineHeight dy "em")
.text(word);
}
}
});
}
// Add the circle for the nodes
var nodes = svg
.selectAll("mynodes")
.data(data.nodes1)
.enter()
.append("circle")
.attr("cx", function(d) {
return (x(d.name))
})
.attr("cy", height - 30)
.attr("r", 10)
.style("fill", function(d) {
return color(d.grp)
})
// And give them a label
var labels = svg
.selectAll("mylabels")
.data(data.nodes1)
.enter()
.append("text")
.attr("x", function(d) {
return (x(d.name))
})
.attr("y", height - 10)
.text(function(d) {
return (d.name)
})
.style("text-anchor", "middle")
.style("font-size", "10")
.call(wrap, 100);
// Add links between nodes. Here is the tricky part.
// In my input data, links are provided between nodes -id-, NOT between node names.
// So I have to do a link between this id and the name
var idToNode = {};
data.nodes.forEach(function(n) {
idToNode[n.id] = n;
});
// Cool, now if I do idToNode["2"].name I've got the name of the node with id 2
// Add the links
var links = svg
.selectAll('mylinks')
.data(data.links1)
.enter()
.append('path')
.attr('d', function(d) {
start = x(idToNode[d.source].name) // X position of start node on the X axis
end = x(idToNode[d.target].name) // X position of end node
return ['M', start, height - 30, // the arc starts at the coordinate x=start, y=height-30 (where the starting node is)
'A', // This means we're gonna build an elliptical arc
(start - end) / 1.95, ',', // Next 2 lines are the coordinates of the inflexion point. Height of this point is proportional with start - end distance
(start - end) / 2, 0, 0, ',',
start < end ? 1 : 0, end, ',', height - 30
] // We always want the arc on top. So if end is before start, putting 0 here turn the arc upside down.
.join(' ');
})
.style("fill", "none")
.attr("stroke", "#919191")
var tooltip1 = d3.select("#graph1822")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "#FFFFFF")
.style("border-style", "solid")
.style("border-width", "1px")
.style("position", "absolute")
.style('width', '200px')
// Add the highlighting functionality
nodes
.on('mouseover', function(d) {
// Highlight the nodes: every node is green except of him
nodes.style('fill', function(d) {
return color(d.grp)
})
d3.select(this).style('fill', function(d) {
return color(d.grp)
})
// Highlight the connections
links
.style('stroke', function(link_d) {
return link_d.source === d.id || link_d.target === d.id ? color(d.grp) : '#b8b8b8';
})
.style('stroke-width', function(link_d) {
return link_d.source === d.id || link_d.target === d.id ? 4 : 1;
})
tooltip1
.html(d.name)
.style('text-align', 'center')
.style('font-family', 'Gotham Narrow, sans-serif')
.style('font-size', '.9em')
.style('margin-left', '29%')
.style('margin-right', '30%')
.style("opacity", .8)
.style("stroke", "#EEEEEE")
.style("background-color", "#FFFFFF")
.style("z-index", 20)
.style('padding', '10px')
})
.on('mouseout', function(d) {
nodes.attr("r", '8').style("fill", function(d) {
return color(d.grp)
})
links
.style('stroke', '#919191')
.style('stroke-opacity', 1)
.style('stroke-width', '1')
tooltip1
.style("opacity", 0)
d3.select(this)
.style("stroke", "none")
.style("opacity", 1)
})
})
svg
.append("text")
.attr("text-anchor", "middle")
.style("fill", "#black")
.style("font-size", "17px")
.attr("x", 225)
.attr("y", 40)
.html(" Correspondence from 1822")
})();
// DIAGRAM 1823 //
(function() {
var margin = {
top: 40,
right: 60,
bottom: 30,
left: 60
},
width = 580 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#graph1823")
.append("svg")
.attr("width", width margin.left margin.right)
.attr("height", height margin.top margin.bottom)
.append("g")
.attr("transform",
"translate(" margin.left "," margin.top ")");
// Read data
d3.json("https://raw.githubusercontent.com/arkatark/colsec/main/nodes.json", function(data) {
// List of node names
var allNodes = data.nodes2.map(function(d) {
return d.name
})
// A linear scale to position the nodes on the X axis
var x = d3.scalePoint()
.range([0, width])
.domain(allNodes)
var color = d3.scaleOrdinal().domain([1, 10])
.range(["#E9D8A6", "#E9B006", "#E9B006", "#BB3E03", "#005F73", "#0A9396", "#BCE6E6"]);
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s /).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
x = text.attr("x"),
y = text.attr("y"),
dy = 0, //parseFloat(text.attr("dy")),
tspan = text.text(null)
.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", dy "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", lineNumber * lineHeight dy "em")
.text(word);
}
}
});
}
// Add the circle for the nodes
var nodes = svg
.selectAll("mynodes")
.data(data.nodes2)
.enter()
.append("circle")
.attr("cx", function(d) {
return (x(d.name))
})
.attr("cy", height - 30)
.attr("r", 8)
.style("fill", function(d) {
return color(d.grp)
})
// And give them a label
var labels = svg
.selectAll("mylabels")
.data(data.nodes2)
.enter()
.append("text")
.attr("x", function(d) {
return (x(d.name))
})
.attr("y", height - 10)
.text(function(d) {
return (d.name)
})
.style("text-anchor", "middle")
.style("font-size", "10")
.call(wrap, 130);
// Add links between nodes. Here is the tricky part.
// In my input data, links are provided between nodes -id-, NOT between node names.
// So I have to do a link between this id and the name
var idToNode = {};
data.nodes.forEach(function(n) {
idToNode[n.id] = n;
});
// Cool, now if I do idToNode["2"].name I've got the name of the node with id 2
// Add the links
var links = svg
.selectAll('mylinks')
.data(data.links2)
.enter()
.append('path')
.attr('d', function(d) {
start = x(idToNode[d.source].name) // X position of start node on the X axis
end = x(idToNode[d.target].name) // X position of end node
return ['M', start, height - 30, // the arc starts at the coordinate x=start, y=height-30 (where the starting node is)
'A', // This means we're gonna build an elliptical arc
(start - end) / 1.95, ',', // Next 2 lines are the coordinates of the inflexion point. Height of this point is proportional with start - end distance
(start - end) / 2, 0, 0, ',',
start < end ? 1 : 0, end, ',', height - 30
] // We always want the arc on top. So if end is before start, putting 0 here turn the arc upside down.
.join(' ');
})
.style("fill", "none")
.attr("stroke", "#919191")
var tooltip1 = d3.select("#graph1823")
.append("div")
.style("opacity", 0)
.attr("class", "tooltip")
.style("background-color", "#FFFFFF")
.style("border-style", "solid")
.style("border-width", "1px")
.style("position", "absolute")
.style('width', '200px')
// Add the highlighting functionality
nodes
.on('mouseover', function(d) {
// Highlight the nodes: every node is green except of him
nodes.style('fill', function(d) {
return color(d.grp)
})
d3.select(this).style('fill', function(d) {
return color(d.grp)
})
// Highlight the connections
links
.style('stroke', function(link_d) {
return link_d.source === d.id || link_d.target === d.id ? color(d.grp) : '#b8b8b8';
})
.style('stroke-width', function(link_d) {
return link_d.source === d.id || link_d.target === d.id ? 4 : 1;
})
tooltip1
.html(d.name)
.style('text-align', 'center')
.style('font-family', 'Gotham Narrow, sans-serif')
.style('font-size', '.9em')
.style('margin-left', '30%')
.style('margin-right', '30%')
.style("opacity", .8)
.style("stroke", "#EEEEEE")
.style("background-color", "#FFFFFF")
.style("z-index", 20)
.style('padding', '10px')
})
.on('mouseout', function(d) {
nodes.attr("r", '8').style("fill", function(d) {
return color(d.grp)
})
links
.style('stroke', '#919191')
.style('stroke-opacity', 1)
.style('stroke-width', '1')
tooltip1
.style("opacity", 0)
d3.select(this)
.style("stroke", "none")
.style("opacity", 1)
})
})
svg
.append("text")
.attr("text-anchor", "middle")
.style("fill", "#black")
.style("font-size", "17px")
.attr("x", 225)
.attr("y", 40)
.html(" Correspondence from 1823")
})();
</script>
</body>
</html>
uj5u.com熱心網友回復:
問題是該getComputedTextLength()函式不能用于確定未呈現的元素上文本的長度 ( display: none )。因此該wrap()功能不適用于最初未顯示的圖表。
也許您可以僅在下拉串列中選擇圖形時才呈現圖形?這也將避免代碼重復。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/535878.html
下一篇:帶有連接節點的鏈接的簇狀氣泡
