Conditional rendering tickvalues in D3JS in Vue3

23 Views Asked by At

unfortunately I'm not able to find my mistake, so i'm asking you in the hope that someone can help me. What I want to have in the end is, that only every fifth bin is labeled, if the binNumber is higher than 30. I tried every inline condition I know, but non of this worked so far.

What I currently have is the following:

const binWidth = d3.max(testData, (d) => d.expressionValue) / (binNumber - 1);

      const bins = Array.from({ length: binNumber}, () => ({
        x0: 0,
        x1: 0,
        length: 0, // gets updated later on
      }));

      bins.forEach((bin, i) => {
        bin.x0 = (i === 0) ? 0 : bins[i - 1].x1;
        bin.x1 = bin.x0 + binWidth;
      });

      testData.forEach((d) => {
      for (let i = 0; i < binNumber; i++) {
        const bin = bins[i];
        if (d.expressionValue >= bin.x0 && d.expressionValue < bin.x1) {
          bin.length += 1;
          if(this.proteinId != null && d.proteinId == this.proteinId){
            binIndexOfInputProteinId = i; // bin at position i needs to be in a different color
          }
          break;
        }
      }
      });

       const x = d3.scaleLinear()
            .domain([0, d3.max(testData, (d) => d.expressionValue) + binWidth])
            .range([marginLeft, width - marginRight]);

      const y = d3.scaleLinear()
          .domain([0, d3.max(bins, (d) => d.length)])
          .range([height - marginBottom, marginTop + 15]);

      const svg = d3.select(this.$refs.barContainer)
          .append("svg")
          .attr("width", width)
          .attr("height", height)
          .attr("viewBox", [0, 0, width, height + 20])
          .attr("style", "max-width: 100%; height: auto;");

      const binMidpoints = bins.map((bin) => (bin.x0 + bin.x1) / 2);

      svg.append("g")   
        .selectAll()
        .data(bins)
        .join("rect")
          .attr("x", (d) => x(d.x0) + 1)
          .attr("width", (d) => x(d.x1) - x(d.x0) -1)
          .attr("y", (d) => y(Math.max(d.length, 0.05)))
          .attr("height", (d) => Math.max(y(0) - y(d.length), minRectHeight))
          .attr("fill", (d, i) => (i == binIndexOfInputProteinId && binIndexOfInputProteinId != null) ? "red" : "steelblue"); 

      svg.append("g")
          .attr("transform", `translate(0,${height - marginBottom})`)
          .call(d3.axisBottom(x)
              .tickValues([
                ...((this.binNumber < 10) ? binMidpoints : []),
                ...((this.binNumber <= 20) ? bins.map((bin, i) => (bin.x1)) : []),
                ...((this.binNumber > 30) ? bins.map((bin, i) => (i % 5 === 0 ? bin.x1 : null)) : [])
              ])
              .tickSizeOuter(0)
              .tickFormat((d) => d.toFixed(1)))
          .call((g) => g.append("text")
              .attr("x", width)
              .attr("y", marginBottom + 15)
              .attr("fill", "currentColor")
              .attr("text-anchor", "end")
              .text("Protein expression value →"))
          .selectAll("text")
          .attr("style", `font-size: 18px`);

      svg.append("g")
          .attr("transform", `translate(${marginLeft},0)`)
           .call(d3.axisLeft(y).ticks(10))
          .call((g) => g.append("text")
              .attr("x", marginLeft - 180)
              .attr("y", marginTop)
              .attr("fill", "currentColor")
              .attr("text-anchor", "start")
              .text("↑ Frequency of proteins with corresponding expression"))
              .selectAll("text")
              .attr("style", `font-size: 18px`);
      
      return svg.node();

The important part is the following:

.tickValues([
                ...((this.binNumber < 10) ? binMidpoints : []),
                ...((this.binNumber <= 30) ? bins.map((bin, i) => (bin.x1)) : []),
                ...((this.binNumber > 30) ? bins.map((bin, i) => (i % 5 === 0 ? bin.x1 : null)) : [])
              ])

The first two conditions work well. The problem is the last one. If I have found this out correctly, then this does not work because of the "null". However, I have also tried "undefined" and an empty string, but unfortunately that doesn't work either. In my histogram there are simply no more axes to be seen.

Then I tried a different inline condition, because I thought maybe I must not do anything in the else statement:

...((this.binNumber > 20) && bins.map((bin, i) => (i % 5 === 0 ? bin.x1)))

There the error occurs that the ":" is missing.

...((this.binNumber > 30) ? bins.map((bin, i) => (i % 5 === 0 ? bin.x1)) : [])

Didn"t worked as well.

Can you please help me how I can solve this? Thank you very much :D

0

There are 0 best solutions below