欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

前端学习】AntV G6-09 复杂定制的侧面、侧面动画

最编程 2024-10-19 07:15:48
...

课程视频

AntV G6:复杂的自定义边、边动画(上)_哔哩哔哩_bilibili

AntV G6:复杂的自定义边、边动画(下)_哔哩哔哩_bilibili

讲义截图

提及链接

https://codesandbox.io/p/sandbox/register-polyline-getpath-jkd6dn

G6

实例讲解

(从第一个课程链接的04:10开始)

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>07 复杂的自定义边、边动画</title>
    <!-- 引入 G6 -->
    <script src="https://gw.alipayobjects.com/os/lib/antv/g6/4.3.11/dist/g6.min.js"></script>
    <!-- <script src="https://gw.alipayobjects.com/os/lib/antv/g6/3.7.1/dist/g6.min.js"></script> -->
</head>

<body>
    <div id="container"></div>
    <script>
        const { getLabelPosition, transform } = G6.Util;

        const addAnimateArrow = (path, group, arrowStyle) => {
            const arrow =
                group.find((ele) => ele.get("name") === "animate-arrow") ||
                group.addShape("marker", {
                    attrs: {
                        stroke: "#3370ff",
                        fill: "#fff",
                        ...arrowStyle,
                        x: 16,
                        y: 0,
                        r: 8,
                        lineWidth: 2,
                        symbol: (x, y, r) => {
                            return [
                                ["M", x - 8, y - 8],
                                ["L", x - 2, y],
                                ["L", x - 8, y + 8]
                            ];
                        }
                    },
                    name: "animate-arrow"
                });

            arrow.stopAnimate();

            // animation for the red circle
            arrow.animate(
                (ratio) => {
                    // the operations in each frame. Ratio ranges from 0 to 1 indicating the prograss of the animation. Returns the modified configurations
                    // get the position on the edge according to the ratio
                    const tmpPoint = path.getPoint(ratio);
                    const roundPoint = {
                        x: Math.round(tmpPoint.x),
                        y: Math.round(tmpPoint.y)
                    };
                    const pos = getLabelPosition(path, ratio);
                    let matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1];
                    matrix = transform(matrix, [
                        ["t", -roundPoint.x, -roundPoint.y],
                        ["r", pos.angle],
                        ["t", roundPoint.x, roundPoint.y]
                    ]);

                    // returns the modified configurations here, x and y here
                    return {
                        x: tmpPoint.x,
                        y: tmpPoint.y,
                        matrix
                    };
                },
                {
                    repeat: true, // Whether executes the animation repeatly
                    duration: 3000 // the duration for executing once
                }
            );
        };

        const lineDashAnimate = (path) => {
            const lineDash = [6, 4, 2, 4];
            path.stopAnimate();
            let index = 0;
            // Define the animation
            path.animate(
                () => {
                    index++;
                    if (index > 9) {
                        index = 0;
                    }
                    const res = {
                        lineDash,
                        lineDashOffset: -index
                    };
                    // returns the modified configurations here, lineDash and lineDashOffset here
                    return res;
                },
                {
                    repeat: true, // whether executes the animation repeatly
                    duration: 3000 // the duration for executing once
                }
            );
        };

        G6.registerEdge(
            "line-arrow",
            {
                getPath(points) {
                    const startPoint = points[0];
                    const endPoint = points[1];
                    return [
                        ["M", startPoint.x, startPoint.y],
                        ["L", endPoint.x / 3 + (2 / 3) * startPoint.x, startPoint.y],
                        ["L", endPoint.x / 3 + (2 / 3) * startPoint.x, endPoint.y],
                        ["L", endPoint.x, endPoint.y]
                    ];
                },
                afterDraw(cfg, group) {
                    const keyShape = group.find((ele) => ele.get("name") === "edge-shape");
                    const attrs = keyShape.attr();
                    const halo = group.addShape("path", {
                        attrs: {
                            ...attrs,
                            lineWidth: 8,
                            opacity: 0.2
                        },
                        name: "edge-halo"
                    });
                    halo.hide();

                    const { endLabel, endPoint, labelCfg } = cfg;
                    const { style: labelStyle = {}, refX = 0, refY = 0 } = labelCfg;
                    if (endLabel) {
                        const endLabelShape = group.addShape("text", {
                            attrs: {
                                text: endLabel,
                                x: endPoint.x - refX,
                                y: endPoint.y + refY,
                                textAlign: "right",
                                fill: "#000",
                                textBaseline: "middle",
                                ...labelStyle
                            },
                            name: "end-label-shape"
                        });
                        console.log("endLabelShape", endLabelShape);
                    }
                },
                afterUpdate(cfg, item) {
                    const group = item.getContainer();
                    const endLabelShape = group.find(
                        (ele) => ele.get("name") === "end-label-shape"
                    );
                    const { endLabel, endPoint, labelCfg } = cfg;
                    const { style: labelStyle = {}, refX = 0, refY = 0 } = labelCfg;
                    endLabelShape.attr({
                        text: endLabel,
                        x: endPoint.x - refX,
                        y: endPoint.y + refY,
                        ...labelStyle
                    });
                },
                setState(name, value, item) {
                    const group = item.getContainer();
                    const keyShapePath = group.find(
                        (ele) => ele.get("name") === "edge-shape"
                    );
                    switch (name) {
                        case "hover":
                            const halo = group.find((ele) => ele.get("name") === "edge-halo");
                            if (value) {
                                const path = keyShapePath.attr("path");
                                halo.show();
                                halo.attr("path", path);
                            } else {
                                halo.hide();
                            }
                            break;
                        case "selected":
                            if (value) {
                                lineDashAnimate(keyShapePath);
                                // addAnimateArrow(keyShapePath, group, keyShapePath.attr());
                            } else {
                                keyShapePath.stopAnimate();
                                keyShapePath.attr("lineDash", undefined);
                                // const arrow = group.find(ele => ele.get('name') === 'animate-arrow');
                                // if (arrow) arrow.remove(true);
                            }
                            break;
                        default:
                            break;
                    }
                }
            },
            "polyline"
        );

        const data = {
            nodes: [
                {
                    id: "7",
                    x: 150,
                    y: 100
                },
                {
                    id: "8",
                    x: 300,
                    y: 200
                }
            ],
            edges: [
                {
                    source: "7",
                    target: "8",
                    label: "xxx",
                    endLabel: "yyy"
                }
            ]
        };

        const container = document.getElementById("container");
        const width = container.scrollWidth;
        const height = container.scrollHeight || 500;
        const graph = new G6.Graph({
            container: "container",
            width,
            height,
            // translate the graph to align the canvas's center, support by v3.5.1
            fitCenter: true,
            modes: {
                // behavior
                default: ["drag-node", "drag-canvas", "click-select"]
            },
            defaultNode: {
                type: "circle",
                size: 40,
                anchorPoints: [
                    [0, 0.5],
                    [1, 0.5]
                ],
                style: {
                    fill: "#DEE9FF",
                    stroke: "#5B8FF9"
                },
                linkPoints: {
                    left: true,
                    right: true,
                    fill: "#fff",
                    stroke: "#1890FF",
                    size: 5
                }
            },
            defaultEdge: {
                type: "line-arrow",
                color: "#F6BD16",
                labelCfg: {
                    autoRotate: true,
                    position: "start",
                    refX: 10
                }
            }
        });

        graph.data(data);
        graph.render();

        graph.on("edge:mouseenter", (e) => {
            graph.setItemState(e.item, "hover", true);
        });
        graph.on("edge:mouseleave", (e) => {
            graph.setItemState(e.item, "hover", false);
        });

        const clearEdgeStates = () => {
            const selectedEdges = graph.findAllByState("selected");
            selectedEdges?.forEach((edge) => graph.setItemState(edge, "selected", false));
        };
        graph.on("node:click", (e) => {
            clearEdgeStates();
            const relatedEdges = e.item.getEdges();
            relatedEdges.forEach((edge) => graph.setItemState(edge, "selected", true));
        });
        graph.on("canvas:click", (e) => clearEdgeStates());

        if (typeof window !== "undefined")
            window.onresize = () => {
                if (!graph || graph.get("destroyed")) return;
                if (!container || !container.scrollWidth || !container.scrollHeight) return;
                graph.changeSize(container.scrollWidth, container.scrollHeight);
            };
    </script>
</body>

</html>