【示例】Vue AntV G6 base64自定义img 动画效果,自适应宽高屏

需求:拓扑图中需要用动画的线条连接node,在此之前将HTML页面改成了vue页面。需要使用到G6的registerEdge 自定义边,小车的图片需要转成base64格式(并翻转),可以通过base64转image查看原来的样子。

另外,通过动态控制div的scale自适应拉伸尺寸的计算来达到自适应宽高屏幕的效果。

【完整代码】

<template>
    <div class="body-wrap" ref="contentWrapper">
        <div class="graph-wrap">
            <div ref="graphContainer"></div>
        </div>
    </div>
</template>

<script>
import G6 from '@antv/g6';
const { getLabelPosition, transform } = G6.Util;

export default {
    name: 'CustomEdgeGraph',
    data() {
        return {
            designWidth: 1920, // 设计稿宽度
            designHeight: 1080, // 设计稿高度
            currentScale: [1, 1],
            nodeData: {
                // 点集
                nodes: [
                    {
                        id: 'point1',
                        x: 110,
                        y: 200,
                    },
                    {
                        id: 'point2',
                        x: 110,
                        y: 200,
                    },
                    {
                        id: 'point3',
                        x: 130,
                        y: 630,
                    },
                    {
                        id: 'point4',
                        x: 130,
                        y: 630,
                    },
                    {
                        id: 'center',
                        x: 500,
                        y: 400,
                    },
                    {
                        id: 'oil_star',
                        x: 1600,
                        y: 1030,
                    },
                    {
                        id: 'oil_end',
                        x: 100,
                        y: 780,
                    },
                    {
                        id: 'car_star',
                        x: 1600,
                        y: 990,
                    },
                    {
                        id: 'car_end',
                        x: 100,
                        y: 750,
                    },

                ],
                // 边集
                edges: [
                    {
                        source: 'point1',
                        target: 'center',
                        curveOffset: -180,
                    },
                    {
                        source: 'point2',
                        target: 'center',
                        curveOffset: 160,
                    },
                    {
                        source: 'point3',
                        target: 'center',
                        curveOffset: -120,
                    },
                    {
                        source: 'point4',
                        target: 'center',
                        curveOffset: 90,
                    },

                    // 动画线
                    {
                        source: 'point1',
                        target: 'center',
                        curveOffset: -180,
                        type: 'line-growth',
                        style: {
                            lineAppendWidth: 5,
                            lineWidth: 5, // 线宽
                            stroke: 'l(0) 0:rgba(34,255,242,0.06) 0.25:rgba(34,255,242,0.5) 0.5:rgba(34,255,242,1) 0.75:rgba(34,255,242,0.5)  1:rgba(34,255,242,0.06)', // 线的颜色
                        }
                    },
                    {
                        source: 'point2',
                        target: 'center',
                        curveOffset: 160,
                        type: 'line-growth',
                        style: {
                            lineAppendWidth: 5,
                            lineWidth: 5, // 线宽
                            stroke: 'l(0) 0:rgba(34,255,242,0.06) 0.25:rgba(34,255,242,0.5) 0.5:rgba(34,255,242,1) 0.75:rgba(34,255,242,0.5)  1:rgba(34,255,242,0.06)', // 线的颜色
                        }
                    },
                    {
                        source: 'point3',
                        target: 'center',
                        curveOffset: -120,
                        type: 'line-growth',
                        style: {
                            lineAppendWidth: 5,
                            lineWidth: 5, // 线宽
                            stroke: 'l(0) 0:rgba(34,255,242,0.06) 0.25:rgba(34,255,242,0.5) 0.5:rgba(34,255,242,1) 0.75:rgba(34,255,242,0.5)  1:rgba(34,255,242,0.06)', // 线的颜色
                        }
                    },
                    {
                        source: 'point4',
                        target: 'center',
                        curveOffset: 90,
                        type: 'line-growth',
                        style: {
                            lineAppendWidth: 5,
                            lineWidth: 5, // 线宽
                            stroke: 'l(0) 0:rgba(34,255,242,0.06) 0.25:rgba(34,255,242,0.5) 0.5:rgba(34,255,242,1) 0.75:rgba(34,255,242,0.5)  1:rgba(34,255,242,0.06)', // 线的颜色
                        }
                    },
                    {
                        source: 'oil_star',
                        target: 'oil_end',
                        type: 'arrow-running',
                        style: {
                            lineAppendWidth: 10,
                            lineWidth: 10, // 线宽
                            stroke: 'l(0) 0:rgba(188,133,26,0.16) 0.95:rgba(188,133,26,0.16)  1:rgba(188,133,26,0)', // 线的颜色
                            // 
                        },
                        // assign the control points to control the bending positions
                        // 开车线路的中间拐点
                        controlPoints: [
                            {
                                x: 600,
                                y: 1030,
                            },
                        ],
                    },
                    {
                        source: 'car_star',
                        target: 'car_end',
                        type: 'car-running',
                        style: {
                            lineAppendWidth: 10,
                            lineWidth: 10, // 线宽
                            //stroke:'red'
                            stroke: 'rgba(255,255,255,0)', // 线的颜色
                            // 
                        },
                        // assign the control points to control the bending positions
                        // 开车的中间拐点
                        controlPoints: [
                            {
                                x: 600,
                                y: 990,
                            },
                        ],
                    },

                ]
            }
        }
    },
    beforeDestroy() {
        window.removeEventListener('resize', this.onWindowResize);
    },
    mounted() {
        this.initGraph();
        this.updateScale();
        window.addEventListener('resize', this.updateScale);

    },
    methods: {
        // 自适应拉伸尺寸计算
        updateScale() {
            const { designWidth, designHeight } = this;
            const windowWidth = window.innerWidth;
            const windowHeight = window.innerHeight;

            // 计算宽高比
            const widthRatio = (windowWidth / designWidth).toFixed(4) - 0.002;
            const heightRatio = (windowHeight / designHeight).toFixed(4) - 0.002;
            const scale = [widthRatio, heightRatio];

            // 更新缩放比例
            this.currentScale = scale;
            this.applyTransform();
        },
        applyTransform() {
            const contentWrapper = this.$refs.contentWrapper;
            if (contentWrapper) {
                contentWrapper.style.transform = `scale(${this.currentScale[0]},${this.currentScale[1]})`;
                contentWrapper.style.transformOrigin = 'top left';
            }
        },
        // 自适应拉伸尺寸计算 END

        // 初始化图表
        initGraph() {
            const car1 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAeCAYAAACv1gdQAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyVpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDYuMC1jMDAyIDc5LjE2NDQ4OCwgMjAyMC8wNy8xMC0yMjowNjo1MyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIyLjAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NUI3OUE0N0NCNjBDMTFFRjhGQUE5RDc0QzcwRDE1NkQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NUI3OUE0N0RCNjBDMTFFRjhGQUE5RDc0QzcwRDE1NkQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1Qjc5QTQ3QUI2MEMxMUVGOEZBQTlENzRDNzBEMTU2RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1Qjc5QTQ3QkI2MEMxMUVGOEZBQTlENzRDNzBEMTU2RCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pnqu6cUAAAp9SURBVHjapFhp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'
            const cube = 'data:image/png;base64,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'
            
            // 自定义边类型
            G6.registerEdge(
                'line-growth',
                {
                    afterDraw(cfg, group) {
                        const shape = group.get('children')[0];
                        const length = shape.getTotalLength();
                        shape.animate(
                            (ratio) => {
                                // the operations in each frame. Ratio ranges from 0 to 1 indicating the prograss of the animation. Returns the modified configurations
                                const startLen = ratio * length;
                                // Calculate the lineDash
                                const cfg = {
                                    lineDash: [startLen, length - startLen],
                                };
                                return cfg;
                            },
                            {
                                repeat: true, // Whether executes the animation repeatly
                                duration: 2000, // the duration for executing once
                            },
                        );
                    },
                },
                'arc', // extend the built-in edge 'cubic' arc 
            );
            G6.registerEdge(
                "arrow-running",
                {
                    afterDraw(cfg, group) {
                        // get the first shape in the group, it is the edge's path here=
                        const shape = group.get("children")[0];
                        const length = shape.getTotalLength();
                        let circleCount = Math.ceil(length / 100);

                        circleCount = circleCount === 0 ? 1 : circleCount;

                        const _loop = function _loop(i) {
                            const delay = 0;
                            const start = shape.getPoint(0);
                            const image = group.addShape("image", {
                                attrs: {
                                    x: start.x,
                                    y: start.y - 9,
                                    width: 14,
                                    height: 14,
                                    img: cube,
                                }
                            });

                            // animation for the red circle
                            image.animate(
                                (ratio) => {
                                    ratio += i / circleCount;
                                    if (ratio > 1) {
                                        ratio %= 1;
                                    }
                                    const tmpPoint = shape.getPoint(ratio);
                                    const pos = getLabelPosition(shape, ratio);
                                    let matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1];
                                    matrix = transform(matrix, [
                                        ["t", -tmpPoint.x - 9, -tmpPoint.y],
                                        ["r", pos.angle],
                                        ["t", tmpPoint.x, tmpPoint.y]
                                    ]);

                                    // returns the modified configurations here, x and y here
                                    return {
                                        x: tmpPoint.x,
                                        y: tmpPoint.y - 9,
                                        matrix
                                    };
                                },
                                {
                                    repeat: true, // Whether executes the animation repeatly
                                    // duration: 3000 // the duration for executing once
                                    duration: 8 * length,
                                    easing: 'easeLinear',
                                    // delay:5 * length,
                                }
                            );
                        }
                        for (let i = 0; i < circleCount; i++) {
                            _loop(i);
                        }
                    }
                },
                "polyline" // extend the built-in edge 'cubic'
            );
            G6.registerEdge(
                "car-running",
                {
                    afterDraw(cfg, group) {
                        // get the first shape in the group, it is the edge's path here=
                        const shape = group.get("children")[0];
                        const image = group.addShape("image", {
                            attrs: {
                                x: 0,
                                y: 0,
                                width: 73,
                                height: 41,
                                img: car1,
                            }
                        });
                        // animation for the red circle
                        image.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 = shape.getPoint(ratio);
                                const pos = getLabelPosition(shape, ratio);
                                let matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1];
                                // var op =1
                                if (tmpPoint.x > 1653) {
                                    matrix = transform(matrix, [
                                        ["t", -tmpPoint.x - 50, -tmpPoint.y],
                                        ["r", pos.angle],
                                        ["t", tmpPoint.x, tmpPoint.y]
                                    ]);
                                } else {
                                    matrix = transform(matrix, [
                                        ["t", -tmpPoint.x, -tmpPoint.y + 10],
                                        ["r", pos.angle],
                                        ["t", tmpPoint.x, tmpPoint.y]
                                    ]);
                                }
                                var op = 1
                                // 当车跑到某点时变成不透明 0.5
                                // if (tmpPoint.x > 1483) {
                                //     op = 1
                                // } else {
                                //     op = 0.5
                                // }
                                // returns the modified configurations here, x and y here
                                return {
                                    x: tmpPoint.x,
                                    y: tmpPoint.y - 36,
                                    matrix,
                                    opacity: op
                                };
                            },
                            {
                                repeat: true, // Whether executes the animation repeatly
                                duration: 9000 // the duration for executing once
                            }
                        );
                    }
                },
                "polyline" // extend the built-in edge 'cubic'
            );
            this.$nextTick(() => {
                // 初始化图表
                const graph = new G6.Graph({
                    container: this.$refs.graphContainer,
                    width: 1920,
                    height: 1080,
                    modes: {
                        default: ['drag-node', 'zoom-canvas', 'click-select']
                    },
                    defaultNode: { // 节点样式修改
                        type: 'circle', // 设置节点为图片
                        size: [0, 0], // 节点大小
                        anchorPoints: [
                            [0.5, 0.5],
                            [0.5, 0.5],
                        ],
                    },
                    defaultEdge: { // 边通用配置
                        type: 'arc',
                        labelCfg: {
                            autoRotate: true,
                        },
                        style: {
                            lineAppendWidth: 3,
                            lineWidth: 3, // 线宽
                            stroke: 'rgba(9,237,224,0.3)', // 线的颜色
                        },
                    },
                });

                // 设置初始数据
                graph.data(this.nodeData);

                // 渲染图表
                graph.render();

                if (typeof window !== 'undefined')
                    window.onresize = () => {
                        if (!graph || graph.get('destroyed')) return;
                    };
            })
        }
    }
};
</script>

