ooder-A2UI 框架中的矢量图形全面指南

SVG(可缩放矢量图形)是A2UI框架中用于创建高质量矢量图形的重要组件。本专辑将全面介绍SVGPaper组件的使用、SVG形状类型、连接线系统、样式配置以及实际应用案例。

📋 目录

  1. [SVGPaper 组件概述](#SVGPaper 组件概述 "#svgpaper-%E7%BB%84%E4%BB%B6%E6%A6%82%E8%BF%B0")
  2. 快速入门
  3. [SVG 形状类型大全](#SVG 形状类型大全 "#svg-%E5%BD%A2%E7%8A%B6%E7%B1%BB%E5%9E%8B%E5%A4%A7%E5%85%A8")
  4. 连接线系统
  5. 样式与渐变
  6. 实际应用案例
  7. [API 参考](#API 参考 "#api-%E5%8F%82%E8%80%83")
  8. 最佳实践
  9. 常见问题

SVGPaper 组件概述

SVGPaper 是 A2UI 框架中专门用于绘制和管理 SVG 矢量图形的组件。它继承自 Div 组件,提供了丰富的图形创建、编辑和交互功能。

核心特性

  • 矢量图形绘制:支持多种预定义形状和自定义路径
  • 流程图支持:专门的流程图形状和连接线系统
  • 交互支持:点击、悬停、拖拽等交互事件
  • 样式配置:丰富的描边、填充、渐变选项
  • 响应式设计:自动适应不同屏幕尺寸
  • 可访问性:ARIA 属性和键盘导航支持

技术架构

SVGPaper 基于以下技术构建:

  • Raphaël SVG 库:轻量级、跨浏览器的 SVG 库
  • A2UI 组件体系:标准的 UI 组件生命周期和事件系统
  • CSS 变量主题:支持主题切换和自定义样式

快速入门

1. 创建 SVG 画布

html 复制代码
<!-- 引入核心库和SVGPaper组件 -->
<script type="text/javascript" src="ood/ood.js"></script>
<script type="text/javascript" src="ood/UI/SVGPaper.js"></script>

<!-- 创建画布容器 -->
<div id="svg-container"></div>

<script>
// 创建 SVGPaper 实例
var svgPaper = ood.UI.SVGPaper({
    width: '800px',
    height: '600px',
    scaleChildren: false,
    overflow: undefined,
    graphicZIndex: 0
}).appendTo('#svg-container');

// 画布创建完成,可以开始添加图形
</script>

2. 添加基本形状

javascript 复制代码
// 添加圆形
svgPaper.append(
    ood.create("ood.svg.circle")
    .setHost(svgPaper, "circle1")
    .setSvgTag("Shapes:Circle")
    .setAttr({
        "KEY":{
            "cx": 100,
            "cy": 100,
            "r": 50,
            "fill": "#2196F3",
            "stroke": "#1976D2",
            "stroke-width": 3
        }
    })
);

// 添加矩形
svgPaper.append(
    ood.create("ood.svg.rect")
    .setHost(svgPaper, "rect1")
    .setSvgTag("Shapes:Rect")
    .setAttr({
        "KEY":{
            "x": 200,
            "y": 80,
            "width": 120,
            "height": 80,
            "fill": "90-#4CAF50-#C8E6C9",
            "stroke": "#388E3C",
            "stroke-width": 2
        }
    })
);

3. 添加文本和连接线

javascript 复制代码
// 添加文本
svgPaper.append(
    ood.create("ood.svg.text")
    .setHost(svgPaper, "text1")
    .setSvgTag("Shapes:Text")
    .setAttr({
        "KEY":{
            "x": 150,
            "y": 250,
            "text": "SVG 示例",
            "fill": "#333333",
            "font-size": "20px",
            "font-weight": "bold"
        }
    })
);

// 添加连接线
svgPaper.append(
    ood.create("ood.svg.connector")
    .setHost(svgPaper, "connector1")
    .setSvgTag("Connectors:Straight")
    .setAttr({
        "KEY":{
            "path": "M,100,150L,300,150",
            "fill": "none",
            "stroke": "#666666",
            "stroke-width": 2,
            "arrow-start": "classic-wide-long",
            "arrow-end": "classic-wide-long"
        },
        "BG":{
            "fill": "none",
            "stroke": "#FFFFFF",
            "stroke-width": 4
        }
    })
    .setFromObj("circle1")
    .setFromPoint("bottom")
    .setToObj("rect1")
    .setToPoint("left")
);

SVG 形状类型大全

基础形状

形状ID 名称 描述 关键属性
ood.svg.circle 圆形 标准圆形 cx, cy, r, fill, stroke
ood.svg.ellipse 椭圆 椭圆形 cx, cy, rx, ry
ood.svg.rect 矩形 矩形 x, y, width, height
ood.svg.line 直线 直线段 x1, y1, x2, y2
ood.svg.polygon 多边形 多边形 points
ood.svg.polyline 折线 折线 points

流程图专用形状

SVGPaper 提供了丰富的流程图形状,每个形状都有特定的用途:

流程控制形状

形状类型 用途 示例
FlowChart:Process 处理过程 服务器处理
FlowChart:Decision 决策判断 条件判断
FlowChart:Termination 终止点 流程结束

数据形状

形状类型 用途 示例
FlowChart:Data 数据 数据存储
FlowChart:Document 文档 报告文档
FlowChart:Database 数据库 数据库系统

输入输出形状

形状类型 用途 示例
FlowChart:ManualInput 手动输入 用户输入
FlowChart:Display 显示 结果展示

存储形状

形状类型 用途 示例
FlowChart:StoredData 存储数据 数据缓存
FlowChart:InternalStorage 内部存储 内存存储

组合形状

组合形状是A2UI中特殊的SVG元素,将图形和文本组合在一起:

ood.svg.rectComb

矩形组合形状,支持渐变填充和文本:

javascript 复制代码
ood.create("ood.svg.rectComb")
.setAttr({
    "KEY":{
        "x": 40,
        "y": 30,
        "width": 90,
        "height": 50,
        "fill": "90-#5198D3-#A1C8F6",
        "stroke": "#004A7F"
    },
    "TEXT":{
        "text": "服务器",
        "font-size": "12px",
        "fill": "#fff",
        "font-weight": "bold"
    }
})

ood.svg.pathComb

路径组合形状,用于复杂图形:

javascript 复制代码
ood.create("ood.svg.pathComb")
.setAttr({
    "KEY":{
        "fill": "90-#5198D3-#A1C8F6",
        "stroke": "#004A7F",
        "path": "M,319,85C,310.7157314383532,85,304,71.56854048887718,304,55C,304,38.43145548427702,310.7157178477474,25,319,25M,319,85C,319,85,319,85,319,85C,310.7157314383532,85,304,71.56854048887718,304,55C,304,38.43145548427702,310.7157178477474,25,319,25M,319,25C,327.2842655415122,25,334,38.43145548427702,334,55C,334,71.56854048887718,327.2842655415122,85,319,85C,319,85,259,85,259,85C,250.7157118074781,85,244,71.56854048887718,244,55C,244,38.43145548427702,250.7157118074781,25,259,25C,259,25,319,25,319,25"
    },
    "TEXT":{
        "text": "网关",
        "font-size": "12px",
        "fill": "#fff",
        "font-weight": "bold"
    }
})

ood.svg.circleComb

圆形组合形状:

javascript 复制代码
ood.create("ood.svg.circleComb")
.setAttr({
    "KEY":{
        "cx": 504,
        "cy": 55,
        "r": 40,
        "fill": "90-#5198D3-#A1C8F6",
        "stroke": "#004A7F"
    },
    "TEXT":{
        "text": "传感器",
        "font-size": "12px",
        "fill": "#fff",
        "font-weight": "bold"
    }
})

连接线系统

连接线是流程图和图表中连接不同元素的纽带。A2UI 提供了强大的连接线系统,支持自动路径计算和智能连接。

连接线类型

1. 直线连接线 (Connectors:Straight)

最简单的连接线类型,两点之间直接连接:

javascript 复制代码
ood.create("ood.svg.connector")
.setSvgTag("Connectors:Straight")
.setAttr({
    "KEY":{
        "path": "M,100,100L,300,200",
        "fill": "none",
        "stroke": "#228B22",
        "stroke-width": 2,
        "arrow-start": "oval-midium-midium",
        "arrow-end": "classic-wide-long"
    },
    "BG":{
        "fill": "none",
        "stroke": "#FFFFFF",
        "stroke-width": 4
    }
})
.setFromObj("shape1")
.setFromPoint("right")
.setToObj("shape2")
.setToPoint("left")

2. 贝塞尔曲线连接线 (Connectors:Bezier)

平滑的曲线连接,适合避免交叉的情况:

javascript 复制代码
ood.create("ood.svg.connector")
.setSvgTag("Connectors:Bezier")
.setAttr({
    "KEY":{
        "path": "M,100,100C,150,50,250,250,300,200",
        "fill": "none",
        "stroke": "#FF5722",
        "stroke-width": 2
    }
})

3. 流程图连接线 (Connectors:flowchart)

带拐角的连接线,典型的流程图风格:

javascript 复制代码
ood.create("ood.svg.connector")
.setSvgTag("Connectors:flowchart")
.setAttr({
    "KEY":{
        "path": "M,100,100L,200,100L,200,200L,300,200",
        "fill": "none",
        "stroke": "#673AB7",
        "stroke-width": 2
    }
})

连接点系统

连接线可以连接到形状的特定位置:

javascript 复制代码
// 连接到形状的不同位置
connector.setFromObj("serverRect")      // 起始形状
        .setFromPoint("right")          // 从右侧连接
        .setToObj("gatewayPath")        // 目标形状
        .setToPoint("left");            // 连接到左侧

支持的位置:

  • "left":左侧
  • "right":右侧
  • "top":顶部
  • "bottom":底部

箭头样式

连接线支持多种箭头样式:

javascript 复制代码
// 箭头配置示例
"arrow-start": "classic-wide-long"     // 起始箭头
"arrow-end": "oval-midium-midium"      // 结束箭头

箭头类型:

  1. classic :经典箭头
    • classic-narrow-short
    • classic-midium-midium
    • classic-wide-long
  2. oval :椭圆形箭头
    • oval-midium-midium
  3. diamond:菱形箭头
  4. triangle:三角形箭头

样式与渐变

基本样式属性

属性 类型 描述 示例
fill String 填充颜色或渐变 "#FF0000", "90-#FF0000-#0000FF"
stroke String 描边颜色 "#333333"
stroke-width Number 描边宽度 2
stroke-opacity Number 描边透明度 0.8
fill-opacity Number 填充透明度 0.5
opacity Number 整体透明度 0.9

渐变填充

A2UI 支持多种渐变类型:

1. 线性渐变

javascript 复制代码
"fill": "90-#5198D3-#A1C8F6"
  • 格式:"角度-起始颜色-结束颜色"
  • 角度:0-360,0°为从上到下,90°为从左到右

2. 径向渐变

javascript 复制代码
"fill": "r-#FF0000-#FFFFFF"
  • 格式:"r-起始颜色-结束颜色"

3. 多色渐变

javascript 复制代码
"fill": "90-#FF0000-#00FF00-#0000FF"
  • 支持多个颜色节点

样式应用示例

javascript 复制代码
// 渐变矩形
var gradientRect = ood.create("ood.svg.rectComb")
.setAttr({
    "KEY":{
        "x": 100,
        "y": 100,
        "width": 200,
        "height": 100,
        "fill": "45-#FF6B6B-#4ECDC4",  // 45°线性渐变
        "stroke": "#2D3436",
        "stroke-width": 3,
        "stroke-dasharray": "5,5",      // 虚线描边
        "rx": 10,                       // 圆角半径
        "ry": 10
    },
    "TEXT":{
        "text": "渐变样式示例",
        "font-size": "16px",
        "fill": "#FFFFFF",
        "font-weight": "bold",
        "text-anchor": "middle",
        "dy": "0.35em"                  // 垂直居中调整
    }
});

// 添加阴影效果
gradientRect.on("mouseover", function() {
    this.attr({
        "filter": "url(#shadow)"        // SVG滤镜阴影
    });
});

gradientRect.on("mouseout", function() {
    this.attr({
        "filter": "none"
    });
});

实际应用案例

案例1:物联网系统架构图

基于用户提供的示例,创建一个完整的物联网系统架构图:

javascript 复制代码
// 创建物联网系统架构图
function createIoTSystemDiagram(containerId) {
    var svgPaper = ood.UI.SVGPaper({
        width: '800px',
        height: '500px',
        scaleChildren: false
    }).appendTo(containerId);
    
    // 1. 云服务器
    svgPaper.append(
        ood.create("ood.svg.rectComb")
        .setHost(svgPaper, "cloudServer")
        .setSvgTag("FlowChart:Process")
        .setAttr({
            "KEY":{
                "x": 50,
                "y": 200,
                "width": 120,
                "height": 80,
                "fill": "90-#4285F4-#8AB4F8",
                "stroke": "#1A73E8"
            },
            "TEXT":{
                "text": "云服务器",
                "font-size": "14px",
                "fill": "#FFFFFF",
                "font-weight": "bold"
            }
        })
    );
    
    // 2. 网关设备
    svgPaper.append(
        ood.create("ood.svg.pathComb")
        .setHost(svgPaper, "gateway")
        .setSvgTag("FlowChart:DirectData")
        .setAttr({
            "KEY":{
                "fill": "90-#34A853-#81C995",
                "stroke": "#1E8E3E",
                "path": "M,250,200C,240,200,230,180,230,160C,230,140,240,120,250,120C,250,120,350,120,350,120C,358,120,360,140,360,160C,360,180,358,200,350,200C,350,200,250,200,250,200"
            },
            "TEXT":{
                "text": "智能网关",
                "font-size": "14px",
                "fill": "#FFFFFF",
                "font-weight": "bold"
            }
        })
    );
    
    // 3. 传感器节点
    svgPaper.append(
        ood.create("ood.svg.circleComb")
        .setHost(svgPaper, "sensor")
        .setSvgTag("FlowChart:OnPageRefrence")
        .setAttr({
            "KEY":{
                "cx": 550,
                "cy": 160,
                "r": 60,
                "fill": "r-#FBBC05-#FDE293",
                "stroke": "#F9AB00"
            },
            "TEXT":{
                "text": "温湿度传感器",
                "font-size": "12px",
                "fill": "#333333",
                "font-weight": "bold"
            }
        })
    );
    
    // 4. 连接线
    svgPaper.append(
        ood.create("ood.svg.connector")
        .setHost(svgPaper, "conn1")
        .setSvgTag("Connectors:Straight")
        .setAttr({
            "KEY":{
                "path": "M,170,240L,230,240",
                "fill": "none",
                "stroke": "#666666",
                "stroke-width": 2,
                "arrow-end": "classic-wide-long"
            }
        })
        .setFromObj("cloudServer")
        .setFromPoint("right")
        .setToObj("gateway")
        .setToPoint("left")
    );
    
    svgPaper.append(
        ood.create("ood.svg.connector")
        .setHost(svgPaper, "conn2")
        .setSvgTag("Connectors:Straight")
        .setAttr({
            "KEY":{
                "path": "M,350,240L,490,240",
                "fill": "none",
                "stroke": "#666666",
                "stroke-width": 2,
                "arrow-end": "classic-wide-long"
            }
        })
        .setFromObj("gateway")
        .setFromPoint("right")
        .setToObj("sensor")
        .setToPoint("left")
    );
    
    return svgPaper;
}

// 使用示例
var iotDiagram = createIoTSystemDiagram("#diagram-container");

案例2:业务流程管理图

javascript 复制代码
// 创建订单处理流程图
function createOrderProcessDiagram(containerId) {
    var svgPaper = ood.UI.SVGPaper({
        width: '1000px',
        height: '600px'
    }).appendTo(containerId);
    
    var shapes = [];
    
    // 订单接收
    shapes.push(svgPaper.append(
        ood.create("ood.svg.rectComb")
        .setHost(svgPaper, "orderReceive")
        .setSvgTag("FlowChart:Process")
        .setAttr({
            "KEY":{
                "x": 100,
                "y": 100,
                "width": 150,
                "height": 60,
                "fill": "90-#2196F3-#64B5F6",
                "stroke": "#1976D2"
            },
            "TEXT":{
                "text": "订单接收",
                "font-size": "14px",
                "fill": "#FFFFFF"
            }
        })
    ));
    
    // 库存检查(决策)
    shapes.push(svgPaper.append(
        ood.create("ood.svg.pathComb")
        .setHost(svgPaper, "inventoryCheck")
        .setSvgTag("FlowChart:Decision")
        .setAttr({
            "KEY":{
                "fill": "90-#FF9800-#FFB74D",
                "stroke": "#F57C00",
                "path": "M,300,100L,400,160L,300,220L,200,160Z"
            },
            "TEXT":{
                "text": "库存检查",
                "font-size": "12px",
                "fill": "#FFFFFF"
            }
        })
    ));
    
    // 更多流程节点...
    
    // 连接所有节点
    for (var i = 0; i < shapes.length - 1; i++) {
        svgPaper.append(
            ood.create("ood.svg.connector")
            .setSvgTag("Connectors:Straight")
            .setAttr({
                "KEY":{
                    "path": "M," + (shapes[i].getBBox().x + shapes[i].getBBox().width) + "," + (shapes[i].getBBox().y + shapes[i].getBBox().height/2) + 
                           "L," + (shapes[i+1].getBBox().x) + "," + (shapes[i+1].getBBox().y + shapes[i+1].getBBox().height/2),
                    "fill": "none",
                    "stroke": "#666666",
                    "stroke-width": 2,
                    "arrow-end": "classic-wide-long"
                }
            })
            .setFromObj(shapes[i].alias)
            .setFromPoint("right")
            .setToObj(shapes[i+1].alias)
            .setToPoint("left")
        );
    }
    
    return svgPaper;
}

案例3:组织结构图

javascript 复制代码
// 创建公司组织结构图
function createOrgChart(containerId, orgData) {
    var svgPaper = ood.UI.SVGPaper({
        width: '1200px',
        height: '800px'
    }).appendTo(containerId);
    
    // 按层级布局节点
    var levelPositions = {};
    
    // 遍历组织数据,创建节点
    orgData.forEach(function(dept, index) {
        var level = dept.level || 0;
        var position = levelPositions[level] || {x: 100, y: 100 + level * 150};
        
        var shape = ood.create("ood.svg.rectComb")
            .setHost(svgPaper, "dept_" + dept.id)
            .setSvgTag("FlowChart:Document")
            .setAttr({
                "KEY":{
                    "x": position.x,
                    "y": position.y,
                    "width": 180,
                    "height": 80,
                    "fill": getDeptColor(dept.type),
                    "stroke": "#333333",
                    "rx": 8,
                    "ry": 8
                },
                "TEXT":{
                    "text": dept.name + "\n" + (dept.manager || ""),
                    "font-size": "12px",
                    "fill": "#FFFFFF",
                    "text-anchor": "middle"
                }
            });
            
        svgPaper.append(shape);
        
        // 更新位置
        levelPositions[level] = {
            x: position.x + 220,
            y: position.y
        };
        
        // 连接到上级部门
        if (dept.parentId) {
            svgPaper.append(
                ood.create("ood.svg.connector")
                .setSvgTag("Connectors:Straight")
                .setAttr({
                    "KEY":{
                        "path": calculateOrgPath(dept.parentId, dept.id),
                        "fill": "none",
                        "stroke": "#999999",
                        "stroke-width": 2
                    }
                })
                .setFromObj("dept_" + dept.parentId)
                .setFromPoint("bottom")
                .setToObj("dept_" + dept.id)
                .setToPoint("top")
            );
        }
    });
    
    return svgPaper;
}

// 辅助函数
function getDeptColor(deptType) {
    var colors = {
        "executive": "90-#D32F2F-#F44336",
        "management": "90-#1976D2-#2196F3", 
        "technical": "90-#388E3C-#4CAF50",
        "support": "90-#F57C00-#FF9800"
    };
    return colors[deptType] || "90-#607D8B-#90A4AE";
}

原始示例代码深度分析

以下是您提供的原始物联网系统流程图代码的详细分析,展示了A2UI中SVG的核心用法:

代码结构解析

javascript 复制代码
// 1. 创建SVG画布并添加到FormLayout中
host.xui_ui_formlayout1.append(
    ood.create("ood.UI.SVGPaper")
    .setHost(host,"xui_ui_svgpaper7")
    .setLeft("0em")
    .setTop("0em")
    .setWidth("61.416666666666664em")
    .setHeight("9.333333333333334em"),
    "A1"
);

关键点:

  • ood.create("ood.UI.SVGPaper"):创建SVGPaper组件实例
  • .setHost(host,"xui_ui_svgpaper7"):设置宿主和唯一标识符
  • .setWidth()/.setHeight():使用em单位实现响应式设计
  • "A1":布局位置标识符

2. 创建流程图节点

javascript 复制代码
// 服务器节点(矩形)
host.xui_ui_svgpaper7.append(
    ood.create("ood.svg.rectComb")
    .setHost(host,"xui_svg_rectcomb1")
    .setSvgTag("FlowChart:Process")
    .setAttr({
        "KEY":{
            "x":40,
            "y":30,
            "width":90,
            "height":50,
            "fill":"90-#5198D3-#A1C8F6",
            "stroke":"#004A7F"
        },
        "TEXT":{
            "text":"服务器",
            "font-size":"12px",
            "fill":"#fff",
            "font-weight":"bold"
        }
    })
);

技术细节:

  • ood.svg.rectComb:矩形组合形状类
  • FlowChart:Process:流程图处理节点类型
  • 渐变填充:"90-#5198D3-#A1C8F6"(90°线性渐变)
  • 文本配置:白色粗体,12px大小

3. 创建网关节点(路径形状)

javascript 复制代码
host.xui_ui_svgpaper7.append(
    ood.create("ood.svg.pathComb")
    .setHost(host,"xui_svg_pathcomb49")
    .setSvgTag("FlowChart:DirectData")
    .setAttr({
        "KEY":{
            "fill":"90-#5198D3-#A1C8F6",
            "stroke":"#004A7F",
            "path":"M,319,85C,310.7157314383532,85,304,71.56854048887718,304,55C,304,38.43145548427702,310.7157178477474,25,319,25M,319,85C,319,85,319,85,319,85C,310.7157314383532,85,304,71.56854048887718,304,55C,304,38.43145548427702,310.7157178477474,25,319,25M,319,25C,319,25,319,25,319,25C,327.2842655415122,25,334,38.43145548427702,334,55C,334,71.56854048887718,327.2842655415122,85,319,85C,319,85,259,85,259,85C,250.7157118074781,85,244,71.56854048887718,244,55C,244,38.43145548427702,250.7157118074781,25,259,25C,259,25,319,25,319,25"
        },
        "TEXT":{
            "text":"网关",
            "font-size":"12px",
            "fill":"#fff",
            "font-weight":"bold"
        }
    })
);

路径语法解析:

  • M:移动到起点 (319,85)
  • C:三次贝塞尔曲线到目标点
  • 控制点计算确保平滑过渡
  • 复杂路径实现专业的流程图符号

4. 传感器节点(圆形)

javascript 复制代码
host.xui_ui_svgpaper7.append(
    ood.create("ood.svg.circleComb")
    .setHost(host,"xui_svg_circlecomb1")
    .setSvgTag("FlowChart:OnPageRefrence")
    .setAttr({
        "KEY":{
            "cx":504,
            "cy":55,
            "r":40,
            "fill":"90-#5198D3-#A1C8F6",
            "stroke":"#004A7F"
        },
        "TEXT":{
            "text":"传感器",
            "font-size":"12px",
            "fill":"#fff",
            "font-weight":"bold"
        }
    })
);

圆形属性:

  • cx, cy:圆心坐标,精确定位
  • r:半径大小
  • FlowChart:OnPageRefrence:页面引用类型

5. 智能连接线系统

javascript 复制代码
// 服务器 → 网关连接线
host.xui_ui_svgpaper7.append(
    ood.create("ood.svg.connector")
    .setHost(host,"xui_svg_connector19")
    .setSvgTag("Connectors:Straight")
    .setAttr({
        "KEY":{
            "path":"M,130,55L,244,55",
            "fill":"#B6E026",
            "stroke":"#228B22",
            "stroke-width":2,
            "arrow-start":"oval-midium-midium",
            "arrow-end":"classic-wide-long"
        },
        "BG":{
            "fill":"none",
            "stroke":"#fff",
            "stroke-width":4
        }
    })
    .setFromObj("xui_svg_rectcomb1")
    .setFromPoint("right")
    .setToObj("xui_svg_pathcomb49")
    .setToPoint("left")
);

连接线高级特性:

  • 双箭头系统:起始箭头+结束箭头
  • BG层:白色背景描边,增强可读性
  • 自动路径计算:基于形状位置
  • 智能连接点:rightleft 自然流向

设计模式总结

  1. 分层架构

    • SVGPaper(画布层)
    • 形状组合(图形层)
    • 连接线系统(关系层)
    • 文本标注(信息层)
  2. 样式系统

    • 一致性:相同渐变和描边
    • 可读性:对比色和适当大小
    • 专业性:标准流程图符号
  3. 交互设计

    • 逻辑连接:服务器→网关→传感器
    • 视觉引导:箭头方向和路径
    • 信息层次:标题和位置

扩展建议

  1. 动态数据绑定:将节点数据与后端API连接
  2. 交互增强:添加拖拽、缩放、选择功能
  3. 主题系统:支持暗色/亮色主题切换
  4. 导出功能:支持PNG、PDF、SVG格式导出

这个示例展示了A2UI SVG系统的强大功能,从基础形状创建到复杂的流程图构建,为各种数据可视化和图表应用提供了完整的解决方案。

API 参考

SVGPaper 类

构造函数

javascript 复制代码
new ood.UI.SVGPaper(config)

配置选项

属性 类型 默认值 描述
width String/Object '32em' 画布宽度
height String/Object '25em' 画布高度
scaleChildren Boolean false 是否缩放子元素
overflow String undefined 溢出处理
graphicZIndex Number 0 图形层级

实例方法

append(shape)

添加SVG形状到画布。

参数:

  • shape (Object): SVG形状对象

返回:

  • (Object): SVGPaper实例
removeChildren()

移除所有子元素。

返回:

  • (Object): SVGPaper实例
getPaper()

获取底层的Raphaël paper对象。

返回:

  • (Object): Raphaël paper实例
getSVGString()

获取SVG内容的字符串表示。

返回:

  • (String): SVG字符串
setChildren(shapes)

替换所有子元素。

参数:

  • shapes (Array): 形状对象数组

返回:

  • (Object): SVGPaper实例

形状创建 API

ood.create(type)

创建指定类型的SVG形状。

参数:

  • type (String): 形状类型标识符

返回:

  • (Object): 形状实例

常用形状类型

  • "ood.svg.circle":圆形
  • "ood.svg.rect":矩形
  • "ood.svg.rectComb":矩形组合
  • "ood.svg.pathComb":路径组合
  • "ood.svg.circleComb":圆形组合
  • "ood.svg.connector":连接线

形状配置方法

setHost(host, alias)

设置宿主和别名。

参数:

  • host (Object): 宿主对象
  • alias (String): 形状别名

返回:

  • (Object): 形状实例

setSvgTag(tag)

设置SVG标签类型。

参数:

  • tag (String): SVG标签标识符

返回:

  • (Object): 形状实例

setAttr(attributes)

设置形状属性。

参数:

  • attributes (Object): 属性对象

返回:

  • (Object): 形状实例

连接线配置方法

setFromObj(objAlias)

设置起始形状。

参数:

  • objAlias (String): 起始形状别名

返回:

  • (Object): 连接线实例

setFromPoint(point)

设置起始连接点。

参数:

  • point (String): 连接点位置(left/right/top/bottom)

返回:

  • (Object): 连接线实例

setToObj(objAlias)

设置目标形状。

参数:

  • objAlias (String): 目标形状别名

返回:

  • (Object): 连接线实例

setToPoint(point)

设置目标连接点。

参数:

  • point (String): 连接点位置(left/right/top/bottom)

返回:

  • (Object): 连接线实例

最佳实践

1. 性能优化

批量操作:

javascript 复制代码
// 不推荐:单独添加每个形状
shapes.forEach(function(shape) {
    svgPaper.append(shape);
});

// 推荐:批量添加
svgPaper.setChildren(shapes);

图形复用:

javascript 复制代码
// 创建模板形状
var templateShape = ood.create("ood.svg.rectComb")
    .setAttr({ /* 基础配置 */ });

// 批量创建相似形状
var shapes = data.map(function(item, index) {
    return templateShape.clone()
        .setHost(svgPaper, "shape_" + index)
        .setAttr({
            "KEY":{
                "x": index * 120,
                "y": 100
            },
            "TEXT":{
                "text": item.name
            }
        });
});

2. 可维护性

模块化设计:

javascript 复制代码
// 形状工厂
var ShapeFactory = {
    createServerNode: function(x, y, name) {
        return ood.create("ood.svg.rectComb")
            .setSvgTag("FlowChart:Process")
            .setAttr({
                "KEY":{
                    "x": x,
                    "y": y,
                    "width": 120,
                    "height": 60,
                    "fill": "90-#4285F4-#8AB4F8"
                },
                "TEXT":{
                    "text": name,
                    "fill": "#FFFFFF"
                }
            });
    },
    
    createDecisionNode: function(x, y, name) {
        return ood.create("ood.svg.pathComb")
            .setSvgTag("FlowChart:Decision")
            .setAttr({ /* 配置 */ });
    }
};

配置集中管理:

javascript 复制代码
// 样式配置
var StyleConfig = {
    colors: {
        primary: "90-#4285F4-#8AB4F8",
        success: "90-#34A853-#81C995",
        warning: "90-#FBBC05-#FDE293",
        danger: "90-#EA4335-#F28B82"
    },
    
    sizes: {
        node: { width: 120, height: 60 },
        text: { fontSize: "14px" }
    }
};

3. 响应式设计

javascript 复制代码
// 响应式布局调整
function adjustDiagramLayout(svgPaper, viewportWidth) {
    var scale = 1;
    
    if (viewportWidth < 768) {
        scale = 0.8;
    } else if (viewportWidth < 480) {
        scale = 0.6;
    }
    
    // 缩放所有形状
    svgPaper.each(function(shape) {
        shape.attr({
            "transform": "scale(" + scale + ")"
        });
    });
}

// 监听窗口大小变化
window.addEventListener('resize', function() {
    adjustDiagramLayout(svgPaper, window.innerWidth);
});

4. 可访问性

javascript 复制代码
// 增强可访问性
function enhanceAccessibility(svgPaper) {
    svgPaper.attr({
        "role": "img",
        "aria-label": "系统架构图"
    });
    
    // 为每个形状添加描述
    svgPaper.each(function(shape) {
        var text = shape.getAttr("TEXT")?.text || "图形元素";
        shape.attr({
            "aria-label": text,
            "tabindex": "0"  // 支持键盘导航
        });
    });
}

5. 事件处理最佳实践

事件委托模式

javascript 复制代码
// 为整个画布添加事件委托,而不是为每个形状单独绑定
svgPaper.on("click", ".node-shape", function(event) {
    var shape = event.target;
    console.log("节点被点击:", shape.alias);
    
    // 高亮显示被点击的节点
    shape.attr({
        "stroke": "#FF5722",
        "stroke-width": 3
    });
});

// 添加鼠标悬停效果
svgPaper.on("mouseover", ".node-shape", function(event) {
    event.target.attr({
        "cursor": "pointer",
        "filter": "url(#hover-shadow)"
    });
});

svgPaper.on("mouseout", ".node-shape", function(event) {
    event.target.attr({
        "filter": "none"
    });
});

自定义事件系统

javascript 复制代码
// 创建自定义事件触发器
function createInteractiveShape(svgPaper, config) {
    var shape = ood.create(config.type)
        .setHost(svgPaper, config.alias)
        .setAttr(config.attr);
    
    // 添加自定义事件
    shape.on("custom:select", function() {
        this.attr({
            "fill": "#FFEB3B",
            "stroke": "#FF9800"
        });
    });
    
    shape.on("custom:deselect", function() {
        this.attr({
            "fill": config.attr.KEY.fill,
            "stroke": config.attr.KEY.stroke
        });
    });
    
    return shape;
}

6. 动画效果应用

平滑过渡动画

javascript 复制代码
// 创建形状移动动画
function animateShapeMove(shape, targetX, targetY, duration) {
    var currentX = shape.attr("x") || shape.attr("cx");
    var currentY = shape.attr("y") || shape.attr("cy");
    
    shape.animate({
        "x": targetX,
        "y": targetY
    }, duration, "linear", function() {
        console.log("动画完成");
    });
}

// 创建连接线流动效果
function createFlowAnimation(connector) {
    var path = connector.attr("path");
    var length = connector.getTotalLength();
    
    // 创建虚线流动效果
    connector.attr({
        "stroke-dasharray": "10,5",
        "stroke-dashoffset": length
    });
    
    connector.animate({
        "stroke-dashoffset": 0
    }, 2000, "linear", function() {
        // 循环动画
        connector.attr({
            "stroke-dashoffset": length
        });
        createFlowAnimation(connector);
    });
}

交互反馈动画

javascript 复制代码
// 点击脉冲效果
function createPulseEffect(shape) {
    shape.on("click", function() {
        var originalStroke = shape.attr("stroke-width");
        
        // 脉冲动画
        shape.animate({
            "stroke-width": originalStroke * 3
        }, 200, ">", function() {
            shape.animate({
                "stroke-width": originalStroke
            }, 300);
        });
    });
}

// 悬停缩放效果
function createHoverScale(shape) {
    shape.on("mouseover", function() {
        shape.animate({
            "transform": "s1.1"
        }, 200);
    });
    
    shape.on("mouseout", function() {
        shape.animate({
            "transform": "s1"
        }, 200);
    });
}

7. 与其他A2UI组件集成

与MDialog集成创建图形编辑器

javascript 复制代码
function createSVGEditorDialog() {
    var dialog = ood.create("ood.UI.MDialog")
        .setTitle("SVG 图形编辑器")
        .setWidth("800px")
        .setHeight("600px");
    
    // 在对话框中添加SVGPaper
    var svgPaper = ood.create("ood.UI.SVGPaper")
        .setWidth("100%")
        .setHeight("100%");
    
    dialog.append(svgPaper);
    
    // 添加工具栏
    var toolbar = ood.create("ood.UI.ToolBar")
        .addButton("矩形", function() {
            // 创建矩形形状
            svgPaper.append(createRectShape());
        })
        .addButton("圆形", function() {
            // 创建圆形形状
            svgPaper.append(createCircleShape());
        });
    
    dialog.append(toolbar);
    
    return dialog;
}

与MFormLayout集成创建属性编辑器

javascript 复制代码
function createShapePropertyEditor(shape) {
    var form = ood.create("ood.UI.MFormLayout")
        .setLabelWidth("100px");
    
    // 添加形状属性编辑控件
    form.addItem("x", "位置X", {
        type: "textbox",
        value: shape.attr("x") || shape.attr("cx"),
        onValueChange: function(value) {
            shape.attr("x", parseInt(value));
        }
    });
    
    form.addItem("y", "位置Y", {
        type: "textbox",
        value: shape.attr("y") || shape.attr("cy"),
        onValueChange: function(value) {
            shape.attr("y", parseInt(value));
        }
    });
    
    form.addItem("fill", "填充颜色", {
        type: "colorpicker",
        value: shape.attr("fill"),
        onValueChange: function(value) {
            shape.attr("fill", value);
        }
    });
    
    return form;
}

8. 数据可视化最佳实践

数据绑定模式

javascript 复制代码
function createDataVisualization(svgPaper, data) {
    var maxValue = Math.max.apply(null, data.map(d => d.value));
    var barWidth = 40;
    var spacing = 20;
    
    data.forEach(function(item, index) {
        var barHeight = (item.value / maxValue) * 300;
        var x = index * (barWidth + spacing) + 50;
        var y = 350 - barHeight;
        
        // 创建数据柱状图
        var bar = ood.create("ood.svg.rectComb")
            .setHost(svgPaper, "bar_" + index)
            .setAttr({
                "KEY":{
                    "x": x,
                    "y": y,
                    "width": barWidth,
                    "height": barHeight,
                    "fill": getColorByValue(item.value)
                },
                "TEXT":{
                    "text": item.label,
                    "x": x + barWidth/2,
                    "y": 370,
                    "text-anchor": "middle",
                    "font-size": "12px"
                }
            });
        
        // 添加数值标签
        var valueText = ood.create("ood.svg.text")
            .setHost(svgPaper, "value_" + index)
            .setAttr({
                "KEY":{
                    "x": x + barWidth/2,
                    "y": y - 10,
                    "text": item.value,
                    "text-anchor": "middle",
                    "font-size": "11px",
                    "fill": "#333"
                }
            });
        
        svgPaper.append(bar);
        svgPaper.append(valueText);
    });
}

function getColorByValue(value) {
    if (value > 80) return "90-#FF5252-#FF8A80";
    if (value > 60) return "90-#FF9800-#FFCC80";
    if (value > 40) return "90-#4CAF50-#A5D6A7";
    return "90-#2196F3-#90CAF9";
}

实时数据更新

javascript 复制代码
// 实时更新数据可视化
function updateDataVisualization(svgPaper, newData) {
    // 平滑过渡更新
    newData.forEach(function(item, index) {
        var bar = svgPaper.getChild("bar_" + index);
        if (bar) {
            // 计算新的柱状图高度
            var maxValue = Math.max.apply(null, newData.map(d => d.value));
            var barHeight = (item.value / maxValue) * 300;
            var y = 350 - barHeight;
            
            // 动画更新
            bar.animate({
                "height": barHeight,
                "y": y
            }, 500);
            
            // 更新数值标签
            var valueText = svgPaper.getChild("value_" + index);
            if (valueText) {
                valueText.animate({
                    "y": y - 10
                }, 500);
                
                valueText.attr({
                    "text": item.value
                });
            }
        }
    });
}

常见问题

1. 图形不显示

可能原因:

  • 画布尺寸未正确设置
  • 形状坐标超出画布范围
  • 样式配置错误

解决方案:

javascript 复制代码
// 检查画布配置
console.log('画布尺寸:', svgPaper.width(), svgPaper.height());

// 检查形状坐标
shape.attr({
    "fill": "#FF0000",  // 使用简单颜色测试
    "stroke": "#000000"
});

2. 连接线不连接

可能原因:

  • 形状别名不正确
  • 连接点位置无效
  • 路径计算错误

解决方案:

javascript 复制代码
// 验证形状别名
console.log('起始形状别名:', connector.properties.fromObj);
console.log('目标形状别名:', connector.properties.toObj);

// 检查连接点
console.log('连接点位置:', {
    from: connector.properties.fromPoint,
    to: connector.properties.toPoint
});

3. 渐变效果不显示

可能原因:

  • 渐变格式不正确
  • 浏览器不支持
  • 颜色值格式错误

解决方案:

javascript 复制代码
// 使用标准颜色测试
shape.attr({
    "fill": "#FF0000"  // 替换渐变测试
});

// 检查渐变格式
var gradient = "90-#FF0000-#0000FF";
console.log('渐变格式:', gradient.split('-'));

4. 交互事件不触发

可能原因:

  • 事件绑定时机不对
  • 事件名不正确
  • 形状层级问题

解决方案:

javascript 复制代码
// 确保在形状渲染后绑定事件
shape.on("click", function() {
    console.log('形状被点击');
});

// 检查事件系统
console.log('形状事件监听器:', shape._events);

总结

SVGPaper 是 A2UI 框架中强大的矢量图形组件,为创建复杂的图表、流程图和数据可视化提供了完整的解决方案。通过本专辑的学习,您应该能够:

  1. 掌握 SVGPaper 的核心功能:创建画布、添加形状、配置样式
  2. 了解 SVG 形状类型:基础形状、流程图专用形状、组合形状
  3. 熟练使用连接线系统:直线、曲线、流程图连接线
  4. 应用高级样式:渐变填充、阴影效果、交互样式
  5. 构建实际应用:系统架构图、业务流程、组织结构图

下一步建议

  1. 实践练习:根据本专辑的示例,创建自己的SVG图表
  2. 探索高级特性:深入研究Raphaël SVG库的高级功能
  3. 集成数据绑定:将SVG图形与动态数据结合
  4. 性能优化:对于大规模图形,实施虚拟化和懒加载
  5. 主题系统:创建可切换的主题样式

相关资源


本专辑基于 A2UI 框架和实际应用案例编写,内容将持续更新和完善。如有任何问题或建议,欢迎提交反馈。

© 2025 A2UI 项目组 | MIT License

相关推荐
P-ShineBeam7 小时前
知识图谱-KGQA意图澄清-CLEAR_KGQA
人工智能·语言模型·自然语言处理·知识图谱
paopao_wu7 小时前
LangChainV1.0[06]-Prompt/上下文/结构化输出
人工智能·langchain·prompt·ai编程
研☆香7 小时前
html界面的树形菜单介绍与制作
前端·microsoft·html
权泽谦7 小时前
传统机器学习 vs 深度学习:什么时候该选谁?
人工智能·深度学习·机器学习
星辰也为你祝福h7 小时前
前端面试题-CSS篇
前端·css
金融Tech趋势派7 小时前
2026金融行业私域运营:选SCRM,合规与功能如何平衡?微盛·企微管家解析
人工智能
咚咚王者7 小时前
人工智能之核心基础 机器学习 第八章 无监督学习概述
人工智能·学习·机器学习
编程武士7 小时前
开源 AI 智能体项目 Parlant 介绍
人工智能·开源
雨雨雨雨雨别下啦7 小时前
ajax和axios到底是什么
前端·ajax·okhttp
shayudiandian7 小时前
AI安全与伦理:深度学习的“双刃剑”
人工智能·深度学习·安全