uber / react-vis

Data Visualization Components
https://uber.github.io/react-vis
MIT License
8.73k stars 835 forks source link

Animated Sunburst can not take SVG Pattern #1015

Open martin-luo opened 6 years ago

martin-luo commented 6 years ago

Hi all

Similar to this #721 , when I tried to applied the SVG pattern to the Sunburst, it shows the black box like the following: image

However, when I remove animation from Sunburst, it works perfectly! image

Just wondering if this is caused by the animated Sunburst? I think I met a similar issue for the animated bar chart as well.

Wattenberger commented 6 years ago

Interesting! I'm curious what your code looks like - it looks okay to me (testing on Chrome + Firefox) when editing the Animated Sunburst example:

image

martin-luo commented 6 years ago

Here is the snippet of my code:

<Sunburst
    animation
    hideRootNode
    className={`${SUNBURST_CLASS}${extraContainerClass}`}
    colorType="literal"
    data={data}
    height={height}
    width={width}
    margin={{ top: 50, bottom: 50, left: 50, right: 50 }}
    getSize={d => d.size}
    getColor={d => {
        const showPattern: boolean = !this.__showSVGPattern(d.depth);
        if (showPattern) {
            return `url(#${this.__getSVGPatternID(showPattern, d.color)})`;
        }
        return d.color;
    }}
    padAngle={() => 0.02}
    onValueMouseOver={v => this.setState({ hoveredCell: v })}
    onValueMouseOut={v => this.setState({ hoveredCell: null })}
>
    {this.__renderHint()}
</Sunburst>

Version: 1.11.3

Wattenberger commented 6 years ago

Hm, I won't be able to debug your code without knowing what data or the svg pattern look like. I have no trouble with this attempt to recreate your chart:

        <svg height={0} width={0}>
          <GradientDefs>
              <pattern id="circles" width="3" height="3" patternUnits="userSpaceOnUse">
                <circle cx="1.5" cy="1.5" r="0.8" fill="magenta" />
              </pattern>
          </GradientDefs>
        </svg>
        <Sunburst
          animation
          hideRootNode
          height={300}
          width={350}
          colorType="literal"
          getColor={d => `url(#circles)`}
          data={data}
          margin={{ top: 50, bottom: 50, left: 50, right: 50 }}
      />

image

It might be worth looking into the Sunburst code and how an animated value might change it: https://github.com/uber/react-vis/blob/05cc2b374f983de3b9736a1c9cca422991c2a683/src/sunburst/index.js#L176-L184

martin-luo commented 6 years ago

Hi Wattengerger

Please try with this:

