简体   繁体   中英

d3 bar chart- How do I automatically change font-size of value so that it fits within bar

I've created a d3 bar chart that shows the values within the bar.

条形内的值

When a user hovers over a bar it shows the values change to show how all other countries compare to that country. 悬停没有问题

However, sometimes the comparison is too large - when it is over 100% or over 1000%. 悬停有问题

I would like to dynamically change the font size so that the value fits the bar width.

Ideally, I would like to do this calculation before the value is rendered to prevent re-rendering.

The bar width isn't constant. It depends on the number of countries the user has selected and the user's screen size.

How can I know the width of the value before it is rendered (based on the number of characters it contains) and reduce the font-size so it never takes up more than 95% of the bar width?

This is my code for rendering the bar:

    function renderVerticalBars(data, measurements, metric, countryID) {

    let selectDataForBarCharts = d3.select("svg")
        .selectAll("rect")
        .data(data, d => d[countryID])

    selectDataForBarCharts
        .enter()
        .append("rect")
        .attr('width', measurements.xScale.bandwidth())
        .attr("height", 0)
        .attr('y', d => measurements.yScale(0))
        .merge(selectDataForBarCharts)
        .on('mouseover', (event, barData) => { displayComparisons(event, barData, data, metric, countryID, measurements); displayToolTip(barData) })
        .on("mousemove", (event) => tooltip.style("top", (event.pageY - 10) + "px").style("left", (event.pageX + 10) + "px"))
        .on('mouseout', () => { removeComparisons(data, metric, countryID, measurements); tooltip.style("visibility", "hidden") })
        .transition().delay(500)
        .attr("transform", `translate(0, ${measurements.margin.top})`)
        .attr('width', measurements.xScale.bandwidth())
        .attr('x', (d) => measurements.xScale(d[countryID]))
        .transition()
        .ease(d3.easeLinear)
        .duration(setSpeed())
        .attr("height", d => measurements.innerHeight - measurements.yScale(d[metric]))
        .attr("y", (d) => measurements.yScale(d[metric]))
        .attr("fill", d => setBarColor(d))
        .on("end", () => renderValuesInBars(data, metric, countryID, measurements, [], countriesDownloaded))


    selectDataForBarCharts.exit()
        .transition().duration(500).attr("height", 0).attr("y", d => measurements.yScale(0)).remove()
}

and this is the code for rendering the values in the bar:

function renderValuesInBars(data, metric, countryID, measurements, barData, countriesDownloaded) {


function calculateFontSize(data) {

        return ((.25 / data.length) * Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)).toString()
}


let values = d3.select("svg")
    .selectAll(".casesPerCapita")
    .data(data, d => d[countryID])

values
    .enter()
    .append("text")

    .attr("y", 0)
    .style("opacity", "1")
    .merge(values)
    .attr("class", metric)
    .attr('text-anchor', setTextAnchor())
    .attr('alignment-baseline', setAlignmentBaseline())
    .attr('data-countryCode', d => d.countryCode)
    .attr("x", countryData => setXValue(countryData, measurements, countryID))
    .attr("y", countryData => setYValue(countryData, measurements, metric))
    .style("fill", countryData => setColor(countryData, barData))
    .style("font-size", calculateFontSize(data))
    .text(countryData => decideTextToReturn(countryData))
    .on('mouseover', (event) => makeBarHover(event))
    .on('mouseout', (event) => { stopBarHover(event); tooltip.style("visibility", "hidden") })
    .on("mousemove", (event) => tooltip.style("top", (event.pageY - 10) + "px").style("left", (event.pageX + 10) + "px"))
    .on("end", () => checkValueSize)

values.exit().remove()

}

Try changing your font-size to:

.style("font-size", measurements.xScale.bandwidth()+'%')

This will scale your font size to match your bar width.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM