2

I am trying to create some circles in d3js dynamically, But for some reason it fails. My requirement is to show two small circles on the rectangle when I hover the rectangle. on the mouse out event circles should hide. I tried to it by creating a rect object and passing it to a function, then in the function I get the group of the rectangle and try to append circles to it.

Can anyone tell me where the error is?

function drawCircle(rect, side){

        var g = (rect.parentNode);
//                var g = d3.select(aaa.parentNode);
//        console.log(g.attr('id'));


        g.append('rect')
                .attr('x', 10)
                .attr('y', 10)
                .attr('width', 500)
                .attr('height', 500)
                .style('fill', 'red')
        ;

        var x = 0, y = 0, r =0;

        var rectHeight = parseFloat(rect.attr('height'));
        var rectWidth = parseFloat(rect.attr('width'));
        var rectX = parseFloat(rect.attr('x'));
        var rectY = parseFloat(rect.attr('y'));

        y = rectY + rectHeight/2;
        r  = rectHeight/8;

        if(side == 'left'){
            x = rectX;
        }else{
            x = rectX + rectWidth;
        }

        g.append('circle')
                .attr('cx', x)
                .attr('cy', y)
                .attr('r', r)
                .style('visibility', 'hidden')
                .on('mouseover', function(){
                   g
                            .selectAll('circle')
                            .style('visibility', 'visible')
                    ;
                })
                .on('mouseout', function () {
                    g
                            .selectAll('circle')
                            .style('visibility', 'hidden')
                });

        rect
                .on('mouseover', function(){

//                    alert('hover');

                    g
                            .selectAll('circle')
                            .style('visibility', 'visible')
                    ;
                })
                .on('mouseout', function(){
                   g
                            .selectAll('circle')
                            .style('visibility', 'hidden')

                })




    }




 var rectangle = {
        width : 50,
        height:50,
        x:100,
        y:100

    }; 

   var svg = d3.select('svg');

    var g = svg.append('g').attr('id', 'group');

    console.log(g.attr('id'));

    var rect = g.append('rect')
                    .attr('id', 'aaa')
            .attr('x', rectangle.x)
            .attr('y', rectangle.y)
            .attr('width', rectangle.width)
            .attr('height', rectangle.height)
            .style('fill', 'blue')
            .on('mouseover', function(){

                    drawCircle(this, 'right');
                    drawCircle(this, 'left');
                        })

     ;
8
  • Sorry. Here is the fiddle jsfiddle.net/fawzan/4a17z1pn Commented Jun 15, 2015 at 5:21
  • Remember in JSfiddle, you have to add the link to D3 as an external resource... Fortunately there is a Content Distribution Network (CDN) available for that library... cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js Commented Jun 15, 2015 at 5:40
  • error: Uncaught TypeError: g.append is not a function? Commented Jun 15, 2015 at 5:42
  • yes, That is what confused me. How can I aces the parent node from the function? Commented Jun 15, 2015 at 5:43
  • I'd start by cleaning up the code a bit.. get indents cleaned up, use a different var name for g inside the function (g is both a 'global' and 'local' variable... change the name of one of them to make troubleshooting easier...) Commented Jun 15, 2015 at 5:46

2 Answers 2

3

You want something like this?

[0][0] gives you the underlying DOM element if you have a d3 selection. I also removed the big red test rect as that stopped everything working.

function drawCircle(rect, side){

    var g = d3.select(rect[0][0].parentNode);

    var x = 0, y = 0, r =0;

    var rectHeight = parseFloat(rect.attr('height'));
    var rectWidth = parseFloat(rect.attr('width'));
    var rectX = parseFloat(rect.attr('x'));
    var rectY = parseFloat(rect.attr('y'));

    y = rectY + rectHeight/2;
    r  = rectHeight/8;

    if(side == 'left'){
        x = rectX;
    }else{
        x = rectX + rectWidth;
    }

    g.append('circle')
            .attr('cx', x)
            .attr('cy', y)
            .attr('r', r)
            .style('visibility', 'hidden')
            .on('mouseover', function(){
               g
                        .selectAll('circle')
                        .style('visibility', 'visible')
                ;
            })
            .on('mouseout', function () {
                g
                        .selectAll('circle')
                        .style('visibility', 'hidden')
            });

    rect
            .on('mouseover', function(){
                g
                        .selectAll('circle')
                        .style('visibility', 'visible')
                ;
            })
            .on('mouseout', function(){
               g
                        .selectAll('circle')
                        .style('visibility', 'hidden')

            })




}

var rectangle = {
    width : 50,
    height:50,
    x:100,
    y:100

}; 

var svg = d3.select('svg');

var g = svg.append('g').attr('id', 'group');

console.log(g.attr('id'));

var rect = g.append('rect')
                .attr('id', 'aaa')
        .attr('x', rectangle.x)
        .attr('y', rectangle.y)
        .attr('width', rectangle.width)
        .attr('height', rectangle.height)
        .style('fill', 'blue')
        .on('mouseover', function(){

                drawCircle(rect, 'right');
                drawCircle(rect, 'left');
                    })

 ;
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks man. It works great. Thanks for the pointer rect[0][0].parentNode . That was the exact same place I struggled .
Hi, I found an elegant way, Checkout my answer. :)
1

Robert's Answer worked fine. But I have found another solution. I think this is more elegant than that.

function drawCircle(rect, side){

    var g = d3.select(rect.node().parentNode);

    var x = 0, y = 0, r =0;

    var rectHeight = parseFloat(rect.attr('height'));
    var rectWidth = parseFloat(rect.attr('width'));
    var rectX = parseFloat(rect.attr('x'));
    var rectY = parseFloat(rect.attr('y'));

    y = rectY + rectHeight/2;
    r  = rectHeight/8;

    if(side == 'left'){
        x = rectX;
    }else{
        x = rectX + rectWidth;
    }

    g.append('circle')
            .attr('cx', x)
            .attr('cy', y)
            .attr('r', r)
            .style('visibility', 'hidden')
            .on('mouseover', function(){
               g
                        .selectAll('circle')
                        .style('visibility', 'visible')
                ;
            })
            .on('mouseout', function () {
                g
                        .selectAll('circle')
                        .style('visibility', 'hidden')
            });

    rect
            .on('mouseover', function(){
                g
                        .selectAll('circle')
                        .style('visibility', 'visible')
                ;
            })
            .on('mouseout', function(){
               g
                        .selectAll('circle')
                        .style('visibility', 'hidden')

            })




}

var rectangle = {
    width : 50,
    height:50,
    x:100,
    y:100

}; 

var svg = d3.select('svg');

var g = svg.append('g').attr('id', 'group');

console.log(g.attr('id'));

var rect = g.append('rect')
                .attr('id', 'aaa')
        .attr('x', rectangle.x)
        .attr('y', rectangle.y)
        .attr('width', rectangle.width)
        .attr('height', rectangle.height)
        .style('fill', 'blue')
        .on('mouseover', function(){

                drawCircle(rect, 'right');
                drawCircle(rect, 'left');
                    })

 ;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.