Добавить div поверх диаграммы svg (D3.js )

#javascript #css #d3.js #svg

#javascript #css #d3.js #svg

Вопрос:

У меня есть гистограмма, где я хотел бы добавить круглый красный крестик в правом верхнем углу каждой строки, чтобы показать, что пользователь может удалить определенную строку, но у меня возникли проблемы с выяснением, как это добавить. Мне нравится, чтобы конечное изображение было таким, но также повторялось и на других четырех столбцах.Конечная цель

Я предоставил jsfiddle вместе с JS-кодом, который выполняет все остальное, что мне нравится в графике, за исключением отсутствия красного x.

Демокод

     // graph variables
    var xScale                 ,
        yScale                 ,
        xAxis                  ,
        yAxis                  ;

    // chart dimensions
    var margin   = { top: 20, right: 30, bottom: 20, left: 70 },
        width    =  $('#chart').width() - margin.left - margin.right,
        height   =  $(window).height() / 3.5 - margin.top - margin.bottom;

    // color palette for graph
    var colors = [ '#4398B5', '#ADC4CC', '#92B06A', '#E09D2A', '#DE5F32' ];

    var data = [
        { id : 1, value : 100},
        { id : 2, value : 200},
        { id : 3, value : 300},
        { id : 4, value : 400},
        { id : 5, value : 500}
    ];

    // svg object for graph
    var svg;

    xScale = d3.scaleBand()
               .domain( d3.range( data.length ) )
               .range( [ 0, width ] )
               .padding( 0.1 );

    var yMax = d3.max( data, function( d ) {
        return d.value;
    });

    yScale = d3.scaleLinear()
               .domain( [ 0, yMax  ] )
               .range( [ height, 0 ] );


    xAxis = d3.axisBottom( xScale );
    yAxis = d3.axisLeft( yScale );

    var yTicks       = yAxis.ticks(5),
        yTicksFormat = yAxis.tickFormat( d3.format( '$,' ) );

    svg = d3.select( '#chart svg' )
                    .attr('viewBox', '0 0 '    ( width   margin.left   margin.right )   ' '   ( height    margin.top   margin.bottom ) )
                    .attr('height', ( height   'px' ) )
                    .attr('width', '100%')
                    .attr('preserveAspectRatio', 'none')
                    .append( 'g' )
                    .attr( 'transform', 'translate('   margin.left   ','   margin.top   ')' );

    svg.selectAll( 'rect' )
       .data( data )
       .enter()
       .append( 'rect' )
           .attr('x', function ( d, i ) {
                return xScale( i );
           })
           .attr('y', function( d, i ) {
                return yScale( 0 );
           })
           .attr( 'height', function( d ) {
               return height - yScale( 0 );
           })
           .attr( 'width', xScale.bandwidth() )
           .attr('fill', function( d, i ) {
               return colors[ i ];
           })
           .transition()
           .duration( 1500 )
           .attr( 'y', function( d, i ) {
               return yScale( d.value );
           })
           .attr( 'height', function( d ) {
               return height - yScale( d.value );
           })
           .on('end', function( d, i ) {
                /*Insert this button somewhere
                    <button type="button" class="btn btn-default btn-circle btn-danger"><i class="glyphicon glyphicon-remove"></i></button>*/

           });

    svg.append( 'g' )
       .attr( 'class', 'yAxis' )
       .attr( 'transform', 'translate(0, '   (-1)   ')')
       .call( yAxis );
  

Я бы предположил, что нужно вставить красный крестик после вызова каждой .on('end', function...) функции bars.

Сам по себе красный x будет

 <button type="button" class="btn btn-default btn-circle btn-danger"><i class="glyphicon glyphicon-remove"></i></button>*/
  

И CSS для этого будет

     .btn-circle {
        width: 19px;
        height: 19px;
        text-align: center;
        padding: 1px 0;
        font-size: 13px;
        line-height: 0.1;
        border-radius: 30px;
    }
  

который предоставляется в JSFiddle. Любая помощь будет с благодарностью принята.

Спасибо!

Комментарии:

1. вам нужно, чтобы X рос вместе с столбцами? или просто появится в конце анимации?

2. Извините, если вы упомянули, что я думаю, что все в порядке, если значок остается того же размера, пока он отображается в правом верхнем углу. На случай, если я захочу, чтобы он рос, я думаю, я мог бы поместить его в адаптивный div, и все будет в порядке, но я не уверен.

3. Я имел в виду — вам нужно их анимировать — поднимать с помощью баров, появляться в конце загрузки SVG или просто быть там постоянно?

4. О, моя ошибка, да, мне нравится, чтобы они начинались снизу, если это возможно, и поднимались вместе с баром.

5. Хм, этот SVG меняет размер в зависимости от высоты окна. Разве это не будет фиксированный размер?

Ответ №1:

Вместо добавления a div (или любого другого элемента HTML, который вы не можете добавить в SVG), проще добавить элемент круга SVG и текстовый элемент SVG, имитирующий кнопку:

 var circles = svg.selectAll('.circles')
    .data(data)
    .enter()
    .append('circle').attr("cursor", "pointer")
    .attr('cx', function (d, i) {
        return xScale(i)  xScale.bandwidth();
     })
    .attr('cy', function(d, i) {
        return yScale(0);
    })
    .attr('fill', "red").attr("r", 8)
    .transition()
    .duration(1500)
    .attr('cy', function(d, i) {
         return yScale( d.value );
    });

var xtext = svg.selectAll('.xtext')
    .data(data)
    .enter()
    .append('text')
    .attr('x', function (d, i) {
        return xScale( i )  xScale.bandwidth();
    })
    .attr('y', function( d, i ) {
        return yScale( 0 );
    })
    .attr('fill', "white")
    .attr("text-anchor", "middle")
    .attr("dominant-baseline", "central")
    .attr("pointer-events", "none")
    .text("x")
    .transition()
    .duration( 1500 )
    .attr( 'y', function( d, i ) {
       return yScale( d.value );
    });
  

Вот скрипка: https://jsfiddle.net/dcb8ok9j /

PS: это добавляет только круги, вам нужно будет добавить поведение отдельно.