Я работал над гистограммой, и я хотел бы добавить к ней пару функций.
Я бы хотел, чтобы все знали, что я не публикую вопрос до Я исчерпал все остальные варианты и потерял терпение. Я действительно хочу попытаться выяснить это самостоятельно, но я совершенно новичок в этом.
Во-первых, я хотел бы добавить эффект наведения мыши, чтобы значение отображалось при наведении курсора на планку. и значение, которое находится справа от бара, должно исчезнуть. При отключении мыши значение справа должно появиться снова.
Во-вторых, я бы хотел, чтобы значение рядом с полосой оставалось на 5 пикселей справа от флага, когда ширина полосы становится меньше, чем флаг ширина.
Вот полный код на этот раз.
data = d3.json('data.json')
.then(data => {data
.forEach(d => {
d.country = d.country;
d.population = +d.population * 1000;
d.flagurl = `../images/countryflags/`+d.country+`.png`;
});
render(data);
});
const render = data => {
const chartTitle = 'Top 10 Most Populous Countries';
const xAxisLabel = 'Population';
const yAxisLabel = 'Country';
const margin = {
top: 100,
right: 75,
bottom: 75,
left: 200
};
const width = 1200 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;
const animateDuration = 750;
const delay = 125;
const countryflagHeight = 50;
const countryflagWidth = 50;
// x axis
const xValuesNumberFormat = number => d3.format(',.0f')(number);
const xValues = d => +d.population;
const xScaleMaxValue = Math.ceil(((d3.max(data, xValues)))/(1000000000))*1000000000-
400000000;
//console.log(xScaleMaxValue);
const xScaleMinValue = Math.ceil((d3.min(data, xValues)));
//console.log(xScaleMinValue);
const xScale = d3.scaleLinear()
.domain([0, xScaleMaxValue])
.range([0, width]);
const xAxisNumberFormat = number => d3.format('.2s')(number)
.replace('G','B')
.replace('0.0','0');
const xAxis = d3.axisBottom(xScale)
.tickFormat(xAxisNumberFormat)
.tickSize(-height)
;
const xPos = d => xScale(xValues(d));
// y axis
const yValues = d => d.country;
const yScale = d3.scaleBand()
.paddingInner(0.2)
.domain(data.map(yValues))
.range([0, height])
;
const yAxis = d3.axisLeft(yScale);
const yPos = d => yScale(yValues(d));
const barHeight = yScale.bandwidth();
// svg chart
const svg = d3.select('#responsivechart3')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.call(responsivefy) // Call responsivefy to make the chart responsive
.append('g')
.attr('class', 'chart')
.attr('transform', `translate(${margin.left}, ${margin.top})`)
;
// x axis
svg.append('g')
.call(xAxis)
.attr('class', 'x-axis')
.attr('transform', `translate(0,${height})`)
.selectAll('.domain')
.remove()
;
// bar values
svg.append('g')
.selectAll('text')
.data(data)
.enter()
.append('text')
.attr('class', 'bar-value')
.attr('x', 0)
.attr('y', yPos)
.text(d => d3.format(',.0f')(+d.population))
.attr('transform', `translate(`+ 5 +`,`+ barHeight/1.5 +`)`)
// animation and delay time for bar values
.transition()
.attr('x', xPos)
//.attr ('y', yPos)
//.attr('transform', `translate(5,`+barHeight/1.5+`)`)
.duration(animateDuration)
.delay(delay)
.ease(d3.easeBounceOut)
;
// y axis
svg.append('g')
.call(yAxis)
.selectAll('.domain, .tick line')
.remove()
;
// chart title
svg.append('text')
.attr('class','chart-title')
.attr('x',width/15)
.attr('y',-40)
.attr('fill', 'black')
.text(chartTitle)
;
// x axis label
svg.append('text')
.attr('class','x-axis-label')
.attr('x',width/3)
.attr('y', height+60)
.attr('fill', 'black')
.text(xAxisLabel)
;
// y axis label
svg.append('text')
.attr('class','y-axis-label')
.attr('x', -height/1.5)
.attr('y', -height/2.75)
.attr('fill', 'black')
.text(yAxisLabel)
.attr('transform', `rotate(-90)`)
;
// bars
svg.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr('class', 'rect')
.attr('y', yPos)
.attr('width', 0)
.attr('height', yScale.bandwidth())
// transition and delay
.transition()
//.attr ('y', yPos)
.attr ('width', xPos)
//.attr('height', yScale.bandwidth())
.duration(animateDuration)
.delay(delay)
.ease(d3.easeBounceOut)
;
// country flags
svg.append('g')
.selectAll('image')
.data(data)
.enter()
.append('image')
.attr('class', 'countryflag')
.attr('href', d => (d.flagurl))
.attr('width', 50)
.attr('height', 0.8*barHeight)
.attr('x', 0)
.attr('y', yPos)
.attr('opacity', 0)
.attr('transform', `translate(`+0.05*barHeight+`,`+0.1*barHeight+`)`)
// transition and delay
.transition()
//.attr ('y', yPos)
.attr ('opacity', 1)
//.attr('height', yScale.bandwidth())
.duration(animateDuration-625)
.delay(delay+animateDuration+375)
;
function responsivefy(svg) {
// Container is the DOM element, svg is appended.
// Then we measure the container and find its
// aspect ratio.
const container = d3.select(svg.node().parentNode),
width = parseInt(svg.style('width'), 10),
height = parseInt(svg.style('height'), 10),
aspect = width / height;
// Add viewBox attribute to set the value to initial size
// add preserveAspectRatio attribute to specify how to scale
// and call resize so that svg resizes on page load
svg.attr('viewBox', `0 0 ${width} ${height}`).
attr('preserveAspectRatio', 'xMinYMid').
call(resize);
d3.select(window).on('resize.' + container.attr('id'), resize);
function resize() {
const targetWidth = parseInt(container.style('width'));
svg.attr('width', targetWidth);
svg.attr('height', Math.round(targetWidth / aspect));
}
}
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text
.append("tspan")
.attr("x", 0)
.attr("y", y)
.attr("dy", ++lineNumber * lineHeight + dy + "em")
.text(word);
}
}
});
}
};
Вот данные
[
{"country":"China","population":1415046},
{"country":"India","population":1354052},
{"country":"United States","population":326767},
{"country":"Indonesia","population":266795},
{"country":"Brazil","population":210868},
{"country":"Pakistan","population":200814},
{"country":"Nigeria","population":195875},
{"country":"Bangladesh","population":166368},
{"country":"Russia","population":143965},
{"country":"Mexico","population":130759}
]
Вот также несколько изображений. Спасибо еще раз всем, кто помог.
Желая избежать этого