【发布时间】:2018-07-25 03:39:24
【问题描述】:
我尝试在不同幻灯片中显示的 d3js 图表的幻灯片放映有一点问题。问题是我的两个图表都显示在一张幻灯片中,而不是显示在不同的幻灯片中。我仔细检查了所有 div 标签以确保它们是否都已关闭。不确定我在这里缺少什么?
附:我知道脚本是重复的,但我会在修复幻灯片问题后进行代码清理。请多多包涵!
【问题讨论】:
标签: javascript html d3.js
我尝试在不同幻灯片中显示的 d3js 图表的幻灯片放映有一点问题。问题是我的两个图表都显示在一张幻灯片中,而不是显示在不同的幻灯片中。我仔细检查了所有 div 标签以确保它们是否都已关闭。不确定我在这里缺少什么?
附:我知道脚本是重复的,但我会在修复幻灯片问题后进行代码清理。请多多包涵!
【问题讨论】:
标签: javascript html d3.js
您在这里面临的问题与我针对您的previous question 的解决方案不同,d3.csv 是异步。因此,您的方法(选择脚本所在的 div)将不起作用:全局范围内将存在污染和冲突。
一个非常简单的解决方法是使用 IIFE,如下所示:
(function foo(){
//your code here
}());
让我们看看。这是你的 HTML 和我制作的一个愚蠢的条形图,没有 IIFE。蓝色图表应该出现在第 3 个 div 中,红色图表应该出现在第 4 个 div 中,但您可以看到,这两个图表都显示在最后一个 div 中:
<!DOCTYPE html>
<html>
<head>
<title>Slides</title>
<!-- Required stylesheet -->
<link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>
<body>
<div class="slideshow-container">
<div class="mySlides fade">
<div class="numbertext">1 / 4</div>
</div>
<div class="mySlides fade">
<div class="numbertext">2 / 4</div>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<div class="mySlides fade">
<div class="numbertext">3 / 4</div>
<div id="filter"><b>States:</b></div>
<script>
var container = document.currentScript.parentNode;
var svg = d3.select(container)
.append("svg");
d3.json("https://api.myjson.com/bins/xv0yy", function(data) {
var scale = d3.scaleBand()
.domain(data)
.range([0, 300])
.padding(0.4);
var bars = svg.selectAll(null)
.data(data)
.enter()
.append("rect")
.style("fill", "steelblue")
.attr("x", d => scale(d))
.attr("width", scale.bandwidth())
.attr("height", d => 150 - d)
.attr("y", Number)
})
</script>
</div>
<div class="mySlides fade">
<div class="numbertext">4 / 4</div>
<script>
var container = document.currentScript.parentNode;
var svg = d3.select(container)
.append("svg");
d3.json("https://api.myjson.com/bins/zgway", function(data) {
var scale = d3.scaleBand()
.domain(data)
.range([0, 300])
.padding(0.4);
var bars = svg.selectAll(null)
.data(data)
.enter()
.append("rect")
.style("fill", "tomato")
.attr("x", d => scale(d) + 10)
.attr("width", scale.bandwidth())
.attr("height", d => 150 - d)
.attr("y", Number)
})
</script>
</div>
<!-- Next and previous buttons -->
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
</div>
<br>
<div style="text-align:center">
<span class="dot" onclick="currentSlide(1)"></span>
<span class="dot" onclick="currentSlide(2)"></span>
<span class="dot" onclick="currentSlide(3)"></span>
<span class="dot" onclick="currentSlide(4)"></span>
</div>
<script>
var slideIndex = 1;
showSlides(slideIndex);
function plusSlides(n) {
showSlides(slideIndex += n);
}
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
var slides = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("dot");
if (n > slides.length) {
slideIndex = 1
}
if (n < 1) {
slideIndex = slides.length
}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex - 1].style.display = "block";
dots[slideIndex - 1].className += " active";
}
</script>
</body>
</html>
现在相同的代码,但使用 IIFE,一切都显示在正确的位置:
<!DOCTYPE html>
<html>
<head>
<title>Slides</title>
<!-- Required stylesheet -->
<link rel="stylesheet" type="text/css" href="stylesheet.css">
</head>
<body>
<div class="slideshow-container">
<div class="mySlides fade">
<div class="numbertext">1 / 4</div>
</div>
<div class="mySlides fade">
<div class="numbertext">2 / 4</div>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<div class="mySlides fade">
<div class="numbertext">3 / 4</div>
<div id="filter"><b>States:</b></div>
<script>
(function iife() {
var container = document.currentScript.parentNode;
var svg = d3.select(container)
.append("svg");
d3.json("https://api.myjson.com/bins/xv0yy", function(data) {
var scale = d3.scaleBand()
.domain(data)
.range([0, 300])
.padding(0.4);
var bars = svg.selectAll(null)
.data(data)
.enter()
.append("rect")
.style("fill", "steelblue")
.attr("x", d => scale(d))
.attr("width", scale.bandwidth())
.attr("height", d => 150 - d)
.attr("y", Number)
})
}())
</script>
</div>
<div class="mySlides fade">
<div class="numbertext">4 / 4</div>
<script>
(function iife() {
var container = document.currentScript.parentNode;
var svg = d3.select(container)
.append("svg");
d3.json("https://api.myjson.com/bins/zgway", function(data) {
var scale = d3.scaleBand()
.domain(data)
.range([0, 300])
.padding(0.4);
var bars = svg.selectAll(null)
.data(data)
.enter()
.append("rect")
.style("fill", "tomato")
.attr("x", d => scale(d))
.attr("width", scale.bandwidth())
.attr("height", d => 150 - d)
.attr("y", Number)
})
}())
</script>
</div>
<!-- Next and previous buttons -->
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
</div>
<br>
<div style="text-align:center">
<span class="dot" onclick="currentSlide(1)"></span>
<span class="dot" onclick="currentSlide(2)"></span>
<span class="dot" onclick="currentSlide(3)"></span>
<span class="dot" onclick="currentSlide(4)"></span>
</div>
<script>
var slideIndex = 1;
showSlides(slideIndex);
function plusSlides(n) {
showSlides(slideIndex += n);
}
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
var slides = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("dot");
if (n > slides.length) {
slideIndex = 1
}
if (n < 1) {
slideIndex = slides.length
}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex - 1].style.display = "block";
dots[slideIndex - 1].className += " active";
}
</script>
</body>
</html>
在那些sn-ps中我用的是d3.json,不是d3.csv,但是原理是一样的。
PS:这一点我怎么强调都不为过:可以这么说,我对您的previous question 的回答只是好奇心。不要遵循您在此处遵循的方法(使用document.currentScript)。这可能是未来维护/调试的噩梦。
【讨论】: