javascriptd3.js

How to show multicolor on slider using d3-simple-slider.js


I am using d3-simple slider and want to show multicolor on slider i.e. enter image description here

From Range 0-9 it should be blue and 9 to 26 is orange and for range 26-60 color should be red and If I move handle which is currently pointing to 26 then slide it towards left then red color should follow it ,similarly for otehr handle too.Can someone please help in regarding this?

 const rangeSvg = d3.select('figure#rangeContainer')
      .append('svg')
      .attr('width', 350) 
      .attr('height', height);

    const segmentWidth = 90; 

    // Create the first slider
    const rangeSlider = rangeSvg.append('g')
      .attr('transform', 'translate(10,30)'); // Position the first slider

    // Call your slider function to draw the first slider
    rangeSlider.call(sliderHorizontal()

      .min(1)
      .max(60)
      .step(1)
      .default([6,36])
      .tickValues([1, 6, 36, 60])
      .width(segmentWidth * 3)
      .handle(d3.symbol().type(d3.symbolCircle).size(100)())
      .fill('orange') // Apply the gradient here
      .on('onchange', selectedPeriod => {
       let fileAgingPeriod = selectedPeriod.map(Math.round);
        this.activeValue = fileAgingPeriod[0];
        this.obsoleteValue = tfileAgingPeriod[1];
        this.cdr.detectChanges(); 
      })
    );

    rangeSlider.select('.track-inset')
      .attr('stroke', '#54A7FF');
    //  .attr('stroke-dasharray',230);

    rangeSlider.selectAll('.handle')
      .attr('fill', '#54A7FF');

Solution

  • Here's a little d3/SVG trickery. It clones the slider's "inset" to break them into two pieces, one before the selection, colored blue, and one after, colored red. The two insets then dynamically resize as you move the slider.

    <script src="https://d3js.org/d3.v7.js"></script>
    <script src="https://unpkg.com/d3-simple-slider"></script>
    
    <p id="value"></p>
    <div id="slider"></div>
    
    <script>
      const min = 1,
        max = 60;
    
      // function to dynamically resize
      setInsetLens = (selection) => {
        d3.select('#before-inset')
        .attr('x2', (selection[0] / (min + max)) * initialWidth);
        d3.select('#after-inset')
        .attr('x1', (selection[1] / (min + max)) * initialWidth);
      };
    
      var slider = d3
        .sliderHorizontal()
        .min(min)
        .max(max)
        .step(1)
        .default([6, 36])
        .tickValues([1, 6, 36, 60])
        .width(90 * 3)
        .handle(d3.symbol().type(d3.symbolCircle).size(100)())
        .fill('orange')
        .on('onchange', setInsetLens);
    
      d3.select('#slider')
        .append('svg')
        .attr('width', 500)
        .attr('height', 100)
        .append('g')
        .attr('transform', 'translate(30,30)')
        .call(slider);
    
      // clone the inset, set the colors and get its initial width
      const initialWidth = d3.select('.track-inset')
        .attr('id', 'before-inset')
        .attr('stroke', 'steelblue')
        .clone()
        .attr('id', 'after-inset')
        .attr('stroke', 'red')
        .node()
        .getBBox()
        .width;
    
      // set initial size
      setInsetLens([6,36]);
    
    </script>