<style lang="less" scoped>
.body-wrap {
    overflow: hidden;
    width: 1920px;
    height: 1080px;
    background: #040d27;
    background-size: cover;
    transform-origin: 0 0;
}

.graph-wrap {
    width: 1920px;
    height: 1080px;
    background: none;
}
</style>

【小车原图示例】

【工具网站】

base64图片在线转换工具 - 站长工具

G6

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/941369.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL的分析查询语句

【图书推荐】《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;》-CSDN博客 《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;&#xff08;数据库技术丛书&#xff09;》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) MySQL9数据库技术_夏天又到了…

【递归,搜索与回溯算法 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)

优美的排列 题目解析 算法原理 解法 &#xff1a;暴搜 决策树 红色剪枝&#xff1a;用于剪去该节点的值在对应分支中&#xff0c;已经被使用的情况&#xff0c;可以定义一个 check[ ] 紫色剪枝&#xff1a;perm[i] 不能够被 i 整除&#xff0c;i 不能够被 per…

观察者模式(sigslot in C++)

大家&#xff0c;我是东风&#xff0c;今天抽点时间整理一下我很久前关注的一个不错的库&#xff0c;可以支持我们在使用标准C的时候使用信号槽机制进行观察者模式设计&#xff0c;sigslot 官网&#xff1a; http://sigslot.sourceforge.net/ 本文较为详尽探讨了一种观察者模…

