Forum Discussion

cogsie's avatar
cogsie
Helper I
6 years ago
Solved

Overlapping Tick Marks on X-Axis

I am creating a custom visual and hvaing difficulty with the tick mark values on the x-azis.  If I shrink the visual size the labels start overlapping and looking jumbled (see picture below).  Is the...
  • cogsie's avatar
    6 years ago

    In case anyone runs into the same problem, this is how I solved the issue.

     

    I put the creation of the X axis inside a do/while loop.  The loop begins with creating the axis then loops through each text element and gets the width of the text.  The width is added to an array from which the largest width is determined and multiplied by the total number of ticks to get an estimate of how much space all the labels would need.  This is then compared to the plot width and if it is greater (i.e. the labels require more room than is available in the plot area and are overlapping) the whole loop is rerun (and the axis recreated) with one fewer ticks until there is no overlapping.  Generally it only needs to run 5 or fewer times, but I put in an iteration counter and added it to the while condition to avoid an infinite loop.

     

    I am pasting the code below in case it is helpful.  It needs to be cleaned up considerably (I have a lot of console logs to help with debugging), but here it is for what it's worth.

     

    If any one has a more efficient way I would love to hear it.

     

    do {
    
      var xAxis = d3.axisBottom(xScale)
        .tickFormat((d) => valueFormatter.format(d))
        .ticks(tickMarks);
    
        this.xAxisContainer
          .attr("class", "xAxis")
          .attr("transform", "translate(" + plotArea.x + "," + (plotArea.height + plotArea.y) + ")")
          .call(xAxis)
          .style("font-size", viewModel.XAxisFontSize)
          .style("font-family", viewModel.FontFamily)
    
    
          console.log("******************")
          console.log("iteration" + m)
          console.log("View Port Width:" + options.viewport.width)
          var gCounter = 0
          var g = 0
          var gArray = []
          var labelWidth = 0
          var gMax = 0
          d3.select(".xAxis").selectAll("text")
            .each(function (d,i) {
              console.log("starting")
              let textProperties: TextProperties = {
                text: valueFormatter.format(d),
                fontFamily: viewModel.FontFamily,
                fontSize: "" + viewModel.XAxisFontSize
              }
                            
              let h = textMeasurementService.measureSvgTextRect(textProperties).width
              gCounter++
              g = h + g
              gArray.push(h)
              gMax = d3.max(gArray)
              labelWidth = ((gCounter - .5) * gMax)
                            
              console.log("----------------------")
              console.log("Font Family: " + textProperties.fontFamily)
              console.log("Font Size: " + textProperties.fontSize)
              console.log("width of " + textProperties.text + ":" + h)
              console.log("Counter:" + gCounter)
              console.log("g:" + g)
              console.log("gArray: " + gArray)
              console.log("gMax: " + gMax)
              console.log("Label Width:" + labelWidth)
              console.log("Plot Width: " + plotArea.width)
             
              return(labelWidth)
            });
    
                
                    
            --tickMarks  
            console.log("TickMarks:" + tickMarks)
            ++m
            console.log("Plot Width: " + plotArea.width)
            console.log("Label Width:" + labelWidth)
            console.log("Test: ", plotArea.width < labelWidth)
                    
          } while (m<100 && plotArea.width < labelWidth)