我有两个输入字段。将插入jsdata对象数组的名称和值。但是,当我单击“提交”按钮时,x域和y域似乎被无故调用了两次。我真的不知道为什么要重复。我希望图表绘制一个新的条,然后以升序排序。
<!DOCTYPE html>
.bar {
font: 10px sans-serif;
text-align: right;
padding: 3px;
margin: 1px;
color: white;
}
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.legend rect {
fill: white;
stroke: black;
opacity: 0.8;
}
.toolTip {
position: absolute;
display: none;
min-width: 80px;
height: auto;
background: none repeat scroll 0 0 #ffffff;
border: 1px solid #6F257F;
padding: 14px;
text-align: center;
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
display: none;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #2196F3;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
#userdata {
top: -80px;
}
div {
display: inline-block;
position: relative;
}
#colorize {
position: absolute;
bottom: 10px;
right: 10px;
}
#toggle {
top: -60px;
}
</style>
<svg class="chart"></svg>
<div class="row">
<div class="col-sm-4">
<h3>Enter your desired colors in hexadecimal value</h3>
<textarea rows="6" cols="60" id="colorInput"></textarea>
<button id="colorize" onclick="colorize()">Colorize</button>
</div>
<div class="col-sm-4" id="userdata">
<h3>Enter your data</h3>
<input type="text" id="name" placeholder="name">
<input type="number" id="value" placeholder="value">
<button onclick="addData()">Submit</button>
</div>
<div class="col-sm-4" id="toggle">
<h3>Toggle Data Label</h3>
<label class="switch">
<input type="checkbox" onclick="togglePressed()" checked>
<span class="slider round"></span>
</label>
</div>
</div>
<script src="http://d3js.org/d3.v3.js"></script>
<script src="d3legend.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var jsdata = [
{ name: "Locke", value: 4 },
{ name: "Reyes", value: 8 },
{ name: "Ford", value: 15 },
{ name: "Jarrah", value: 16 },
{ name: "Shephard", value: 23 },
{ name: "Kwon", value: 52 }
];
console.log(typeof jsdata);
var colorCodes = ["#6b486b", "#a05d56", "#d0743c", "#ff8c00"];
var color = d3.scale.ordinal().range(colorCodes);
//Set the margins for the bar chart.
var margin = { top: 20, right: 30, bottom: 30, left: 40 },
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
//Encoding ordinal data. rangeRoundBands is used to snap each position to the exact pixel boundary for crisp edges
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var tooltip = d3.select("body").append("div").attr("class", "toolTip");
//Adding the axes
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
//Declaring the chart container
var chart = d3.select(".chart")
.attr("width", width + margin.left + margin.right)
.data(jsdata)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x.domain(jsdata.map(function (jsdata) { return jsdata.name; }));
y.domain([0, d3.max(jsdata, function (jsdata) { return jsdata.value; })]);
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart.append("g")
.attr("class", "y axis")
.call(yAxis);
chart.selectAll(".bar")
.data(jsdata) // Using the data join pattern
.enter().append("rect") //Selecting the chart container then append the width and height for new nodes
.style("fill", function (jsdata, i) { return color(i); })
.style("color", function () { return '#FFFFFF'; })
.on("mousemove", function (jsdata) {
tooltip
.style("left", d3.event.pageX - 50 + "px")
.style("top", d3.event.pageY - 70 + "px")
.style("display", "inline-block")
.html((jsdata.name) + "<br>" + "£" + (jsdata.value));
})
.on("mouseout", function (jsdata) { tooltip.style("display", "none"); })
.attr("class", "bar")
.attr("data-legend", function (jsdata) { return jsdata.name })
.attr("x", function (jsdata) { return x(jsdata.name); })
.attr("y", function (jsdata) { return y(jsdata.value); })
.attr("height", function (jsdata) { return height - y(jsdata.value); })
.attr("width", x.rangeBand());
chart.selectAll(".text")
.data(jsdata)
.enter()
.append("text")
.attr("class", "label")
.attr("x", (function (jsdata) { return x(jsdata.name) + 56; }))
.attr("y", function (jsdata) { return y(jsdata.value) - 20; })
.attr("dy", ".75em")
.text(function (jsdata) { return jsdata.value; });
/*chart.selectAll("text")
.data(jsdata)
.enter()
.append("text")
.text(function (jsdata) {
return jsdata.value;
})*/
//Converting the column from name to integer
function type(jsdata) {
jsdata.value = +jsdata.value;
return jsdata;
}
function togglePressed() {
$(".label").toggle();
}
function colorize() {
var lines = $('#colorInput').val().split('\n');
for (var i = 0; i < lines.length; i++) {
if (colorCodes.includes(lines[i])) {
alert("Error. This color already exists.");
}
else {
colorCodes.push(lines[i]);
}
}
chart.selectAll(".bar")
.style('fill', function (jsdata, i) { return color(i); })
.attr("height", function (jsdata) { return height - y(jsdata.value); })
.attr("width", x.rangeBand());
}
function addData() {
var name = document.getElementById("name").value;
var value = document.getElementById("value").value;
var person = new Object();
person.name = name;
person.value = parseInt(value);
jsdata.push(person);
//chart.select(x).remove();
x.domain(jsdata.map(function (jsdata) { return jsdata.name; }));
y.domain([0, d3.max(jsdata, function (jsdata) { return jsdata.value; })]);
chart.select(".xaxis").remove();
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart.append("g")
.attr("class", "y axis")
.call(yAxis);
var bars = chart.selectAll(".bar").data(jsdata);
bars.enter().append("rect")
.style("fill", function (jsdata, i) { return color(i); })
.style("color", function () { return '#FFFFFF'; })
.on("mousemove", function (jsdata) {
tooltip
.style("left", d3.event.pageX - 50 + "px")
.style("top", d3.event.pageY - 70 + "px")
.style("display", "inline-block")
.html((jsdata.name) + "<br>" + "£" + (jsdata.value));
})
.on("mouseout", function (jsdata) { tooltip.style("display", "none"); })
.attr("class", "bar")
.attr("data-legend", function (jsdata) { return jsdata.name })
.attr("x", function (jsdata) { return x(jsdata.name); })
.attr("y", function (jsdata) { return y(jsdata.value); })
.attr("height", function (jsdata) { return height - y(jsdata.value); })
.attr("width", x.rangeBand());
chart.select(".text")
.data(jsdata)
.enter()
.append("text")
.attr("class", "label")
.attr("x", (function (jsdata) { return x(jsdata.name) + 56; }))
.attr("y", (function (jsdata) { return y(jsdata.value) - 20; }))
.attr("dy", ".75em")
.text(function (jsdata) { return jsdata.value; });
/*chart.select("text")
.data(jsdata)
.enter()
.append("text")
.text(function (jsdata) {
return jsdata.value;
})*/
bars.exit().remove();
}
var legend = chart.append("g")
.attr("class", "legend")
.attr("transform", "translate(50,30)")
.attr("data-legend-pos", "bottom")
.style("font-size", "12px")
.call(d3.legend);
</script>
答案 0 :(得分:3)
您的代码中的条形图(标签也没有)没有更新选择。
您可以利用D3 v3(从v4开始删除)的魔术行为,其中append
修改了更新选择,只做了很小的更改:< / p>
var bars = chart.selectAll(".bar").data(jsdata);
bars.enter().append("rect")
//etc...
bars.attr("x", function(jsdata) {
return x(jsdata.name);
})
//etc...
对标签执行相同的操作(顺便说一句,没有text
类可供选择)。最后,只需再次调用轴,不要重新附加它们:
chart.select(".x.axis")
.call(xAxis);
chart.select(".y.axis")
.call(yAxis);
以下是具有这些更改的代码:
<!DOCTYPE html>
<style>
.bar {
font: 10px sans-serif;
text-align: right;
padding: 3px;
margin: 1px;
color: white;
}
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.legend rect {
fill: white;
stroke: black;
opacity: 0.8;
}
.toolTip {
position: absolute;
display: none;
min-width: 80px;
height: auto;
background: none repeat scroll 0 0 #ffffff;
border: 1px solid #6F257F;
padding: 14px;
text-align: center;
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
display: none;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #2196F3;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
#userdata {
top: -80px;
}
div {
display: inline-block;
position: relative;
}
#colorize {
position: absolute;
bottom: 10px;
right: 10px;
}
#toggle {
top: -60px;
}
</style>
<svg class="chart"></svg>
<div class="row">
<div class="col-sm-4">
<h3>Enter your desired colors in hexadecimal value</h3>
<textarea rows="6" cols="60" id="colorInput"></textarea>
<button id="colorize" onclick="colorize()">Colorize</button>
</div>
<div class="col-sm-4" id="userdata">
<h3>Enter your data</h3>
<input type="text" id="name" placeholder="name">
<input type="number" id="value" placeholder="value">
<button onclick="addData()">Submit</button>
</div>
<div class="col-sm-4" id="toggle">
<h3>Toggle Data Label</h3>
<label class="switch">
<input type="checkbox" onclick="togglePressed()" checked>
<span class="slider round"></span>
</label>
</div>
</div>
<script src="https://d3js.org/d3.v3.js"></script>
<script src="d3legend.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var jsdata = [{
name: "Locke",
value: 4
},
{
name: "Reyes",
value: 8
},
{
name: "Ford",
value: 15
},
{
name: "Jarrah",
value: 16
},
{
name: "Shephard",
value: 23
},
{
name: "Kwon",
value: 52
}
];
console.log(typeof jsdata);
var colorCodes = ["#6b486b", "#a05d56", "#d0743c", "#ff8c00"];
var color = d3.scale.ordinal().range(colorCodes);
//Set the margins for the bar chart.
var margin = {
top: 20,
right: 30,
bottom: 30,
left: 40
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
//Encoding ordinal data. rangeRoundBands is used to snap each position to the exact pixel boundary for crisp edges
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([height, 0]);
var tooltip = d3.select("body").append("div").attr("class", "toolTip");
//Adding the axes
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
//Declaring the chart container
var chart = d3.select(".chart")
.attr("width", width + margin.left + margin.right)
.data(jsdata)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x.domain(jsdata.map(function(jsdata) {
return jsdata.name;
}));
y.domain([0, d3.max(jsdata, function(jsdata) {
return jsdata.value;
})]);
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart.append("g")
.attr("class", "y axis")
.call(yAxis);
chart.selectAll(".bar")
.data(jsdata) // Using the data join pattern
.enter().append("rect") //Selecting the chart container then append the width and height for new nodes
.style("fill", function(jsdata, i) {
return color(i);
})
.style("color", function() {
return '#FFFFFF';
})
.on("mousemove", function(jsdata) {
tooltip
.style("left", d3.event.pageX - 50 + "px")
.style("top", d3.event.pageY - 70 + "px")
.style("display", "inline-block")
.html((jsdata.name) + "<br>" + "£" + (jsdata.value));
})
.on("mouseout", function(jsdata) {
tooltip.style("display", "none");
})
.attr("class", "bar")
.attr("data-legend", function(jsdata) {
return jsdata.name
})
.attr("x", function(jsdata) {
return x(jsdata.name);
})
.attr("y", function(jsdata) {
return y(jsdata.value);
})
.attr("height", function(jsdata) {
return height - y(jsdata.value);
})
.attr("width", x.rangeBand());
chart.selectAll(".text")
.data(jsdata)
.enter()
.append("text")
.attr("class", "label")
.attr("x", (function(jsdata) {
return x(jsdata.name) + 56;
}))
.attr("y", function(jsdata) {
return y(jsdata.value) - 20;
})
.attr("dy", ".75em")
.text(function(jsdata) {
return jsdata.value;
});
/*chart.selectAll("text")
.data(jsdata)
.enter()
.append("text")
.text(function (jsdata) {
return jsdata.value;
})*/
//Converting the column from name to integer
function type(jsdata) {
jsdata.value = +jsdata.value;
return jsdata;
}
function togglePressed() {
$(".label").toggle();
}
function colorize() {
var lines = $('#colorInput').val().split('\n');
for (var i = 0; i < lines.length; i++) {
if (colorCodes.includes(lines[i])) {
alert("Error. This color already exists.");
} else {
colorCodes.push(lines[i]);
}
}
chart.selectAll(".bar")
.style('fill', function(jsdata, i) {
return color(i);
})
.attr("height", function(jsdata) {
return height - y(jsdata.value);
})
.attr("width", x.rangeBand());
}
function addData() {
var name = document.getElementById("name").value;
var value = document.getElementById("value").value;
var person = new Object();
person.name = name;
person.value = parseInt(value);
jsdata.push(person);
//chart.select(x).remove();
x.domain(jsdata.map(function(jsdata) {
return jsdata.name;
}));
y.domain([0, d3.max(jsdata, function(jsdata) {
return jsdata.value;
})]);
chart.select(".xaxis").remove();
chart.select(".x.axis")
.call(xAxis);
chart.select(".y.axis")
.call(yAxis);
var bars = chart.selectAll(".bar").data(jsdata);
bars.enter().append("rect")
.style("fill", function(jsdata, i) {
return color(i);
})
.style("color", function() {
return '#FFFFFF';
})
.on("mousemove", function(jsdata) {
tooltip
.style("left", d3.event.pageX - 50 + "px")
.style("top", d3.event.pageY - 70 + "px")
.style("display", "inline-block")
.html((jsdata.name) + "<br>" + "£" + (jsdata.value));
})
.on("mouseout", function(jsdata) {
tooltip.style("display", "none");
})
.attr("class", "bar")
.attr("data-legend", function(jsdata) {
return jsdata.name
});
bars.attr("x", function(jsdata) {
return x(jsdata.name);
})
.attr("y", function(jsdata) {
return y(jsdata.value);
})
.attr("height", function(jsdata) {
return height - y(jsdata.value);
})
.attr("width", x.rangeBand());
var texts = chart.selectAll(".label")
.data(jsdata);
texts.enter()
.append("text")
.attr("class", "label");
texts.attr("x", (function(jsdata) {
return x(jsdata.name) + 56;
}))
.attr("y", (function(jsdata) {
return y(jsdata.value) - 20;
}))
.attr("dy", ".75em")
.text(function(jsdata) {
return jsdata.value;
});
/*chart.select("text")
.data(jsdata)
.enter()
.append("text")
.text(function (jsdata) {
return jsdata.value;
})*/
bars.exit().remove();
texts.exit().remove();
}
var legend = chart.append("g")
.attr("class", "legend")
.attr("transform", "translate(50,30)")
.attr("data-legend-pos", "bottom")
.style("font-size", "12px")
.call(d3.legend);
</script>
PS:我在摘要中禁用了控制台,因为这里有很多错误。我建议你给他们解决。