reactjstypescriptamchartsword-cloudamcharts5

How to set a background dynamically based on dataItem?


Here is my code for WordCloud Chart and i need to give a background based on frequency check with threshold. Same as text fill color i want to give a background dynamically but not able to get the dataItem as always get the undefined in dataItem so comparison is not applying.

import React, { useEffect, useRef } from "react";
import * as am5 from "@amcharts/amcharts5";
import * as am5wc from "@amcharts/amcharts5/wc";
import am5themes_Animated from "@amcharts/amcharts5/themes/Animated";

interface DataPoint {
    name: string;
    frequency: number;
}

interface WordChartProps {
    data: DataPoint[];
}

const WordChart: React.FC<WordChartProps> = ({ data = [] }) => {
    const chartRef = useRef<HTMLDivElement>(null);
    const dataSet = [
        { name: "Pricing", frequency: 100 },
        { name: "Availability", frequency: 50 },
        { name: "Online", frequency: 20 },
        { name: "Process", frequency: 10 },
        { name: "Work", frequency: 30 },
        { name: "Pricing", frequency: 100 },
        { name: "Availability", frequency: 50 },
        { name: "Online", frequency: 20 },
        { name: "Process", frequency: 10 },
        { name: "Work", frequency: 30 },
        { name: "Pricing", frequency: 100 },
        { name: "Availability", frequency: 50 },
        { name: "Online", frequency: 20 },
        { name: "Process", frequency: 10 },
        { name: "Work", frequency: 30 },
        { name: "Pricing", frequency: 100 },
        { name: "Availability", frequency: 50 },
        { name: "Online", frequency: 20 },
        { name: "Process", frequency: 10 },
        { name: "Work", frequency: 30 },
    ]
    dataSet.sort((a, b) => b.frequency - a.frequency);
    const groupSize = Math.ceil(dataSet.length / 3);
    const highThreshold = dataSet[groupSize - 1]?.frequency || 0; // Lowest frequency in "high"
    const mediumThreshold = dataSet[groupSize * 2 - 1]?.frequency || 0; // Lowest frequency in "medium"

    useEffect(() => {
        if (!chartRef.current) return;
        const root = am5.Root.new(chartRef.current);
        root.setThemes([am5themes_Animated.new(root)]);
        const series = root.container.children.push(
            am5wc.WordCloud.new(root, {
                maxFontSize: am5.percent(12),
                minFontSize: am5.percent(5),
                categoryField: "name",
                valueField: "frequency",
                rotation: 0,
                centerX: am5.percent(0),
                centerY: am5.percent(0),
                angles: [0],
            })
        );

        series.labels.template.setAll({
            paddingTop: 10,
            paddingBottom: 10,
            paddingLeft: 10,
            paddingRight: 10,
            fontFamily: "Roboto",
            fontSize: "14px",
            fontStyle: "normal",
            fontWeight: "400",
            textAlign: "center",
            tooltipText: "{category}: {value}"
        });

        // Dynamically setting the `fill` color for each label
        series.labels.template.adapters.add("fill", (fill, target) => {
            const dataItem = target.dataItem; // Access the associated data item
            const frequency: any = dataItem?.get("value"); // Retrieve the frequency field from data
            if (frequency >= highThreshold) {
                return am5.color(0x52a3ff);
            } else if (frequency >= mediumThreshold) {
                return am5.color(0x7fb5f2);
            } else {
                return am5.color(0x5e93c2);
            }
        });

        series.labels.template.setup = function (label) {
            let backgroundColor;
            let borderColor;
            const dataItem = label.dataItem;
            console.log("dataItem Background", dataItem);
            const frequency = dataItem?.get("frequency");
            console.log("background frequency", frequency)

            if (frequency >= highThreshold) {
                backgroundColor = am5.color(0X52A3FF);
            } else if (frequency >= mediumThreshold) {
                backgroundColor = am5.color(0xF4F5F8);
            } else {
                // backgroundColor = am5.color(0xffffff);
                backgroundColor = am5.color(0X52A3FF);
            }

            backgroundColor = am5.color(0xffffff);
            borderColor = am5.color(0x52a3ff);

            label.set(
                "background",
                am5.RoundedRectangle.new(root, {
                    cornerRadiusBL: 10,
                    cornerRadiusBR: 10,
                    cornerRadiusTL: 10,
                    cornerRadiusTR: 10,
                    fill: backgroundColor,
                    fillOpacity: 1,
                    stroke: borderColor,
                    strokeWidth: 1,
                    marginTop: 15,
                    marginBottom: 15,
                    marginLeft: 15,
                    marginRight: 15,
                })
            );
        };

        series.data.setAll(dataSet);
        return () => {
            root.dispose();
        };
    }, []);

    return <div ref={chartRef} style={{ width: "100%", height: "300px" }} />;
};

export default WordChart;

Here i'm not getting the dataItem:

 series.labels.template.setup = function (label) {
                let backgroundColor;
                let borderColor;
                const dataItem = label.dataItem;
                console.log("dataItem Background", dataItem);
                const frequency = dataItem?.get("frequency");
                console.log("background frequency", frequency)

Thank you in advance for the help!


Solution

  • Now i'm able to change the backgroundcolor and borderColor accroding to dataItem based on threshold. Here is the code fo

    series.labels.template.setup = function (label) {
                let backgroundColor = am5.color(0xffffff);
                let borderColor = am5.color(0x52a3ff);
    
                label.set(
                    "background",
                    am5.RoundedRectangle.new(root, {
                        cornerRadiusBL: 20,
                        cornerRadiusBR: 20,
                        cornerRadiusTL: 20,
                        cornerRadiusTR: 20,
                        marginTop: 15,
                        marginBottom: 15,
                        marginLeft: 15,
                        marginRight: 15,
                    })
                );
    
                label.events.on("dataitemchanged", function (ev) {
                    var label = ev.target;
                    const frequency = label.dataItem?.dataContext?.frequency; // Retrieve the frequency field from data
                    if (frequency >= highThreshold) {
                        backgroundColor = am5.color(0x52A3FF);
                        borderColor = am5.color(0xFFFFFF)
                    } else if (frequency >= mediumThreshold) {
                        backgroundColor = am5.color(0xDBECFF);
                        borderColor = am5.color(0xFFFFFF)
                    } else {
                        backgroundColor = am5.color(0xFFFFFF);
                        borderColor = am5.color(0x7FB5F2)
                    }
    
                    label.set(
                        "background",
                        am5.RoundedRectangle.new(root, {
                            fill: backgroundColor,
                            fillOpacity: 1,
                            stroke: borderColor,
                            strokeWidth: 1,
                        })
                    );
                });
            };