d3 минимальное значение x, даже если бар на гистограмме становится меньше - PullRequest
0 голосов
/ 04 февраля 2020

Я работал над гистограммой, и я хотел бы добавить к ней пару функций.

Я бы хотел, чтобы все знали, что я не публикую вопрос до Я исчерпал все остальные варианты и потерял терпение. Я действительно хочу попытаться выяснить это самостоятельно, но я совершенно новичок в этом.

Во-первых, я хотел бы добавить эффект наведения мыши, чтобы значение отображалось при наведении курсора на планку. и значение, которое находится справа от бара, должно исчезнуть. При отключении мыши значение справа должно появиться снова.

Во-вторых, я бы хотел, чтобы значение рядом с полосой оставалось на 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}
]

Вот также несколько изображений. Спасибо еще раз всем, кто помог.

Желая избежать этого

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...