[
  {
    "category": "Name",
    "title": "Dummy A",
    "children": [
      {
        "color": "#52BAAB",
        "category": "PhysicalLocation",
        "title": "A",
        "children": [
          {
            "color": "#5287AC",
            "category": "Category",
            "title": "Level B",
            "size": 1,
            "seniorityLevel": 2
          }
        ]
      }
    ],
    "color": "#6269AF"
  },
  {
    "category": "Name",
    "title": "Dummy B",
    "children": [
      {
        "color": "#52BAAB",
        "category": "PhysicalLocation",
        "title": "A",
        "children": [
          {
            "color": "#5287AC",
            "category": "Category",
            "title": "Level B",
            "size": 2,
            "seniorityLevel": 2
          }
        ]
      }
    ],
    "color": "#69ACDF"
  },
  {
    "category": "Name",
    "title": "Dummy C",
    "children": [
      {
        "color": "#A763A5",
        "category": "PhysicalLocation",
        "title": "Asia Pacific",
        "children": [
          {
            "color": "#5287AC",
            "category": "Category",
            "title": "Level B",
            "size": 1,
            "seniorityLevel": 2
          }
        ]
      }
    ],
    "color": "#67C0B5"
  },
  {
    "category": "Name",
    "title": "Dummy D",
    "children": [
      {
        "color": "#52BAAB",
        "category": "PhysicalLocation",
        "title": "A",
        "children": [
          {
            "color": "#9AC2E9",
            "category": "Category",
            "title": "Level A",
            "size": 2,
            "seniorityLevel": 1
          }
        ]
      },
      {
        "color": "#85C9F0",
        "category": "PhysicalLocation",
        "title": "New South Wales",
        "children": [
          {
            "color": "#50968D",
            "category": "Category",
            "title": "Level C",
            "size": 1,
            "seniorityLevel": 3
          }
        ]
      }
    ],
    "color": "#B26DAB"
  },
  {
    "category": "Name",
    "title": "Dummy E",
    "children": [
      {
        "color": "#52BAAB",
        "category": "PhysicalLocation",
        "title": "A",
        "children": [
          {
            "color": "#9AC2E9",
            "category": "Category",
            "title": "Level A",
            "size": 12,
            "seniorityLevel": 1
          }
        ]
      },
      {
        "color": "#85C9F0",
        "category": "PhysicalLocation",
        "title": "New South Wales",
        "children": [
          {
            "color": "#50968D",
            "category": "Category",
            "title": "Level C",
            "size": 1,
            "seniorityLevel": 3
          }
        ]
      },
      {
        "color": "#ACCE6C",
        "category": "PhysicalLocation",
        "title": "Victoria",
        "children": [
          {
            "color": "#9AC2E9",
            "category": "Category",
            "title": "Level A",
            "size": 2,
            "seniorityLevel": 1
          }
        ]
      },
      {
        "color": "#FECE44",
        "category": "PhysicalLocation",
        "title": "Western Australia",
        "children": [
          {
            "color": "#9AC2E9",
            "category": "Category",
            "title": "Level A",
            "size": 3,
            "seniorityLevel": 1
          }
        ]
      }
    ],
    "color": "#9CD2F3"
  },
  {
    "category": "Name",
    "title": "Dummy F",
    "children": [
      {
        "color": "#52BAAB",
        "category": "PhysicalLocation",
        "title": "A",
        "children": [
          {
            "color": "#5287AC",
            "category": "Category",
            "title": "Level B",
            "size": 4,
            "seniorityLevel": 2
          }
        ]
      },
      {
        "color": "#A763A5",
        "category": "PhysicalLocation",
        "title": "Asia Pacific",
        "children": [
          {
            "color": "#50968D",
            "category": "Category",
            "title": "Level C",
            "size": 3,
            "seniorityLevel": 3
          }
        ]
      },
      {
        "color": "#85C9F0",
        "category": "PhysicalLocation",
        "title": "New South Wales",
        "children": [
          {
            "color": "#50968D",
            "category": "Category",
            "title": "Level C",
            "size": 4,
            "seniorityLevel": 3
          }
        ]
      },
      {
        "color": "#ACCE6C",
        "category": "PhysicalLocation",
        "title": "Victoria",
        "children": [
          {
            "color": "#5287AC",
            "category": "Category",
            "title": "Level B",
            "size": 1,
            "seniorityLevel": 2
          },
          {
            "color": "#50968D",
            "category": "Category",
            "title": "Level C",
            "size": 1,
            "seniorityLevel": 3
          }
        ]
      },
      {
        "color": "#FECE44",
        "category": "PhysicalLocation",
        "title": "Western Australia",
        "children": [
          {
            "color": "#50968D",
            "category": "Category",
            "title": "Level C",
            "size": 1,
            "seniorityLevel": 3
          }
        ]
      },
      {
        "color": "#4E5389",
        "category": "PhysicalLocation",
        "title": "Queensland",
        "children": [
          {
            "color": "#50968D",
            "category": "Category",
            "title": "Level C",
            "size": 14,
            "seniorityLevel": 3
          }
        ]
      }
    ],
    "color": "#BED572"
  },
  {
    "category": "Name",
    "title": "Dummy G",
    "children": [
      {
        "color": "#85C9F0",
        "category": "PhysicalLocation",
        "title": "New South Wales",
        "children": [
          {
            "color": "#50968D",
            "category": "Category",
            "title": "Level C",
            "size": 1,
            "seniorityLevel": 3
          }
        ]
      }
    ],
    "color": "#E7A2C8"
  },
  {
    "category": "Name",
    "title": "Dummy H",
    "children": [
      {
        "color": "#52BAAB",
        "category": "PhysicalLocation",
        "title": "A",
        "children": [
          {
            "color": "#50968D",
            "category": "Category",
            "title": "Level C",
            "size": 22,
            "seniorityLevel": 3
          }
        ]
      },
      {
        "color": "#85C9F0",
        "category": "PhysicalLocation",
        "title": "New South Wales",
        "children": [
          {
            "color": "#50968D",
            "category": "Category",
            "title": "Level C",
            "size": 1,
            "seniorityLevel": 3
          }
        ]
      },
      {
        "color": "#8D8EC5",
        "category": "PhysicalLocation",
        "title": "Australian Capital Territory",
        "children": [
          {
            "color": "#50968D",
            "category": "Category",
            "title": "Level C",
            "size": 3,
            "seniorityLevel": 3
          }
        ]
      }
    ],
    "color": "#F0848A"
  },
  {
    "category": "Name",
    "title": "Dummy I",
    "children": [
      {
        "color": "#85C9F0",
        "category": "PhysicalLocation",
        "title": "New South Wales",
        "children": [
          {
            "color": "#9AC2E9",
            "category": "Category",
            "title": "Level A",
            "size": 1,
            "seniorityLevel": 1
          }
        ]
      }
    ],
    "color": "#FFDF6E"
  },
  {
    "category": "Name",
    "title": "Dummy J",
    "children": [
      {
        "color": "#ACCE6C",
        "category": "PhysicalLocation",
        "title": "Victoria",
        "children": [
          {
            "color": "#9AC2E9",
            "category": "Category",
            "title": "Level A",
            "size": 1,
            "seniorityLevel": 1
          }
        ]
      }
    ],
    "color": "#4E55A1"
  }
]