GitCode 光引计划投稿|智能制造一体化低代码平台 Skyeye云

随着智能制造行业的快速发展&#xff0c;企业对全面、高效的管理解决方案的需求日益迫切。然而&#xff0c;传统的开发模式往往依赖于特定的硬件平台&#xff0c;且开发过程繁琐、成本高。为了打破这一瓶颈&#xff0c;Skyeye云应运而生&#xff0c;它采用先进的低代码开发模式…

高校就业管理:系统设计与实现的全流程分析

3.1可行性分析 在项目进行开发之前&#xff0c;必须要有可行性分析报告&#xff0c;分别从技术角度&#xff0c;经济角度&#xff0c;操作角度上面进行分析&#xff0c;经过可行性分析是实现科学开发的必要步骤。 3.1.1技术可行性 从技术的角度出发&#xff0c;目前采用开发的技…

超级AI图像放大工具Upscayl:让你的照片细节更清晰,色彩更鲜艳!

前言 Hello大家好&#xff0c;我又来推荐非常好用的AI图片无损放大器,模糊图片秒变高清&#xff0c;Upscayl是一个免费开源的AI图像超分辨率工具。它使用AI模型来通过猜测细节的方式增强图像并提高其分辨率。该工具适用于Linux、macOS和Windows操作系统 安装环境 [名称]&…

