#javascript #jquery #d3.js
#javascript #jquery #d3.js
Вопрос:
Я хочу создать динамику, .container
в которой каждый из них circle
сохраняет свое size
соотношение и всегда распределяется в соответствии с доступным пространством .container
.
Как мне изменить код, чтобы распределение точек данных всегда изменялось в пределах .container
, сохраняя при этом size
соотношение каждого circle
?
.container {
width: 400px;
height: 200px;
}
(function() {
var json = {
call_data: [
[
"Lifestyle",
1,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/5bb3ce2f801fbc657f83dd57_pp-lifestyle(white).svg"
],
[
"Sports",
2,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/5c9131911ad86f445cb5abc7_pp-sport(white).svg"
],
[
"Environment",
8,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/59f2a4bef42fff000159ba7a_pp-environ(white).svg"
],
[
"Medical",
6,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/59f2a4dc831e8500015fda53_pp-health(white).svg"
],
[
"Food",
4,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/59f8c2cc78cc2d0001fd4a7e_pp-food(white).svg"
]
]
};
var width = 200;
var height = 200;
var tooltip = d3
.select(".bubble_chart")
.append("div")
.classed("tooltip", true);
var svg = d3
.select(".bubble_chart")
.append("svg")
//responsive SVG needs these 2 attributes and no width and height attr
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "0 0 " width " " height);
var bubble = d3.layout
.pack()
.size([200, 200])
.value(function(d) {
return d.size;
})
.padding(12);
// generate data with calculated layout values
var nodes = bubble.nodes(processData(json)).filter(function(d) {
return !d.children;
}); // filter out the outer bubble
var vis = svg.selectAll("circle").data(nodes, function(d, i) {
return d.name i;
});
vis
.enter()
.append("circle")
.attr("transform", function(d) {
return "translate(" d.x "," d.y ")";
})
.attr("class", function(d) {
return d.className;
})
.attr("r", 0)
.transition()
.duration(1000)
.attr("r", function(d) {
return d.r;
});
vis
.enter()
.append("svg:image")
.attr("transform", d => "translate(" d.x "," d.y ")")
.attr("x", d => -(d.r / 1.5) / 2)
.attr("y", d => -(d.r / 1.5) / 2)
.attr("xlink:href", function(d) {
return d.img;
})
.attr("width", d => d.r / 1.5)
.transition()
.duration(1000)
.style("opacity", 1);
/*
vis
.enter()
.append("text")
.attr("transform", d => "translate(" d.x "," d.y ")")
.attr("fill", "white")
.attr("text-anchor", "middle")
.attr("font-size", d => d.r / (d.r * 5 / 100))
.text(d => d.name);
*/
/* vis
.enter()
.append("text")
.attr("transform", d => "translate(" d.x "," d.y ")")
.attr("fill", "white")
.attr("text-anchor", "middle")
.attr("font-size", d => d.r / (d.r * 3 / 100))
.text(d => d.value);
*/
vis
.on("mousemove", function(d) {
tooltip
.style("opacity", 1)
.style("left", d3.event.x - tooltip.node().offsetWidth / 2 "px")
.style("top", d3.event.y 25 "px").html(`
<p>Category: ${d.name}</p>
<p>Ordered: ${d.value}</p>
`);
})
.on("mouseout", function() {
tooltip.style("opacity", 0);
});
function processData(data) {
var obj = data.call_data;
var newDataSet = [];
for (var prop in obj) {
newDataSet.push({
name: obj[prop][0],
className: obj[prop][0].toLowerCase(),
size: obj[prop][1],
img: obj[prop][2]
});
}
return {
children: newDataSet
};
}
var aspect = width / height,
chart = d3.select('.bubble_chart');
d3.select(window)
.on("resize", function() {
var targetWidth = chart.node().getBoundingClientRect().width;
chart.attr("width", targetWidth);
chart.attr("height", targetWidth / aspect);
});
})();
.container {
border: 2px solid red;
width: 400px;
height: 200px;
}
.bubble_chart {
flex: 1;
border: 2px solid
}
.lifestyle {
fill: #89BED3;
}
.sports {
fill: #2A83D4;
}
.environment {
fill: #6CC070;
}
.food {
fill: #665C9E;
}
.medical {
fill: #C13E40;
}
.tooltip {
opacity: 0;
position: absolute;
pointer-events: none;
background-color: #fafafa;
border-radius: 8px;
padding: 15px;
z-index: 999;
box-shadow: 1px 1px 3px 0 rgba(0, 0, 0, .1)
}
.tooltip p {
margin: 0;
}
.tooltip:before {
content: " ";
position: absolute;
border: 12px solid transparent;
border-bottom-color: #fafafa;
top: -20px;
left: 50%;
margin-left: -12px;
}
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.5/d3.js"></script>
<div class="container">
<div class="bubble_chart"></div>
</div>
Ответ №1:
Вы должны с самого начала установить ширину и высоту ограничивающих прямоугольников height и width. Прямо сейчас у вас задано значение 200 пикселей, которые одинаковы.
Сделайте это следующим образом:
var width = document.querySelector(".container").getBoundingClientRect().width;
var height = document.querySelector(".container").getBoundingClientRect().height;
(function() {
var json = {
call_data: [
[
"Lifestyle",
1,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/5bb3ce2f801fbc657f83dd57_pp-lifestyle(white).svg"
],
[
"Sports",
2,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/5c9131911ad86f445cb5abc7_pp-sport(white).svg"
],
[
"Environment",
8,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/59f2a4bef42fff000159ba7a_pp-environ(white).svg"
],
[
"Medical",
6,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/59f2a4dc831e8500015fda53_pp-health(white).svg"
],
[
"Food",
4,
"https://uploads-ssl.webflow.com/59df9e77ad9420000140eafe/59f8c2cc78cc2d0001fd4a7e_pp-food(white).svg"
]
]
};
var width = document.querySelector(".container").getBoundingClientRect().width;
var height = document.querySelector(".container").getBoundingClientRect().height;
var tooltip = d3
.select(".bubble_chart")
.append("div")
.classed("tooltip", true);
var svg = d3
.select(".bubble_chart")
.append("svg")
//responsive SVG needs these 2 attributes and no width and height attr
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "0 0 " width " " height);
var bubble = d3.layout
.pack()
.size([200, 200])
.value(function(d) {
return d.size;
})
.padding(12);
// generate data with calculated layout values
var nodes = bubble.nodes(processData(json)).filter(function(d) {
return !d.children;
}); // filter out the outer bubble
var vis = svg.selectAll("circle").data(nodes, function(d, i) {
return d.name i;
});
vis
.enter()
.append("circle")
.attr("transform", function(d) {
return "translate(" d.x "," d.y ")";
})
.attr("class", function(d) {
return d.className;
})
.attr("r", 0)
.transition()
.duration(1000)
.attr("r", function(d) {
return d.r;
});
vis
.enter()
.append("svg:image")
.attr("transform", d => "translate(" d.x "," d.y ")")
.attr("x", d => -(d.r / 1.5) / 2)
.attr("y", d => -(d.r / 1.5) / 2)
.attr("xlink:href", function(d) {
return d.img;
})
.attr("width", d => d.r / 1.5)
.transition()
.duration(1000)
.style("opacity", 1);
/*
vis
.enter()
.append("text")
.attr("transform", d => "translate(" d.x "," d.y ")")
.attr("fill", "white")
.attr("text-anchor", "middle")
.attr("font-size", d => d.r / (d.r * 5 / 100))
.text(d => d.name);
*/
/* vis
.enter()
.append("text")
.attr("transform", d => "translate(" d.x "," d.y ")")
.attr("fill", "white")
.attr("text-anchor", "middle")
.attr("font-size", d => d.r / (d.r * 3 / 100))
.text(d => d.value);
*/
vis
.on("mousemove", function(d) {
tooltip
.style("opacity", 1)
.style("left", d3.event.x - tooltip.node().offsetWidth / 2 "px")
.style("top", d3.event.y 25 "px").html(`
<p>Category: ${d.name}</p>
<p>Ordered: ${d.value}</p>
`);
})
.on("mouseout", function() {
tooltip.style("opacity", 0);
});
function processData(data) {
var obj = data.call_data;
var newDataSet = [];
for (var prop in obj) {
newDataSet.push({
name: obj[prop][0],
className: obj[prop][0].toLowerCase(),
size: obj[prop][1],
img: obj[prop][2]
});
}
return {
children: newDataSet
};
}
var aspect = width / height,
chart = d3.select('.bubble_chart');
d3.select(window)
.on("resize", function() {
var targetWidth = chart.node().getBoundingClientRect().width;
chart.attr("width", targetWidth);
chart.attr("height", targetWidth / aspect);
});
})();
.container {
border: 2px solid red;
width: 400px;
height: 200px;
}
.bubble_chart {
flex: 1;
border: 2px solid
}
.lifestyle {
fill: #89BED3;
}
.sports {
fill: #2A83D4;
}
.environment {
fill: #6CC070;
}
.food {
fill: #665C9E;
}
.medical {
fill: #C13E40;
}
.tooltip {
opacity: 0;
position: absolute;
pointer-events: none;
background-color: #fafafa;
border-radius: 8px;
padding: 15px;
z-index: 999;
box-shadow: 1px 1px 3px 0 rgba(0, 0, 0, .1)
}
.tooltip p {
margin: 0;
}
.tooltip:before {
content: " ";
position: absolute;
border: 12px solid transparent;
border-bottom-color: #fafafa;
top: -20px;
left: 50%;
margin-left: -12px;
}
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.5/d3.js"></script>
<div class="container">
<div class="bubble_chart"></div>
</div>
Комментарии:
1. Это хорошо для ограничения контейнера, но как мне распределить круги, чтобы заполнить пустое пространство?
2. Вы имеете в виду справа? Как вы хотите, чтобы они выстраивались в линию?
3. Да, я хочу, чтобы они распределялись равномерно и заполняли доступное пространство. Таким образом, для этого может потребоваться динамическое изменение размера пузырьков