#javascript #d3.js #svg
#javascript #d3.js #svg
Вопрос:
У меня есть диаграмма bar line symbol, которая преобразуется, когда пользователи нажимают ось y для переключения между linear и sqrt. http://bl.ocks.org/jebeck/9457536. это отлично работает с одним svg, но когда на одной веб-странице более одного svg, это может работать только с одним из svg (ов); на остальных svg (ах) строки и символы перемещаются в одну точку, потому что значения x не являются числом. отладка показывает, что d3.mouse(invisibleRect.node()) получает неперехваченную ошибку типа: не удается прочитать свойство ‘sourceEvent’ из null. Я подозреваю, что это связано с приоритетом последнего элемента, когда на одной странице более одного svg-элемента, но я просто пытаюсь найти хорошее решение. Спасибо.
d3.csv("data13.csv", function (error, data) {
if (error) throw error;
if (data.length == 0) {
svg.append("text").text("data is empty");
throw "No Input";
}
var attributeName = d3.keys(data[0])[0];
var metricList = d3.keys(data[0]).slice(1);
var target = metricList[metricList.length - 1];
data.forEach(function (d) {
var maxData = d3.max(data, function (d) { return d3.max(metricList.map(function (name) { return d[name]; })); });
var minData = d3.min(data, function (d) { return d3.min(metricList.map(function (name) { return d[name]; })); });
x0.domain(metricList);
x1.domain(data.map(function (d) { return d[attributeName]; })).rangeRoundBands([0, x0.rangeBand()]);
y.domain([Math.min(0, minData) * space_to_top, Math.max(0, maxData) * space_to_top]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," height ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
var drawBars = svg.selectAll(".bars")
.data(metricList)
.enter().append("g")
.attr("class", "bargroup")
.attr("transform", function (name) { return "translate(" x0(name) ",0)"; });
drawBars.selectAll("rect")
.data(function (metricName) {
return data.map(function (d) {
return {
name: d[attributeName],
value: d[metricName],
title: metricName
};
});
})
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("x", function (d) { return x1(d.name); })
.attr("y", function (d) { return y(Math.max(0, d.value)); })
.attr("height", function (d) { return Math.abs(y(d.value) - y(0)); })
.style("fill", function (d) { return color(d.name); })
.on("mouseover", function (d) {
d3.select(this).style("fill", "red");
})
.on("mouseout", function (d) {
d3.select(this).style("fill", color(d.name));
})
.append("title")
.text(function (d) {
return attributeName ": " d.name
"nCategory: " d.title
"nValue: " d.value;
});
data.forEach(function (d, i) {
var lineFunction = d3.svg.line()
.x(function (k) { return x0(k) x1(d[attributeName]) x1.rangeBand() / 2; })
.y(function (k) { return y( d[target]); });
svg.append("path")
.attr("class", "targetLine" i)
.attr("d", lineFunction(metricList))
.style("stroke", "#959595")
.style("stroke-width", 1);
// create symbols along the line
svg.append("g")
.selectAll("path")
.data(metricList)
.enter()
.append("path")
.attr("class", "symbol" i)
.attr("transform", function (k) {
return "translate(" (x0(k) x1(d[attributeName]) x1.rangeBand() / 2) ","
y( d[target]) ")";
})
.attr("d", d3.svg.symbol()
.type(symbol(d[attributeName]))
.size(64))
.style("fill", color(d[attributeName]))
.style("stroke", "000000")
.on("mouseover", function (k) {
d3.select(this).attr("d", d3.svg.symbol().type(symbol(d[attributeName])).size(180));
})
.on("mouseout", function (k) {
d3.select(this).attr("d", d3.svg.symbol().type(symbol(d[attributeName])).size(64));
})
.append("title")
.text(target " for " d[attributeName] ": " d[target]);
});
// toggle between linear and sqrt y axis
var sqrtScale = d3.scale.sqrt().clamp(true).range([height, 0]);
sqrtScale.domain([
Math.min(0, minData) * space_to_top,
Math.max(0, maxData) * space_to_top
]);
var sqrtAxis = d3.svg.axis().scale(sqrtScale).orient('left');
var log = false;
var transitionDuration = 500;
var lineFunction_sqrt = d3.svg.line()
.x(function (k) { return x0(k) x1(data[i][attributeName]) x1.rangeBand() / 2; })
.y(function (k) { return sqrtScale( data[i][target]); });
var lineFunction_linear = d3.svg.line()
.x(function (k) { return x0(k) x1(data[i][attributeName]) x1.rangeBand() / 2; })
.y(function (k) { return y( data[i][target]); });
invisibleRect = svg.append('rect')
.attr({
'x': -margin.left,
'y': 0,
'height': height,
'width': margin.left,
'fill': '#FFFFFF',
'opacity': 0.0,
'id': 'invisibleRect'
});
invisibleRect.on('click', function () {
try {
hoverHelp.remove();
}
catch (ReferenceError) {
console.log("There's no hoverHelp right now.");
}
if (!log) {
svg.select('.y.axis')
.transition()
.duration(transitionDuration)
.call(sqrtAxis);
drawBars.selectAll("rect")
.transition()
.duration(transitionDuration)
.attr("y", function (d) { return sqrtScale(Math.max(0, d.value)); })
.attr("height", function (d) { return Math.abs(sqrtScale(d.value) - sqrtScale(0)); });
for (i = 0; i < data.length; i ) {
svg.select(".targetLine" i)
.transition()
.duration(transitionDuration)
.attr("d", lineFunction_sqrt(metricList, i));
};
for (i = 0; i < data.length; i ) {
svg.selectAll(".symbol" i)
.transition()
.duration(transitionDuration)
.attr("transform", function (k) {
return "translate(" (x0(k) x1(data[i][attributeName]) x1.rangeBand() / 2) ","
sqrtScale( data[i][target]) ")";
});
};
log = true;
} else {
svg.select('.y.axis')
.transition()
.duration(transitionDuration)
.call(yAxis);
drawBars.selectAll("rect")
.transition()
.duration(transitionDuration)
.attr("y", function (d) { return y(Math.max(0, d.value)); })
.attr("height", function (d) { return Math.abs(y(d.value) - y(0)); });
for (i = 0; i < data.length; i ) {
svg.select(".targetLine" i)
.transition()
.duration(transitionDuration)
.attr("d", lineFunction_linear(metricList, i));
};
for (i = 0; i < data.length; i ) {
svg.selectAll(".symbol" i)
.transition()
.duration(transitionDuration)
.attr("transform", function (k) {
return "translate(" (x0(k) x1(data[i][attributeName]) x1.rangeBand() / 2) ","
y( data[i][target]) ")";
});
};
log = false;
}
});
invisibleRect.on('mouseover', function () {
debugger;
var coords = d3.mouse(invisibleRect.node());
var hoverHelp = svg.append('g').attr('id', 'hoverHelp');
var x = coords[0];
var y = coords[1];
var triangleSize = 25;
var rectWidth = 200;
var rectHeight = 50;
hoverHelp.append('polygon')
.attr({
'fill': '#3F0040',
'opacity': 0.5,
'points': x ',' y ' ' (x triangleSize) ',' (y - triangleSize) ' ' (x triangleSize rectWidth) ',' (y - triangleSize) ' ' (x triangleSize rectWidth) ',' (y - triangleSize rectHeight) ' ' (x triangleSize) ',' (y - triangleSize rectHeight) ' ' (x triangleSize) ',' (y triangleSize),
'stroke-width': 3,
'stroke': '#FD00FF',
'stroke-linecap': 'round'
});
hoverHelp.append('text')
.attr({
'x': x triangleSize rectWidth / 2,
'y': y - triangleSize rectHeight / 2,
'text-anchor': 'middle',
'dominant-baseline': 'central',
'fill': '#FFFFFF',
'text-weight': 'bold'
})
.text('Click to toggle axis.');
});
invisibleRect.on('mouseout', function () {
try {
hoverHelp.remove();
} catch (ReferenceError) {
console.log("There's no hoverHelp right now.");
}
});