#javascript #jquery #d3.js #charts
#javascript #jquery #d3.js #Диаграммы
Вопрос:
Я создал столбчатую диаграмму с наложением, теперь я расширяю функцию диаграммы, так как при наведении курсора мыши на легенду должны выделяться соответствующие столбцы.
Проблема, с которой я сталкиваюсь, заключается в том, что событие наведения курсора мыши работает только с последней легендой, но выделяет каждый прямоугольный слой на диаграмме.
Проблема, показанная на рисунке ниже.Это изображение появляется при наведении курсора мыши на D_Lines Legend Rect
Моя часть кода
var svg = d3.select("body")
.append("svg")
.attr("width", width margin.left margin.right)
.attr("height", height margin.top margin.bottom)
.append("g")
.attr("transform", "translate(" margin.left "," margin.top ")");
var fData =
[{"orders":"A","Total_Orders":76,"A_Lines":123,"B_Lines":0,"C_Lines":0,"D_Lines":0,"Total_Lines":123,"Total_Units":3267},
{"orders":"B","Total_Orders":68,"A_Lines":0,"B_Lines":107,"C_Lines":0,"D_Lines":0,"Total_Lines":107,"Total_Units":3115},
{"orders":"C","Total_Orders":81,"A_Lines":0,"B_Lines":0,"C_Lines":123,"D_Lines":0,"Total_Lines":123,"Total_Units":3690},
{"orders":"D","Total_Orders":113,"A_Lines":0,"B_Lines":0,"C_Lines":0,"D_Lines":203,"Total_Lines":203,"Total_Units":7863},
{"orders":"AB","Total_Orders":62,"A_Lines":70,"B_Lines":76,"C_Lines":0,"D_Lines":0,"Total_Lines":146,"Total_Units":1739},
{"orders":"AC","Total_Orders":64,"A_Lines":77,"B_Lines":0,"C_Lines":79,"D_Lines":0,"Total_Lines":156,"Total_Units":2027},
{"orders":"AD","Total_Orders":100,"A_Lines":127,"B_Lines":0,"C_Lines":0,"D_Lines":144,"Total_Lines":271,"Total_Units":6467},
{"orders":"BC","Total_Orders":64,"A_Lines":0,"B_Lines":80,"C_Lines":84,"D_Lines":0,"Total_Lines":164,"Total_Units":1845},
{"orders":"BD","Total_Orders":91,"A_Lines":0,"B_Lines":108,"C_Lines":0,"D_Lines":135,"Total_Lines":243,"Total_Units":4061},
{"orders":"CD","Total_Orders":111,"A_Lines":0,"B_Lines":0,"C_Lines":132,"D_Lines":147,"Total_Lines":279,"Total_Units":5011},
{"orders":"ABC","Total_Orders":45,"A_Lines":58,"B_Lines":63,"C_Lines":55,"D_Lines":0,"Total_Lines":176,"Total_Units":1245},
{"orders":"ABD","Total_Orders":69,"A_Lines":105,"B_Lines":87,"C_Lines":0,"D_Lines":116,"Total_Lines":308,"Total_Units":4538},
{"orders":"ACD","Total_Orders":66,"A_Lines":91,"B_Lines":0,"C_Lines":88,"D_Lines":132,"Total_Lines":311,"Total_Units":4446},{
{"orders":"BCD","Total_Orders":68,"A_Lines":0,"B_Lines":84,"C_Lines":95,"D_Lines":111,"Total_Lines":290,"Total_Units":4187},
{"orders":"ABCD","Total_Orders":56,"A_Lines":96,"B_Lines":90,"C_Lines":93,"D_Lines":143,"Total_Lines":422,"Total_Units":6331}]
var headers = ["A_Lines", "B_Lines", "C_Lines", "D_Lines"];
var layers = d3.layout.stack()(headers.map(function (count) {
return fData.map(function (d) {
// alert(d);
return { x: d.ORDER_TYPE, y: d[count] };
});
}));
//StackedBar Rectangle Max
var yStackMax = d3.max(layers, function (layer) { return d3.max(layer, function (d) { return d.y0 d.y; }); });
// Set x, y and colors
var xScale = d3.scale.ordinal()
.domain(layers[0].map(function (d) { return d.x; }))
.rangeRoundBands([25, width], .08);
colors = ["#9999CC", "#F7A35C", "#99CC99", "#CCCC99"];
var y = d3.scale.linear()
.domain([0, yStackMax])
.range([height, 0]);
var colorScale = d3.scale.ordinal()
.domain(headers)
.range(colors);
// Define and draw axes
var xAxis = d3.svg.axis()
.scale(xScale)
.tickSize(1)
.tickPadding(6)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"))
var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function (d, i) { return colorScale(i); });
var rect = layer.selectAll("rect")
.data(function (d) { return d; })
.enter().append("rect")
.attr("x", function (d) { return xScale(d.x); })
.attr("y", height)
.attr("width", xScale.rangeBand())
.attr("height", 0)
.attr("class", function (d) {
return "rect bordered " "color-" colorScale(d.value).substring(1);
});
debugger;
layer.selectAll("text.rect")
.data(function (layer) { return layer; })
.enter().append("text")
.attr("text-anchor", "middle")
.attr("x", function (d) { return xScale(d.x) xScale.rangeBand() / 2; })
.attr("y", function (d) { return y(d.y d.y0) - 3; })
.text(function (d) { return d.y d.y0; })
.style("fill", "4682b4");
//********** AXES ************
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," height ")")
.call(xAxis)
.selectAll("text").style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function (d) {
return "rotate(-45)"
});
svg.attr("class", "x axis")
.append("text")
.attr("text-anchor", "end") // this makes it easy to centre the text as the transform is applied to the anchor
.attr("transform", "translate(" (width / 2) "," (height 60) ")") // centre below axis
.text("Order Velocity Group");
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(20,0)")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr({ "x": -75, "y": -70 })
.attr("dy", ".75em")
.style("text-anchor", "end")
.text("No. Of Lines");
//********** LEGEND ************
var legend = svg.selectAll(".legend")
.data(headers.slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function (d, i) { return "translate(" i * (-100) "," (height 50) ")"; });
debugger;
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", function (d, i) { return colors[i]; })
.on("mouseover", function (d, i) {
svg.selectAll("rect.color-" colors[i].substring(1)).style("stroke", "blue");
})
.on("mouseout", function (d, i) {
svg.selectAll("rect.color-" colors[i].substring(1)).style("stroke", "white");
});
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function (d) { return d; });
transitionStacked();
function transitionStacked() {
y.domain([0, yStackMax]);
rect.transition()
.duration(500)
.delay(function (d, i) { return i * 10; })
.attr("y", function (d) { return y(d.y0 d.y); })
.attr("height", function (d) { return y(d.y0) - y(d.y0 d.y); })
.transition()
.attr("x", function (d) { return xScale(d.x); })
.attr("width", xScale.rangeBand());
};
}
Может ли кто-нибудь помочь мне преодолеть эту проблему.
Комментарии:
1. не могли бы вы опубликовать полный код с вашим
fData
, чтобы наблюдать за поведением диаграммы.2. @Amani Я обновил вопрос с помощью FData, пожалуйста, проверьте
3. с вами ничего
hover
не случилось, если вы просто присваиваете неправильный класс вашимrect
элементам
Ответ №1:
Вы добавляете один и тот же класс: color-9999CC
ко всем своим rect
элементам, поэтому при наведении курсора мыши на последний элемент легенды, имеющий цвет: #9999CC
rect
будет выбран весь элемент.
Чтобы правильно создать требуемый класс, вы можете добавить соответствующую информацию о цвете к каждому элементу вашего layers
объекта при его создании.
Я добавил color
свойство, которое имеет в качестве значения цвет соответствующего headers
элемента:
var layers = d3.layout.stack()(
headers.map(function (count) {
return fData.map(function (d,i) {
return { x: d.orders, y: d[count] , color: colorScale(count)};
/*color = current headers item color */
});
}));
Затем при создании ваших rect
элементов вы можете добавить к каждому элементу класс, обратившись к его свойству цвета следующим образом:
var rect = layer.selectAll("rect")
.data(function (d) { return d; })
.....
.attr("class", function (d) {
return "rect bordered " "color-" d.color.substring(1);
});
полный код:
var margin = {top:10, right: 10, bottom: 80, left: 50},
width =960,
height=650;
var svg = d3.select("body")
.append("svg")
.attr("width", width margin.left margin.right)
.attr("height", height margin.top margin.bottom)
.append("g")
.attr("transform", "translate(" margin.left "," margin.top ")");
var fData =
[{"orders":"A","Total_Orders":76,"A_Lines":123,"B_Lines":0,"C_Lines":0,"D_Lines":0,"Total_Lines":123,"Total_Units":3267},
{"orders":"B","Total_Orders":68,"A_Lines":0,"B_Lines":107,"C_Lines":0,"D_Lines":0,"Total_Lines":107,"Total_Units":3115},
{"orders":"C","Total_Orders":81,"A_Lines":0,"B_Lines":0,"C_Lines":123,"D_Lines":0,"Total_Lines":123,"Total_Units":3690},
{"orders":"D","Total_Orders":113,"A_Lines":0,"B_Lines":0,"C_Lines":0,"D_Lines":203,"Total_Lines":203,"Total_Units":7863},
{"orders":"AB","Total_Orders":62,"A_Lines":70,"B_Lines":76,"C_Lines":0,"D_Lines":0,"Total_Lines":146,"Total_Units":1739},
{"orders":"AC","Total_Orders":64,"A_Lines":77,"B_Lines":0,"C_Lines":79,"D_Lines":0,"Total_Lines":156,"Total_Units":2027},
{"orders":"AD","Total_Orders":100,"A_Lines":127,"B_Lines":0,"C_Lines":0,"D_Lines":144,"Total_Lines":271,"Total_Units":6467},
{"orders":"BC","Total_Orders":64,"A_Lines":0,"B_Lines":80,"C_Lines":84,"D_Lines":0,"Total_Lines":164,"Total_Units":1845},
{"orders":"BD","Total_Orders":91,"A_Lines":0,"B_Lines":108,"C_Lines":0,"D_Lines":135,"Total_Lines":243,"Total_Units":4061},
{"orders":"CD","Total_Orders":111,"A_Lines":0,"B_Lines":0,"C_Lines":132,"D_Lines":147,"Total_Lines":279,"Total_Units":5011},
{"orders":"ABC","Total_Orders":45,"A_Lines":58,"B_Lines":63,"C_Lines":55,"D_Lines":0,"Total_Lines":176,"Total_Units":1245},
{"orders":"ABD","Total_Orders":69,"A_Lines":105,"B_Lines":87,"C_Lines":0,"D_Lines":116,"Total_Lines":308,"Total_Units":4538},
{"orders":"ACD","Total_Orders":66,"A_Lines":91,"B_Lines":0,"C_Lines":88,"D_Lines":132,"Total_Lines":311,"Total_Units":4446},
{"orders":"BCD","Total_Orders":68,"A_Lines":0,"B_Lines":84,"C_Lines":95,"D_Lines":111,"Total_Lines":290,"Total_Units":4187},
{"orders":"ABCD","Total_Orders":56,"A_Lines":96,"B_Lines":90,"C_Lines":93,"D_Lines":143,"Total_Lines":422,"Total_Units":6331}]
var headers = ["A_Lines", "B_Lines", "C_Lines", "D_Lines"];
var colors = ["#9999CC", "#F7A35C", "#99CC99", "#CCCC99"];
var colorScale = d3.scale.ordinal()
.domain(headers)
.range(colors);
var layers = d3.layout.stack()(
headers.map(function (count) {
return fData.map(function (d,i) {
return { x: d.orders, y: d[count] , color: colorScale(count)};
});
}));
//StackedBar Rectangle Max
var yStackMax = d3.max(layers, function (layer) { return d3.max(layer, function (d) { return d.y0 d.y; }); });
// Set x, y and colors
var xScale = d3.scale.ordinal()
.domain(layers[0].map(function (d) { return d.x; }))
.rangeRoundBands([25, width], .08);
var y = d3.scale.linear()
.domain([0, yStackMax])
.range([height, 0]);
// Define and draw axes
var xAxis = d3.svg.axis()
.scale(xScale)
.tickSize(1)
.tickPadding(6)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"))
var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function (d, i) { return colorScale(i); });
var rect = layer.selectAll("rect")
.data(function (d) { return d; })
.enter().append("rect")
.attr("x", function (d) { return xScale(d.x); })
.attr("y", height)
.attr("width", xScale.rangeBand())
.attr("height", 0)
.attr("class", function (d,i) {
return "rect bordered " "color-" d.color.substring(1);
});
layer.selectAll("text.rect")
.data(function (layer) { return layer; })
.enter().append("text")
.attr("text-anchor", "middle")
.attr("x", function (d) { return xScale(d.x) xScale.rangeBand() / 2; })
.attr("y", function (d) { return y(d.y d.y0) - 3; })
.text(function (d) { return d.y d.y0; })
.style("fill", "4682b4");
//********** AXES ************
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," height ")")
.call(xAxis)
.selectAll("text").style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function (d) {
return "rotate(-45)"
});
svg.attr("class", "x axis")
.append("text")
.attr("text-anchor", "end") // this makes it easy to centre the text as the transform is applied to the anchor
.attr("transform", "translate(" (width / 2) "," (height 60) ")") // centre below axis
.text("Order Velocity Group");
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(20,0)")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr({ "x": -75, "y": -70 })
.attr("dy", ".75em")
.style("text-anchor", "end")
.text("No. Of Lines");
//********** LEGEND ************
var legend = svg.selectAll(".legend")
.data(headers)
.enter().append("g")
.attr("class", "legend")
.attr("transform", function (d, i) { return "translate(" (headers.length-(i 1))*-100 "," (height 50) ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", function (d, i) { return colors[i]; })
.on("mouseover", function (d, i) {
svg.selectAll("rect.color-" colors[i].substring(1)).style("stroke", "blue");
})
.on("mouseout", function (d, i) {
svg.selectAll("rect.color-" colors[i].substring(1)).style("stroke", "white");
});
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function (d) { return d; });
transitionStacked();
function transitionStacked() {
y.domain([0, yStackMax]);
rect.transition()
.duration(500)
.delay(function (d, i) { return i * 10; })
.attr("y", function (d) { return y(d.y0 d.y); })
.attr("height", function (d) { return y(d.y0) - y(d.y0 d.y); })
.transition()
.attr("x", function (d) { return xScale(d.x); })
.attr("width", xScale.rangeBand());
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.0/d3.min.js"></script>
<body></body>
Комментарии:
1. Спасибо @Amani за быстрый ответ. Здесь присвоение цветов столбцам и легенде неверно. Для прямоугольника «A» цвет отображается в легенде «D».
2. Привет, что именно не так? для лучшего представления я создал скрипку jsfiddle.net/wc41c9wu не могли бы вы указать мне на неправильное поведение?
3. В легенде я сохранил headers.reverse(), чтобы получить порядок ABCD, так как изменить цвета размещения в обратном порядке
4. Пожалуйста, посмотрите на цвет легенды и соответствующий верхний свет прямоугольника
5. вы можете создать свою легенду, полностью изменив свои данные следующим образом:
var legend = svg.selectAll(".legend") .data(headers) .enter().append("g") .attr("class", "legend") .attr("transform", function (d, i) { return "translate(" (headers.length-(i 1))*-100 "," (height 50) ")"; });
См. Обновленный ответ