我正在尝试使用来自服务器,d3和backbone.js的数据绘制一个简单的区域图表。我收到了错误
解析d =“”
时出现问题
每当抽出实际区域路径时。错误出现两次。控制台中的错误如下:
Error: Problem parsing d="" d3.v3.js:585
attrFunction d3.v3.js:585
(anonymous function) d3.v3.js:868
d3_selection_each d3.v3.js:874
d3_selectionPrototype.each d3.v3.js:867
d3_selectionPrototype.attr d3.v3.js:567
GraphBase.extend.renderData backboney.html:242
Backbone.View.extend.render backboney.html:153
(anonymous function) backboney.html:128
fire jquery-2.0.2.js:2939
self.fireWith jquery-2.0.2.js:3051
done jquery-2.0.2.js:7428
(anonymous function)
以下是我正在使用的代码:
<!DOCTYPE html>
<html>
<head>
<title>BONEZY</title>
<style>
body {
font: .7em sans-serif;
}
#graph {
height: 600px;
width: 800px;
}
/* Styles axes of graph */
.axis path {
fill: none;
stroke: #c9c9c9;
shape-rendering: crispEdges;
}
.axis line {
fill: none;
stroke: none;
shape-rendering: crispEdges;
}
/* Fill of graph */
.area {
fill: #49decf;
}
</style>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<div id="graph"></div>
<script src="jquery-2.0.2.js"></script>
<script type="text/javascript" src="d3.v3.js"></script>
<script type="text/javascript" src="underscore.js"></script>
<script type="text/javascript" src="backbone.js"></script>
<script>
(function ($) {
var Entry = Backbone.Model.extend({});
var Entries = Backbone.Collection.extend({
url: 'http://sensors.metabolic.nl/api/v1/entry/?format=json',
model: Entry,
parse: function(response, xhr) {
// Get objects array from JSON response (actual entries)
//return response.objects;
//console.log('Response object value',response.objects[0].value);
_.each(response.objects, function (object) {
// Convert each value attribute to an actual array
object.value = toArray(object.value);
// Actually fuck it, just extract numerical value and set as value
// FIX WHEN NEW DATA STRUC EXISTS
object.value = object.value[1];
});
console.log('finished parsing', response.objects);
return response.objects;
}
});
// Used to convert the shitty sensor value strings to arrays
function toArray(str) {
var trimRegEx = /[\'\[\]\s\*C\%]/g;
var newStr = str.replace(trimRegEx, "");
var commaIndex = newStr.indexOf(","); // Index of the comma (divider between values)
var sensorName = newStr.slice(0, commaIndex);
var sensorValue = newStr.slice(commaIndex + 1);
return new Array(sensorName, parseFloat(sensorValue));
}
// Base of the graph that we will draw with d3
// MAD HELPS found at http://jtuulos.github.io/bayd3-may2013/
var GraphBase = Backbone.View.extend({
defaults: {
xAttr: "x",
yAttr: "y",
margin: { top: 20, right: 20, bottom: 20, left: 50 }
},
initialize: function(options) {
var self = this;
// Constructor options no longer automatically copied
self.options = options;
self.collection = new Entries();
_.bindAll(self, 'render');
//self.collection.on('add', self.render(self.options));
// Populate collection
self.collection.fetch({
data: { /*offset: 20, limit: 20 */},
add: true,
reset: true,
success: function(collection, response) {
console.log('Collection fetch success', response);
console.log('Collection models: ', collection.models);
},
error: function() {
console.log('alas, failure');
}
}).complete(function() {
console.log('complete!');
self.render(self.options);
});
},
render: function(options) {
console.log('render graph base');
this.options = options;
var margin = this.options.margin;
this.width = this.$el.width() - margin.left - margin.right;
this.height = this.$el.height() - margin.top - margin.bottom;
console.log("height", this.height);
this.svg = d3.select(this.el).append('svg')
.attr("width", this.width + margin.left + margin.right)
.attr("height", this.height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
this.scales = {
x: this.getXScale(),
y: this.getYScale()
};
this.renderAxes();
this.renderData();
return this;
}
});
// Extension of GraphBase View, contains everything related to data
var AreaGraph = GraphBase.extend({
defaults: _.defaults({
/*ex barPadding: 0.1 */
}, GraphBase.prototype.defaults),
// Calculate and return scale and domain of X axis
getXScale: function () {
//console.log('x scale', this.collection.models[1].get('at')/*this.collection.pluck(this.options.at)*/);
console.log('Get X scale');
var xAttr = this.options.xAttr;
return d3.time.scale()
.range([0, this.width])
//.domain(this.collection.models.pluck(this.options.xAttr));
.domain(this.collection.map( function(model) {
return model.get(xAttr);
}));
},
// Calculate and return scale and domain of Y axis
getYScale: function() {
console.log('Get Y scale');
var yAttr = this.options.yAttr;
return d3.scale.linear()
.range([this.height, 0])
//.domain([0, 1.2 * d3.max(this.collection.pluck(this.options.yAttr))]);
.domain([0, 1.2 * d3.max(this.collection.map(function(model) {
return model.get(yAttr);
}
))]);
},
// Render the X and Y axis
renderAxes: function() {
console.log('render axes');
var xAxis = d3.svg.axis()
.scale(this.scales.x)
.orient('bottom');
var yAxis = d3.svg.axis()
.scale(this.scales.y)
.orient('left');
/*.tickFormat(d3.format("") Option to modify ticks on axis*/
//console.log('svg', this.svg);
// Adds X axis to graph
this.svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + this.height + ")")
.call(xAxis);
// Adds Y axis to graph (ignore label for now)
this.svg.append("g")
.attr("class", "y axis")
.call(yAxis);
},
// Render the actual data for the graph
renderData: function() {
console.log('render data');
var chart = this,
x = this.scales.x,
y = this.scales.y;
// Calculate area under path
var area = d3.svg.area()
.x(function(d) { return x(d.at); })
.y0(chart.height)
.y1(function(d) { return y(d.value); });
console.log(this.collection.models);
this.svg.selectAll("path")
.data(this.collection.models)
.attr("class", "area")
//.attr("d", area);
.attr("d", function(d) {
// Generate area
var dArray = new Array();
dArray[x] = d.get('at');
dArray[y] = d.get('value');
//return area(d.attributes);
return area(dArray);
});
}
});
// Graph object (AreaGraph inherits GraphBase)
var graph = new AreaGraph({
// Backbone view options
el: '#graph',
// These are the data attributes to be read to determine values
xAttr: "at",
yAttr: "value",
margin: { top: 20, right: 20, bottom: 20, left: 50 }
});
})(jQuery);
</script>
</body>
</html>
非常感谢任何见解!
答案 0 :(得分:0)
如果你把你的代码放到jsFiddle中会更容易调试,但是一个明显的错误:
.attr("d", function(d) {
// Generate area
var dArray = new Array();
dArray[x] = d.get('at');
dArray[y] = d.get('value');
//return area(d.attributes);
return area(dArray);
});
这段代码对我来说没有任何意义。你的x,y是比例,而不是数组索引。这意味着路径的“d”属性将变为垃圾(即,d =“”)。您应该使用注释掉的代码:
.attr("d", area);
绘制您的区域并确保数据数组中的每个元素都具有“.at”和“.value”属性。