1.gitlab 服务器搭建流程

前提条件&#xff1a; 一、服务器硬件水平 搭建gitlab服务器最低配置要求2核4G,低于这个配置的服务器运行效果很差。 gitlab官网&#xff1a;https://about.gitlab.com/ 下载地址&#xff1a;gitlab/gitlab-ce - Packages packages.gitlab.com 本机ubuntu 二、安装依赖 su…

Ai编程从零开始全栈开发一个后台管理系统之用户登录、权限控制、用户管理-前端部分(十二)

云风网 云风笔记 云风知识库 一、创建前端部分 1、vite初始化项目 npm create vitelatest admin-frontend – --template vue-ts 2、安装必要的依赖 npm install vue-router pinia axios element-plus element-plus/icons-vue安装完成后package.json如下&#xff1a; {&qu…

CVE-2024-34351 漏洞复现

CVE-2024-34351&#xff0c;由Next.js异步函数createRedirectRenderResult导致的SSRF。 影响版本&#xff1a;13.4.0< Next.js < 14.1.1 参考文章&#xff1a; Next.js Server-Side Request Forgery in Server Actions CVE-2024-34351 GitHub Advisory Database Gi…

怎么理解GKE Role-Based Access Control (RBAC) 和 Pod Security Policies (PSP)

怎么理解GKE Role-Based Access Control (RBAC) 和 Pod Security Policies (PSP) 理解 Google Kubernetes Engine (GKE) 中的角色基于访问控制&#xff08;RBAC&#xff09;和 Pod 安全策略&#xff08;PSP&#xff09;对于确保集群安全性至关重要。以下是对这两个概念的详细解…

什么是 DevOps 自动化?

