y在散点图中比例缩放y轴与y值不同y D3.js
问题描述:
我制作的scatterplot有一个正确的y轴,从0到5000左右,但是正在绘制的节点没有达到它们的值。y在散点图中比例缩放y轴与y值不同y D3.js
问题(我认为)是y尺度的领域。我尝试过使用extent(),min和max以及硬编码值(这些尝试在那里并且注释掉)。我已经调整了进入y范围的值,他们似乎没问题,他们应该达到这个图表的顶部,但他们几乎没有到一半。
去图表的顶部节点的唯一方法是,如果我硬编码Y比例域的最大是3000,这是不甚至接近最大值为y值约为4600 picture of chart
<!-- STACK OVERFLOW This code at the top is simple HTML/HTTP request stuff, you can
scroll down till my other comments to start looking at the problem.
I left this code here so people can run the chart on their browser.-->
<meta charset="utf-8">
<title>Template Loading D3</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.12/d3.min.js"></script>
<style media="screen">
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<h1>Bitcoin BTC</h1>
<script type="text/javascript">
var xhr = new XMLHttpRequest();
function makeRequest(){
xhr.open("GET", "https://api.coindesk.com/v1/bpi/historical/close.json?start=2010-07-17&end=2017-09-11", true);
xhr.send();
xhr.onreadystatechange = processRequest;
}
function processRequest(){
console.log("testing, state: ", xhr.readyState)
if(xhr.readyState == 4 && xhr.status == 200){
let response = JSON.parse(xhr.responseText);
makeChart(response);
}
}
// STACK OVERFLOW -- code above this can be ignored since it's just making HTTP request.
// I'm leaving it here so people can serve this code on their own machine and
// see it working in their browser. D3 code is below
// When the HTTP request is finished, this function gets called to draw my chart,
// this is where D3.js starts.
function makeChart(response){
var w = window.innerWidth - 100;
var h = window.innerHeight - 100;
var padding = 20;
var Lpadding = 45;
// makeDatesAndValues is not part of my problem, this formats the dates
// coming from HTTP request into something easier to feed into D3.js X Scale
var makeDatesAndValues = function(input){
let dates = [];
let values = [];
let returnData = [];
for(prop in input){
values.push(input[prop])
let counter = 0;
let year = [];
let month = [];
let day = [];
for(var j = 0; j < prop.length; j++){
if(lastDate[j] !== "-" && counter == 0){
year.push(prop[j]);
} else if(prop[j] == "-"){
counter++;
} else if(prop[j] !== "-" && counter == 1){
month.push(prop[j])
} else if(prop[j] !== "-" && counter == 2){
day.push(prop[j])
}
}
dates.push([Number(year.join("")), Number(month.join("")), Number(day.join(""))]);
returnData.push(
{
date: [Number(year.join("")), Number(month.join("")), Number(day.join(""))],
value: input[prop]
}
)
}
return returnData;
}
var inputData = makeDatesAndValues(response.bpi);
// HERE WE GO, this is where I think the problem is, drawing the actual chart.
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
// Here is the problem child, both "y" and the commented out "yScale" are attempts to
// get the correct y-coordinates for values fed into the scale
// Both of these will make a correct y Axis, but then screw up the y-coordinates of my data
// getting fed in, as described on SO
var y = d3.scale.linear()
.domain([d3.min(inputData, function(d){ return d.value; }), d3.max(inputData, function(d){ return d.value; })])
// .domain([d3.extent(d3.values(inputData, function(d){ return d.value}))])
// .domain([0, 3000])
.range([h - padding, padding])
// var yScale = d3.scale.linear()
// // .domain([0, 5000])
// .domain([d3.min(inputData, function(d){ return d.value; }), d3.max(inputData, function(d){ return d.value; })])
// // .domain([d3.extent(d3.values(inputData, function(d){ return d.value}))])
// .range([0, h])
// X scale works fine, no problems here
var x = d3.time.scale()
.domain([new Date(2010, 7, 18), new Date(2017, 7, 18)])
.range([Lpadding, w]);
// Both Axes seem to be working fine
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(8)
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
// .tickSize(-w, 0, 0)
.ticks(8)
svg.selectAll("circle")
.data(inputData)
.enter()
.append("circle")
.attr("cx", function(d){
let thisDate = x(new Date(d.date[0], d.date[1], d.date[2]))
return thisDate;
})
// And here is the other side of the problem. There are different attempts
// to plot they y-coordinate of my values commented out.
// None of these are working and I don't understand why it works correctly
// for the Y Axis, but my plotted values come way short of where they should be.
.attr("cy", function(d, i){
console.log("this is with yScale: ", y(d.value))
console.log("Without: ", d.value)
// return y((d.value) - padding)
// return y(d.value);
// return y(d.value) - (h - padding)
return h - padding - y(d.value);
})
.attr("r", function(d){
return 1;
})
.attr("fill", "red")
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + 0 + ", " + (h - padding) + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + Lpadding + ", 0)")
.call(yAxis);
}
makeRequest();
</script>
</body>
答
我建议你可能需要考虑人们的感受,当你张贴这样长的代码与可怜的评论。
你的问题是你没有意识到SV指向底部的坐标系。以下是一些修改:
svg.selectAll("circle")
.data(inputData)
.enter()
.append("circle")
.attr("cx", function(d){
let thisDate = x(new Date(d.date[0], d.date[1], d.date[2]));
return thisDate;
})
// this is the KEY part you should change:
.attr("cy", function(d, i){ return h - padding - y(d.value); })
.attr("r", 1)
.attr("fill", "red");
由于您不提供详细数据,我无法检查它。希望它会有所帮助!
感谢您的帮助,您的建议会产生同样的问题,我已经越过了。 对不起,没有评论,我认为这是非常标准的D3.js代码,但我现在要添加评论。 我很惊讶你说你不能检查它,你可以复制粘贴我的代码,静态地提供它而不用改变任何东西,并在浏览器上查看图表。 – iggirex
如你所愿,我更改了你的代码。对于普通的JavaScript和基本的SVG技巧你有很多工作要做。 [这里](http://jsbin.com/natikab/edit?html,js,output)是jsbin代码,它的工作原理。 – 1Cr18Ni9
非常感谢你的代码!是的,我一直在忽略JS框架,因为我确实想在语言上变得更好。你非常先进,我感谢你花时间向我展示这一点。我现在正在学习能够像你一样链接更高级的功能,太酷了!对于这些基本的JS和D3技巧的学习资源的任何建议? – iggirex