It works when I update the data, but when I click the page, it turns to black.

Cheers

Wattenberger commented 6 years ago

Let's do it this way - I approximated your setup in this pen. If you can replicate your issue, I'd be happy to look into it more

martin-luo commented 6 years ago

Thanks Wattengerger! That's a quite good point. I modified the code to try to replicate the problem, but it looks well for me now. I'll dig into it tomorrow and let you know the results!

martin-luo commented 6 years ago

I think I found out the reason why it does not work with animation: instead of get d.color in getColor in Sunburst, I add some logics in to find out the Id of the SVG pattern.

The function of SVG pattern generation looks like this:

 private __getSVGPatternID = (
    showPattern: boolean,
    legendColor: string = "#ffffff"
  ): string => (showPattern ? `sunburst-legend-${legendColor}` : "");

It work well on static Sunburst because the value we get from d.color is a hex code, for example, #52BAAB. However, in animated Sunburst, the color we get changed to RGB which is rgb(82, 186, 171).

My pattern ID generation function did not recognize the changes and keep treating the color as hex code, and the SVG with that ID does not exist, that is why the second ring in the animated sunburst turns to black.

Hopefully this helps.

Regards

martin-luo commented 6 years ago

I think I found out the reason why it does not work with animation: instead of get d.color in getColor in Sunburst, I add some logics in to find out the Id of the SVG pattern.

The function of SVG pattern generation looks like this:

 private __getSVGPatternID = (
    showPattern: boolean,
    legendColor: string = "#ffffff"
  ): string => (showPattern ? `sunburst-legend-${legendColor}` : "");

It work well on static Sunburst because the value we get from d.color is a hex code, for example, #52BAAB. However, in animated Sunburst, the color we get changed to RGB which is rgb(82, 186, 171).

My pattern ID generation function did not recognize the changes and keep treating the color as hex code, and the SVG with that ID does not exist, that is why the second ring in the animated sunburst turns to black.

Hopefully this helps.

Regards

After updating my id generation logic. the animation works well!

  private __getSVGPatternID = (
    showPattern: boolean,
    legendColor: string = "#ffffff"
  ): string => {
    if (!showPattern) {
      return "";
    }
    let hexColor: string = legendColor;
    const isHex: boolean =
      hexColor.length > 1 &&
      hexColor.slice(1).length === 6 &&
      !isNaN(parseInt(hexColor.slice(1), 16));

    if (!isHex) {
      hexColor = hexColor
        .split("(")[1]
        .split(")")[0]
        .split(",")
        .map(color => {
          const hex = parseInt(color).toString(16);
          return hex.length === 1 ? "0" + hex : hex;
        })
        .join("");
      hexColor = `#${hexColor.toUpperCase()}`;
    }

    return `sunburst-legend-${hexColor}`;
  };

image

Just a suggestion, should we make it more clear in the documentation that when use animation, the color representation changed?

Kind Regards

References: