1

I am trying to create a pie chart dynamically using plain vanilla JavaScript and SVG, and I want it to have tooltips that show up when you hover over each pie slice that are specific to the particular slice. I can get it working if I insert a <title> node, but I can't customize <title> with CSS to make it look "pretty".

So, I'm trying to find a workaround using SVG text, but I can't seem to get the text boxes to show up. I've tried putting the group that contains the tooltip box and text both before and after the pie slice paths, but it doesn't work either way.

When I go the inspector, I can see that the group with the tooltip is being created and shows up in the backend, but I can't see them on the rendered page. Can anyone point me in the right direction? I think it might have something to do with the transform for the group, but I've tried different settings and it doesn't fix it. I'm not sure what I'm doing wrong at this point. I created a CodePen with what I have so far at: https://codepen.io/tho1379/pen/MWjMKQV

  • 1
    I think the text is far too big. Check your co-ordinate system and font-size. – Robert Longson Jan 24 '21 at 17:21
  • @RobertLongson I tried changing the font size, but it did not make the text boxes appear, unfortunately. When I tried adjusting the viewbox, the pie chart disappeared and I did see part of the text boxes, but no matter how I adjust the transform, the boxes get cut off. Also, I still can't get both pie chart and text boxes to show up. So, it has to be a layering thing, but I'm stumped as to how to fix it. :( – user15071802 Jan 24 '21 at 18:12
  • your viewBox is tiny, your transform for the tooltip is huge i.e. 200 times the viewBox size. – Robert Longson Jan 24 '21 at 18:13
  • @RobertLongson I think I'm misunderstanding how the transform works. I changed the viewbox size to 0 0 1000 1000 and the pie chart has now shrunk to the size of a dot. And I can now see my text boxes (they all seem to be layered on top of each other), but I don't understand how they're 200 times the size of the chart? I thought the transform>translate was to push the text box off to the side? – user15071802 Jan 24 '21 at 18:41
  • @RobertLongson I think I got it! Because the viewbox is set to 2, a normal size for text is magnified way out of proportion. So, two new questions: 1) Why can't I make the viewbox bigger without losing my chart altogether (as mentioned in my previous comment, when I try to make the viewbox 1000x1000, the chart gets so small I can't even see it)? 2) If you look at the CodePen again, the yellow text box now shows up for all the slices except "vanilla" -- why is that happening? – user15071802 Jan 24 '21 at 20:02
  • 1) Because that's what a viewBox does. See https://stackoverflow.com/questions/15335926/how-to-use-the-svg-viewbox-attribute/15336348#15336348 – Robert Longson Jan 24 '21 at 20:13

1 Answers1

1

The viewBox attribute defines the position and dimension, in user space, of an SVG viewport. In the case of viewBox="-1 -1 2 2" the width of the view port is 2 user units and the height is also 2. The graphic begins at x="-1" and y="-1"

Meanwhile your text has font-size: .9rem (probably 14.4 units)

To fix this problem I separated the text in a different group. I've puted the piePaths in a symbol with a viewBox="0 0 2 2", Since I don't want a symbol with negative coordinates I am trabslating the piePaths transform="translate(1,1)"
Next I'm using the symbol: <use xlink:href="#pie" width="200" height="200"/> This will make the pie bigger (200/200)

Now you can see the text but it's all overlapped. I'll leave it to you to translate each tool tip where you need it to be.

As an observation: it's pointless to use z-index in svg. In order to put a shape on top you draw that shape at the end of the document

.myPie {
  width: 90%;
  margin: 2rem auto;
}

/*
svg {
  width: 100%;
}
*/

/* testing
.piePath {
  visibility: hidden;
}
*/

.piePath .tooltip {
  /*z-index: 1000;
  visibility: hidden;*/
}


path {
  opacity: 0.6;
}


.piePath:hover .tooltip {
 visibility: visible;
}

.piePath:hover path {
  opacity: 1;
  cursor: pointer;
}

.tooltip text {
    fill: black;
    font-size: 0.9rem;
    font-family: sans-serif;
}
.tooltip rect {
    fill: Cornsilk;
    stroke: Gray;
}
<div class="myPie">
  <svg viewBox="0 0 200 200" style="transform: rotate(-90deg)">
    <symbol id="pie" viewBox="0 0 2 2">
      <g transform="translate(1,1)">
    <g class="piePath">
      <path d="M 1 0 A 1 1 0 0 1 0.4600650377311522 0.8878852184023752 L 0 0" fill="MediumPurple" id="1"></path>
      
    </g>
    <g class="piePath">
      <path d="M 0.4600650377311522 0.8878852184023752 A 1 1 0 0 1 -0.7757112907044198 -0.6310879443260528 L 0 0" fill="PaleVioletRed" id="2"></path>
      
    </g>
    <g class="piePath">
      <path d="M -0.7757112907044198 -0.6310879443260528 A 1 1 0 0 1 -0.5766803221148672 -0.816969893010442 L 0 0" fill="MediumSeaGreen" id="3"></path>

    </g>
    <g class="piePath">
      <path d="M -0.5766803221148672 -0.816969893010442 A 1 1 0 0 1 -0.06824241336467135 -0.9976687691905392 L 0 0" fill="SteelBlue" id="4"></path>
     
    </g>
    <g class="piePath">
      <path d="M -0.06824241336467135 -0.9976687691905392 A 1 1 0 0 1 1 -2.4492935982947064e-16 L 0 0" fill="Coral" id="5"></path>
      
    </g>
    </g>
    </symbol>
    
   <use xlink:href="#pie" width="200" height="200"/>
    
    <g id="text">
      <g class="tooltip" transform="translate(30,30) rotate(90)" opacity="0.9">
        <rect rx="5" width="100" height="25"></rect><text x="5" y="15">Vanilla</text>
      </g>
      <g class="tooltip" transform="translate(30,30) rotate(90)" opacity="0.9">
        <rect rx="5" width="100" height="25"></rect><text x="5" y="15">Chocolate</text>
      </g>
       <g class="tooltip" transform="translate(30,30) rotate(90)" opacity="0.9">
        <rect rx="5" width="100" height="25"></rect><text x="5" y="15">Pistachio</text>
      </g>
       <g class="tooltip" transform="translate(30,30) rotate(90)" opacity="0.9">
        <rect rx="5" width="100" height="25"></rect><text x="5" y="15">Strawberry</text>
      </g>
      <g class="tooltip" transform="translate(30,30) rotate(90)" opacity="0.9">
        <rect rx="5" width="100" height="25"></rect><text x="5" y="15">Maple Walnut</text>
      </g>
      
    </g>
  </svg>
</div>
enxaneta
  • 31,608
  • 5
  • 29
  • 42