DevOps 自动化是一种现代软件开发方法&#xff0c;它使用工具和流程来自动化任务并简化工作流程。它将开发人员、IT 运营和安全团队聚集在一起&#xff0c;帮助他们有效协作并交付可靠的软件。借助 DevOps 自动化&#xff0c;组织能够处理重复性任务、优化流程并更快地将应用程…

帝国CMS:如何去掉帝国CMS登录界面的认证码登录

如果在安装的时候&#xff0c;不小心选中了认证码选项&#xff0c;那么后面登录帝国后台都会要求输入认证码才能登录&#xff0c;如何去除这个设置呢&#xff0c;笔者以古诗词网 www.gushichi.com为例&#xff0c;为大家举例说明&#xff01; 去除步骤如下&#xff1a; 1.前往…

4.2V单节锂电池充电电路(TP4056)、USB与锂电池切换电路分享

一、充电原理图 1、连接说明 BAT_VCC和BAT_GND连接电池 VUSB和GND连接USB电源 2、芯片介绍 a、DW01 DW01芯片是一种电池管理保护芯片&#xff0c;主要用于锂离子电池的保护和管理。DW01芯片具有以下特点&#xff1a; 电池电压保护&#xff1a;DW01芯片可以监测和保护电池的…

ChatGPT生成接口文档实践案例(二)

不难发现&#xff0c;两个方案都出色地完成了接口文档的生成&#xff0c;但笔者更喜欢Response 2的表达&#xff0c;因为其描述更加全面。 还可以让ChatGPT生成符合OpenAPI 3.0规范的接口文档&#xff0c;以便于项目相关成员阅读&#xff0c;如图5-13所示。 为什么要生成OpenAP…

MFC用List Control 和Picture控件实现界面切换效果

添加List Control 和Picture控件 添加 3个子窗体 把子窗体边框设置为None, 样式设为Child 声明 CListCtrl m_listPageForm;void ShowForm(int nIndex);void CreatFormList();void CMFCApplication3Dlg::DoDataExchange(CDataExchange* pDX) {CDialogEx::DoDataExchange(pDX);DD…

JavaWeb Servlet的反射优化、Dispatcher优化、视图(重定向)优化、方法参数值获取优化

目录 1. 背景2. 实现2.1 pom.xml2.2 FruitController.java2.3 DispatcherServlet.java2.4 applicationContext.xml 3. 测试 1. 背景 前面我们做了Servlet的一个案例。但是存在很多问题&#xff0c;现在我们要做优化&#xff0c;优化的步骤如下&#xff1a; 每个Fruit请求都需…

frp内网穿透云服务器。云服务器映射多个家庭局域网内网端口。家庭Windows主机内网运行多个web程序

这篇文章最终要实现的效果是&#xff0c;把云服务器的公网IP绑定到自己本地局域网上的主机一样的效果。相当于局域网主机有了一个自己的公网IP地址。 FRP (Fast Reverse Proxy) 是一个用 Go 语言编写的高性能反向代理应用程序&#xff0c;主要用于内网穿透。它允许位于 NAT 或…

windos 安装docker

文章目录 安装1.下载安装包2.双击安装软件 验证修改国内镜像地址FAQDocker Engine stopped 小结 安装 1.下载安装包 到官网下载适配的安装包&#xff1a;https://www.docker.com/products/docker-desktop/ 2.双击安装软件 选择ok 等待安装依赖 安装完成以后会重启电脑&am…

【已解决】黑马点评项目Redis版本替换过程中误删数据库后前端显示出现的问题

为了实现基于Redis的Stream结构作为消息队列&#xff0c;实现异步秒杀下单的功能&#xff0c;换Redis版本 Redis版本太旧了&#xff0c;所以从3.2.1换成了5.0.14 此时犯了一个大忌&#xff0c;因为新的Redis打开后&#xff0c;没有缓存&#xff0c;不知道出了什么问题&#xf…

Odoo 免费开源 ERP:通过 JavaScript 创建对话框窗口的技术实践分享

作者 | 老杨 出品 | 上海开源智造软件有限公司&#xff08;OSCG&#xff09; 概述 在本文中&#xff0c;我们将深入研讨如何于 Odoo 18 中构建 JavaScript&#xff08;JS&#xff09;对话框或弹出窗口。对话框乃是展现重要讯息、确认用户操作以及警示用户留意警告或错误的行…