title: How to create scaleThreshold legend in D3 v5?
body: <p>I am following this tutorial about how to create legends, in particular I need the scaleThreshold:</p>
  <p><a href="https://observablehq.com/@d3/color-legend" rel="nofollow noreferrer">how to create legends</a></p>
  <p>I understand that I can't use import because it works only in Observable's cell, so I have to copy the entire function and code is like that:</p>
  <pre><code>legend({
    color: d3.scaleThreshold([2.5, 3.1, 3.5, 3.9, 6, 7, 8, 9.5], d3.schemeRdBu[9]),
    title: &quot;Unemployment rate (%)&quot;,
    tickSize: 0
  })
  
  function legend({
    color,
    title,
    tickSize = 6,
    width = 320, 
    height = 44 + tickSize,
    marginTop = 18,
    marginRight = 0,
    marginBottom = 16 + tickSize,
    marginLeft = 0,
    ticks = width / 64,
    tickFormat,
    tickValues
  } = {}) {
  
    const svg = d3.create(&quot;svg&quot;)
        .attr(&quot;width&quot;, width)
        .attr(&quot;height&quot;, height)
        .attr(&quot;viewBox&quot;, [0, 0, width, height])
        .style(&quot;overflow&quot;, &quot;visible&quot;)
        .style(&quot;display&quot;, &quot;block&quot;);
  
    let tickAdjust = g =&gt; g.selectAll(&quot;.tick line&quot;).attr(&quot;y1&quot;, marginTop + marginBottom - height);
    let x;
  
    // Continuous
    if (color.interpolate) {
      const n = Math.min(color.domain().length, color.range().length);
  
      x = color.copy().rangeRound(d3.quantize(d3.interpolate(marginLeft, width - marginRight), n));
  
      svg.append(&quot;image&quot;)
          .attr(&quot;x&quot;, marginLeft)
          .attr(&quot;y&quot;, marginTop)
          .attr(&quot;width&quot;, width - marginLeft - marginRight)
          .attr(&quot;height&quot;, height - marginTop - marginBottom)
          .attr(&quot;preserveAspectRatio&quot;, &quot;none&quot;)
          .attr(&quot;xlink:href&quot;, ramp(color.copy().domain(d3.quantize(d3.interpolate(0, 1), n))).toDataURL());
    }
  
    // Sequential
    else if (color.interpolator) {
      x = Object.assign(color.copy()
          .interpolator(d3.interpolateRound(marginLeft, width - marginRight)),
          {range() { return [marginLeft, width - marginRight]; }});
  
      svg.append(&quot;image&quot;)
          .attr(&quot;x&quot;, marginLeft)
          .attr(&quot;y&quot;, marginTop)
          .attr(&quot;width&quot;, width - marginLeft - marginRight)
          .attr(&quot;height&quot;, height - marginTop - marginBottom)
          .attr(&quot;preserveAspectRatio&quot;, &quot;none&quot;)
          .attr(&quot;xlink:href&quot;, ramp(color.interpolator()).toDataURL());
  
      // scaleSequentialQuantile doesn’t implement ticks or tickFormat.
      if (!x.ticks) {
        if (tickValues === undefined) {
          const n = Math.round(ticks + 1);
          tickValues = d3.range(n).map(i =&gt; d3.quantile(color.domain(), i / (n - 1)));
        }
        if (typeof tickFormat !== &quot;function&quot;) {
          tickFormat = d3.format(tickFormat === undefined ? &quot;,f&quot; : tickFormat);
        }
      }
    }
  
    // Threshold
    else if (color.invertExtent) {
      const thresholds
          = color.thresholds ? color.thresholds() // scaleQuantize
          : color.quantiles ? color.quantiles() // scaleQuantile
          : color.domain(); // scaleThreshold
  
      const thresholdFormat
          = tickFormat === undefined ? d =&gt; d
          : typeof tickFormat === &quot;string&quot; ? d3.format(tickFormat)
          : tickFormat;
  
      x = d3.scaleLinear()
          .domain([-1, color.range().length - 1])
          .rangeRound([marginLeft, width - marginRight]);
  
      svg.append(&quot;g&quot;)
        .selectAll(&quot;rect&quot;)
        .data(color.range())
        .join(&quot;rect&quot;)
          .attr(&quot;x&quot;, (d, i) =&gt; x(i - 1))
          .attr(&quot;y&quot;, marginTop)
          .attr(&quot;width&quot;, (d, i) =&gt; x(i) - x(i - 1))
          .attr(&quot;height&quot;, height - marginTop - marginBottom)
          .attr(&quot;fill&quot;, d =&gt; d);
  
      tickValues = d3.range(thresholds.length);
      tickFormat = i =&gt; thresholdFormat(thresholds[i], i);
    }
  
    // Ordinal
    else {
      x = d3.scaleBand()
          .domain(color.domain())
          .rangeRound([marginLeft, width - marginRight]);
  
      svg.append(&quot;g&quot;)
        .selectAll(&quot;rect&quot;)
        .data(color.domain())
        .join(&quot;rect&quot;)
          .attr(&quot;x&quot;, x)
          .attr(&quot;y&quot;, marginTop)
          .attr(&quot;width&quot;, Math.max(0, x.bandwidth() - 1))
          .attr(&quot;height&quot;, height - marginTop - marginBottom)
          .attr(&quot;fill&quot;, color);
  
      tickAdjust = () =&gt; {};
    }
  
    svg.append(&quot;g&quot;)
        .attr(&quot;transform&quot;, `translate(0,${height - marginBottom})`)
        .call(d3.axisBottom(x)
          .ticks(ticks, typeof tickFormat === &quot;string&quot; ? tickFormat : undefined)
          .tickFormat(typeof tickFormat === &quot;function&quot; ? tickFormat : undefined)
          .tickSize(tickSize)
          .tickValues(tickValues))
        .call(tickAdjust)
        .call(g =&gt; g.select(&quot;.domain&quot;).remove())
        .call(g =&gt; g.append(&quot;text&quot;)
          .attr(&quot;x&quot;, marginLeft)
          .attr(&quot;y&quot;, marginTop + marginBottom - height - 6)
          .attr(&quot;fill&quot;, &quot;currentColor&quot;)
          .attr(&quot;text-anchor&quot;, &quot;start&quot;)
          .attr(&quot;font-weight&quot;, &quot;bold&quot;)
          .text(title));
  
    return svg.node();
  }
  
  function ramp(color, n = 256) {
    const canvas = DOM.canvas(n, 1);
    const context = canvas.getContext(&quot;2d&quot;);
    for (let i = 0; i &lt; n; ++i) {
      context.fillStyle = color(i / (n - 1));
      context.fillRect(i, 0, 1, 1);
    }
    return canvas;
  }
  </code></pre>
  <p>But I am getting nothing neither errors.</p>