发布时间:2025-06-24 18:27:46  作者:北方职教升学中心  阅读量:132


line.setAttribute('y1', y1); // 为线段元素设置 x2 属性,表示线段终点的X坐标,这里的 x2 是一个变量,存储了所需的数值。 this.rectElement.setAttribute('fill', fillColor); // 设置了矩形元素的描边颜色为黑色 this.rectElement.setAttribute('stroke', stroke); // 矩形元素的描边宽度为2个单位 this.rectElement.setAttribute('stroke-width', 2); // 创建了一个新的SVG文本元素。 let textElement = document.createElementNS("http://www.w3.org/2000/svg", 'text'); // 'x' 属性设置文本元素在水平方向上的起始位置:为矩形容器的起始x坐标加上宽度的一半 textElement.setAttribute('x', initialX + width / 2); // 'y' 属性设置文本元素在竖直方向上的起始位置:为矩形容器的起始y坐标加上高度的一半 textElement.setAttribute('y', initialY + height / 2); // 设置SVG文本元素的对齐方式:居中 textElement.setAttribute('text-anchor', 'middle'); // 这会让文本水平居中 textElement.setAttribute('dominant-baseline', 'middle'); // 竖直居中,在某些浏览器中可能需要其他值,比如 'central' // 将先前创建的SVG矩形元素(this.rectElement) 添加为 this.svgElement 的子元素 this.svgElement.appendChild(this.rectElement); // 将先前创建的SVG矩形元素(this.textElement) 添加为 this.svgElement 的子元素 this.svgElement.appendChild(textElement); // 将文本元素引用赋值给了类的成员变量 this.textElement,这样后续可以通过 this.textElement 直接访问和操作这个文本元素,比如设置文本内容、 const headX1 = x2 - arrowHeadSize * Math.cos(angle - Math.PI / 6); // 计算箭头左侧顶点相对于线段终点的Y坐标。 line.setAttribute('y2', y2); // 设置线段的颜色 line.setAttribute('stroke', color); //设置线段的粗细 line.setAttribute('stroke-width', strokeWidth); // 创建箭头头部 // 创建一个名为 arrowHead 的SVG多边形元素,这里是创建一个三角形作为箭头头部 const arrowHead = document.createElementNS("http://www.w3.org/2000/svg", 'polygon'); // 计算向量的差分和长度 //计算线段从起点 x1 到终点 x2 在X轴上的位移。 this.textElement = textElement; } // 设置SVG文本元素的内容 setText(textContent) { this.textElement.textContent = textContent; } // 添加创建和连接直线箭头的方法 createArrow(x1, y1, x2, y2, color = '#1d6ee7', strokeWidth = 2) { // 创建的SVG元素类型——这里是线段元素 const line = document.createElementNS("http://www.w3.org/2000/svg", 'line'); // 为刚创建的SVG线段元素设置 x1 属性,表示线段起点的X坐标,这里的 x1 是一个变量,存储了所需的数值。 line.setAttribute('x2', x2); // 为线段元素设置 y2 属性,表示线段终点的Y坐标,这里的 y2 是一个变量,存储了所需的数值。 this.svgElement.appendChild(line); //将创建好的箭头头部(多边形)元素也添加到相同的SVG容器元素中,这样就形成了一个带有箭头的线段图形。 line.setAttribute('y2', y2); // 设置线段的颜色 line.setAttribute('stroke', color); //设置线段的粗细 line.setAttribute('stroke-width', strokeWidth); // 创建箭头头部 // 创建一个名为 arrowHead 的SVG多边形元素,这里是创建一个三角形作为箭头头部 const arrowHead = document.createElementNS("http://www.w3.org/2000/svg", 'polygon'); // 计算向量的差分和长度 //计算线段从起点 x1 到终点 x2 在X轴上的位移。 this.svgElement.appendChild(arrowHead); } //定义了一个名为connectTo的方法,用于连接两个SVG图形 connectTo(otherShape, startAnchor = { side: 'right', verticalAlign: 'center' }, endAnchor = { side: 'left', verticalAlign: 'center' }) { const myBBox = this.rectElement.getBBox(); const otherBBox = otherShape.rectElement.getBBox(); let startX, startY, endX, endY; switch (startAnchor.side) { case 'left': startX = myBBox.x; startY = startAnchor.verticalAlign === 'top' ? myBBox.y : myBBox.y + myBBox.height / 2; break; case 'right': startX = myBBox.x + myBBox.width; startY = startAnchor.verticalAlign === 'top' ? myBBox.y : myBBox.y + myBBox.height / 2; break; case 'top': startX = startAnchor.horizontalAlign === 'left' ? myBBox.x : myBBox.x + myBBox.width / 2; startY = myBBox.y; break; case 'bottom': startX = startAnchor.horizontalAlign === 'left' ? myBBox.x : myBBox.x + myBBox.width / 2; startY = myBBox.y + myBBox.height; break; default: // 默认为中心点 startX = myBBox.x + myBBox.width / 2; startY = myBBox.y + myBBox.height / 2; break; } switch (endAnchor.side) { case 'left': endX = otherBBox.x; endY = endAnchor.verticalAlign === 'top' ? otherBBox.y : otherBBox.y + otherBBox.height / 2; break; case 'right': endX = otherBBox.x + otherBBox.width; endY = endAnchor.verticalAlign === 'top' ? otherBBox.y : otherBBox.y + otherBBox.height / 2; break; case 'top': endX = endAnchor.horizontalAlign === 'left' ? otherBBox.x : otherBBox.x + otherBBox.width / 2; endY = otherBBox.y; break; case 'bottom': endX = endAnchor.horizontalAlign === 'left' ? otherBBox.x : otherBBox.x + otherBBox.width / 2; endY = otherBBox.y + otherBBox.height; break; default: // 默认为中心点 endX = otherBBox.x + otherBBox.width / 2; endY = otherBBox.y + otherBBox.height / 2; break; } this.createArrow(startX, startY, endX, endY); } // 新增setLink方法,处理超链接逻辑 setLink(url) { const linkElement = document.createElementNS("http://www.w3.org/2000/svg", 'a'); linkElement.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', url); // 如果矩形框和文本不在同一个父节点下,或者不在linkElement内 if (this.rectElement.parentNode !== linkElement && this.textElement.parentNode !== linkElement) { // 移除它们原先所在的位置 this.rectElement.parentNode.removeChild(this.rectElement); this.textElement.parentNode.removeChild(this.textElement); // 将矩形和文本都添加到链接元素内部 linkElement.appendChild(this.rectElement); linkElement.appendChild(this.textElement); // 确保链接元素被添加到SVG容器内 this.svgElement.appendChild(linkElement); // 更新类的成员变量引用为链接元素 this.linkElement = linkElement; } else if (this.linkElement) { // 如果linkElement已经存在但href需要更新 this.linkElement.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', url); } else { // 如果linkElement不存在但在同一父节点下,可以直接将它们包裹进新的linkElement this.rectElement.parentNode.insertBefore(linkElement, this.rectElement); linkElement.appendChild(this.rectElement); linkElement.appendChild(this.textElement); this.linkElement = linkElement; } }}// 示例:创建三个矩形框并连接它们window.onload = function () { var svgElement = document.getElementById('workflow-svg'); // 初始化三个矩形框并设置链接(x轴,y轴,宽,高) let shape1Ref = new FlowChartShape(svgElement, 50, 150, 120, 40); let shape2Ref = new FlowChartShape(svgElement, 250, 150, 120, 40); let shape3Ref = new FlowChartShape(svgElement, 450, 150, 120, 40); let shape4Ref = new FlowChartShape(svgElement, 650, 150, 120, 40); let shape5Ref = new FlowChartShape(svgElement, 350, 50, 120, 40); let shape6Ref = new FlowChartShape(svgElement, 250, 250, 120, 40); let shape7Ref = new FlowChartShape(svgElement, 450, 250, 120, 40); let shape8Ref = new FlowChartShape(svgElement, 650, 250, 120, 40); let shape9Ref = new FlowChartShape(svgElement, 850, 250, 120, 40); let shape10Ref = new FlowChartShape(svgElement, 850, 350, 120, 40); let shape11Ref = new FlowChartShape(svgElement, 850, 450, 120, 40); let shape12Ref = new FlowChartShape(svgElement, 350, 350, 120, 40); let shape13Ref = new FlowChartShape(svgElement, 550, 350, 120, 40); setTimeout(() => { //设置名称 shape1Ref.setText('销售订单'); shape2Ref.setText('报价申请'); shape3Ref.setText('报价单签核'); shape4Ref.setText('报价单回复'); shape5Ref.setText('报价单修改'); shape6Ref.setText('订单建立'); shape7Ref.setText('订单审核'); shape8Ref.setText('订单出货'); shape9Ref.setText('销售退货'); shape10Ref.setText('出货对账'); shape11Ref.setText('出货对账取消'); shape12Ref.setText('订单修改'); shape13Ref.setText('订单反审核'); // 连接矩形框 shape1Ref.connectTo(shape2Ref); shape2Ref.connectTo(shape3Ref); shape3Ref.connectTo(shape4Ref); //2的顶部中点到5的底部中点 shape2Ref.connectTo(shape5Ref, { side: 'top', verticalAlign: 'center' }, { side: 'left', verticalAlign: 'center' }); // 从shape1Ref的左上角到shape2Ref的右下角: // shape1Ref.connectTo(shape2Ref, { // side: 'left', // verticalAlign: 'top' // }, { // side: 'right', // verticalAlign: 'bottom' // }); shape5Ref.connectTo(shape3Ref, { side: 'right', verticalAlign: 'center' }, { side: 'top', verticalAlign: 'center' }); shape1Ref.connectTo(shape6Ref); shape6Ref.connectTo(shape7Ref); shape7Ref.connectTo(shape8Ref); shape8Ref.connectTo(shape9Ref); shape9Ref.connectTo(shape10Ref, { side: 'bottom', verticalAlign: 'center' }, { side: 'top', verticalAlign: 'center' }); shape10Ref.connectTo(shape11Ref, { side: 'bottom', verticalAlign: 'center' }, { side: 'top', verticalAlign: 'center' }); shape7Ref.connectTo(shape13Ref, { side: 'bottom', verticalAlign: 'center' }, { side: 'top', verticalAlign: 'center' }); shape13Ref.connectTo(shape12Ref, { side: 'left', verticalAlign: 'center' }, { side: 'right', verticalAlign: 'center' }); shape12Ref.connectTo(shape7Ref, { side: 'top', verticalAlign: 'center' }, { side: 'bottom', verticalAlign: 'center' }); //添加超链接 shape1Ref.setLink('page1.html'); // 为第一个矩形框设置链接到“page1.html” shape2Ref.setLink('page2.html'); // 为第二个矩形框设置链接到“page2.html” shape3Ref.setLink('page3.html'); // 为第三个矩形框设置链接到“page3.html” }, 0);};

版本二

把实现图形的部分写在html页面+部分修改

效果

代码

html

<?phpinclude('includes/session.inc');// echo $RootPath;?><!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>销售流程</title>    <style>        body {            display: flex;            justify-content: center;            /* 水平居中 */            align-items: center;            /* 垂直居中 */            min-height: 100vh;            /* 确保整个视窗高度 */            margin: 0;            padding: 0;            box-sizing: border-box;        }        div {            /* 如果需要可以设置宽度和高度 */            width: 55%;            height: 50%;        }        #workflow-svg {            width: 1000px;            height: 600px;            /* border: 1px solid black; */        }    </style>    <script src="javascript/flow/flow.js"></script>    <script>        // 示例:创建三个矩形框并连接它们        window.onload = function() {            var svgElement = document.getElementById('workflow-svg');            // 初始化三个矩形框并设置链接(x轴,y轴,宽,高)            let shape1Ref = new FlowChartShape(svgElement, 50, 150, 120, 40, '#1d6ee7', '#1d6ee7', '#FFF');            let shape2Ref = new FlowChartShape(svgElement, 250, 150, 120, 40);            let shape3Ref = new FlowChartShape(svgElement, 450, 150, 120, 40);            let shape4Ref = new FlowChartShape(svgElement, 650, 150, 120, 40);            let shape5Ref = new FlowChartShape(svgElement, 350, 50, 120, 40);            let shape6Ref = new FlowChartShape(svgElement, 250, 250, 120, 40);            let shape7Ref = new FlowChartShape(svgElement, 450, 250, 120, 40);            let shape8Ref = new FlowChartShape(svgElement, 650, 250, 120, 40);            let shape9Ref = new FlowChartShape(svgElement, 850, 250, 120, 40);            let shape10Ref = new FlowChartShape(svgElement, 850, 350, 120, 40);            let shape11Ref = new FlowChartShape(svgElement, 850, 450, 120, 40);            let shape12Ref = new FlowChartShape(svgElement, 350, 350, 120, 40);            let shape13Ref = new FlowChartShape(svgElement, 550, 350, 120, 40);            setTimeout(() => {                //设置名称                shape1Ref.setText('销售订单');                shape2Ref.setText('报价申请');                shape3Ref.setText('报价单签核');                shape4Ref.setText('报价单回复');                shape5Ref.setText('报价单修改');                shape6Ref.setText('订单建立');                shape7Ref.setText('订单审核');                shape8Ref.setText('订单出货');                shape9Ref.setText('销售退货');                shape10Ref.setText('出货对账');                shape11Ref.setText('出货对账取消');                shape12Ref.setText('订单修改');                shape13Ref.setText('订单反审核');                // 连接矩形框                shape1Ref.connectTo(shape2Ref);                shape2Ref.connectTo(shape3Ref);                shape3Ref.connectTo(shape4Ref);                //2的顶部中点到5的底部中点                shape2Ref.connectTo(shape5Ref, {                    side: 'top',                    verticalAlign: 'center'                }, {                    side: 'left',                    verticalAlign: 'center'                });                // 从shape1Ref的左上角到shape2Ref的右下角:                // shape1Ref.connectTo(shape2Ref, {                //     side: 'left',                //     verticalAlign: 'top'                // }, {                //     side: 'right',                //     verticalAlign: 'bottom'                // });                shape5Ref.connectTo(shape3Ref, {                    side: 'right',                    verticalAlign: 'center'                }, {                    side: 'top',                    verticalAlign: 'center'                });                shape1Ref.connectTo(shape6Ref);                shape6Ref.connectTo(shape7Ref);                shape7Ref.connectTo(shape8Ref);                shape8Ref.connectTo(shape9Ref);                shape9Ref.connectTo(shape10Ref, {                    side: 'bottom',                    verticalAlign: 'center'                }, {                    side: 'top',                    verticalAlign: 'center'                });                shape10Ref.connectTo(shape11Ref, {                    side: 'bottom',                    verticalAlign: 'center'                }, {                    side: 'top',                    verticalAlign: 'center'                });                shape7Ref.connectTo(shape13Ref, {                    side: 'bottom',                    verticalAlign: 'center'                }, {                    side: 'top',                    verticalAlign: 'center'                });                shape13Ref.connectTo(shape12Ref, {                    side: 'left',                    verticalAlign: 'center'                }, {                    side: 'right',                    verticalAlign: 'center'                });                shape12Ref.connectTo(shape7Ref, {                    side: 'top',                    verticalAlign: 'center'                }, {                    side: 'bottom',                    verticalAlign: 'center'                });                //添加超链接                shape2Ref.setLink('<?php echo $RootPath; ?>/QuoteRequest.php'); // 为第二个矩形框设置链接到“page2.html”                shape3Ref.setLink('<?php echo $RootPath; ?>/QuoteToCustomerapproved.php'); // 为第三个矩形框设置链接到“page3.html”                shape4Ref.setLink('<?php echo $RootPath; ?>/QuoteCustomerReply.php');                shape5Ref.setLink('<?php echo $RootPath; ?>/QuoteRequestModify.php');                shape6Ref.setLink('<?php echo $RootPath; ?>/AddNewOrder.php');                shape7Ref.setLink('<?php echo $RootPath; ?>/SearchSoForApprove.php');                shape8Ref.setLink('<?php echo $RootPath; ?>/SearchShipOrder.php');                shape9Ref.setLink('<?php echo $RootPath; ?>/OrderReturn.php');                shape10Ref.setLink('<?php echo $RootPath; ?>/CheckSODelivery.php');                shape11Ref.setLink('<?php echo $RootPath; ?>/CheckSODeliveryUpdate.php');                shape12Ref.setLink('<?php echo $RootPath; ?>/UpdateSoForApprove.php');                shape13Ref.setLink('<?php echo $RootPath; ?>/SoReturnApprove.php');            }, 0);        };    </script></head><body>    <div>        <svg id="workflow-svg">            <!-- SVG图形内容... -->        </svg>    </div></body></html>

js

增加linkElement.setAttribute('target', '_blank'); // 使链接在新窗口打开

矩形框颜色,边框颜色,字体颜色:按不同矩形框自行定义

// 定义矩形框class FlowChartShape {    // 定义一个类的构造函数。        this.rectElement.setAttribute('fill', '#fff');        // 设置了矩形元素的描边颜色为黑色        this.rectElement.setAttribute('stroke', '#1d6ee7');        // 矩形元素的描边宽度为2个单位        this.rectElement.setAttribute('stroke-width', 2);        // 创建了一个新的SVG文本元素。        this.rectElement = document.createElementNS("http://www.w3.org/2000/svg", 'rect');        // 设定矩形元素在其父SVG容器中的X坐标位置        this.rectElement.setAttribute('x', initialX);        // 设定矩形元素在其父SVG容器中的y坐标位置        this.rectElement.setAttribute('y', initialY);        // 设定矩形元素在其父SVG容器中的宽度        this.rectElement.setAttribute('width', width);        // 设定矩形元素在其父SVG容器中的高度        this.rectElement.setAttribute('height', height);        // 设置矩形的圆角半径设置为10个单位        this.rectElement.setAttribute('rx', 10);        // 设置当前SVG矩形元素的内部填充颜色为纯白色。        const headX2 = x2 - arrowHeadSize * Math.cos(angle + Math.PI / 6);        // 计算箭头右侧顶点相对于线段终点的Y坐标。        const headX1 = x2 - arrowHeadSize * Math.cos(angle - Math.PI / 6);        // 计算箭头左侧顶点相对于线段终点的Y坐标。        line.setAttribute('x1', x1);        // 为线段元素设置 y1 属性,表示线段起点的Y坐标,这里的 y1 是一个变量,存储了所需的数值。width和height:这两个参数表示矩形框的宽度和高度    //fillColor矩形填充颜色:默认为白色、更改样式等。        const headY1 = y2 - arrowHeadSize * Math.sin(angle - Math.PI / 6);        // 根据角度加上π/6(30度),计算箭头右侧顶点相对于线段终点的X坐标。

效果

代码

html代码

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>SVG流程图示例</title>    <style>        /* CSS 样式 */    </style>    <script src="js/index.js"></script> <!-- 引入外部JS文件 --></head><body>    <svg id="workflow-svg" width="1000" height="800">        <!-- SVG图形内容... -->    </svg></body></html>

js/index.js

// 定义矩形框class FlowChartShape {    // 定义一个类的构造函数。svgElement容纳新创建的矩形框、        this.rectElement = document.createElementNS("http://www.w3.org/2000/svg", 'rect');        // 设定矩形元素在其父SVG容器中的X坐标位置        this.rectElement.setAttribute('x', initialX);        // 设定矩形元素在其父SVG容器中的y坐标位置        this.rectElement.setAttribute('y', initialY);        // 设定矩形元素在其父SVG容器中的宽度        this.rectElement.setAttribute('width', width);        // 设定矩形元素在其父SVG容器中的高度        this.rectElement.setAttribute('height', height);        // 设置矩形的圆角半径设置为10个单位        this.rectElement.setAttribute('rx', 10);        // 设置当前SVG矩形元素的内部填充颜色为纯白色。initialX,initialY分别代表矩形框左上角的初始X轴和Y轴坐标、        line.setAttribute('x1', x1);        // 为线段元素设置 y1 属性,表示线段起点的Y坐标,这里的 y1 是一个变量,存储了所需的数值。        arrowHead.setAttribute('fill', color);        //将之前创建的线段元素添加到一个假设存在的SVG容器元素 this.svgElement 中。        const dx = x2 - x1;        //计算线段在Y轴上的位移。        const headY2 = y2 - arrowHeadSize * Math.sin(angle + Math.PI / 6);        // 设置SVG多边形元素的points属性,该属性接受一系列顶点坐标,此处定义了一个等腰三角形作为箭头头部,三个顶点分别为线段终点和刚刚计算出的两侧顶点。        const dx = x2 - x1;        //计算线段在Y轴上的位移。width和height:这两个参数表示矩形框的宽度和高度    constructor(svgElement, initialX, initialY, width, height) {        //是在当前类的实例(FlowChartShape)内部设置一个成员变量。initialX,initialY分别代表矩形框左上角的初始X轴和Y轴坐标、        line.setAttribute('y1', y1);        // 为线段元素设置 x2 属性,表示线段终点的X坐标,这里的 x2 是一个变量,存储了所需的数值。        const headY2 = y2 - arrowHeadSize * Math.sin(angle + Math.PI / 6);        // 设置SVG多边形元素的points属性,该属性接受一系列顶点坐标,此处定义了一个等腰三角形作为箭头头部,三个顶点分别为线段终点和刚刚计算出的两侧顶点。        arrowHead.setAttribute('points', [`${x2},${y2}`, `${headX1},${headY1}`, `${headX2},${headY2}`].join(' '));        //设置箭头头部多边形的填充颜色,使其与线段颜色一致。        arrowHead.setAttribute('fill', color);        //将之前创建的线段元素添加到一个假设存在的SVG容器元素 this.svgElement 中。font_color文字字体:默认为黑色    constructor(svgElement, initialX, initialY, width, height, fillColor = "#ffffff", stroke = '#1d6ee7', font_color = '#000') {        //是在当前类的实例(FlowChartShape)内部设置一个成员变量。        const dy = y2 - y1;        //计算线段的长度(欧几里得距离)        const len = Math.sqrt(dx * dx + dy * dy);        //计算线段的方向角,即从起点指向终点的角度,使用 Math.atan2 函数得到弧度值        const angle = Math.atan2(dy, dx);        //定义箭头头部的大小,这是一个常量,用来决定箭头三角形两边的长度        const arrowHeadSize = 10;        // 计算箭头三角形的两个顶点坐标        //根据角度减去π/6(30度),计算箭头左侧顶点相对于线段终点的X坐标。        this.textElement = textElement;    }    // 设置SVG文本元素的内容    setText(textContent) {        this.textElement.textContent = textContent;    }    // 添加创建和连接直线箭头的方法    createArrow(x1, y1, x2, y2, color = '#1d6ee7', strokeWidth = 2) {        // 创建的SVG元素类型——这里是线段元素        const line = document.createElementNS("http://www.w3.org/2000/svg", 'line');        // 为刚创建的SVG线段元素设置 x1 属性,表示线段起点的X坐标,这里的 x1 是一个变量,存储了所需的数值。        line.setAttribute('x2', x2);        // 为线段元素设置 y2 属性,表示线段终点的Y坐标,这里的 y2 是一个变量,存储了所需的数值。意味着每个FlowChartShape实例都将与特定的SVG元素关联起来        this.svgElement = svgElement;        // 创建一个新的SVG < rect > 元素(图形)。意味着每个FlowChartShape实例都将与特定的SVG元素关联起来        this.svgElement = svgElement;        // 创建一个新的SVG < rect > 元素(图形)。        const headY1 = y2 - arrowHeadSize * Math.sin(angle - Math.PI / 6);        // 根据角度加上π/6(30度),计算箭头右侧顶点相对于线段终点的X坐标。        const dy = y2 - y1;        //计算线段的长度(欧几里得距离)        const len = Math.sqrt(dx * dx + dy * dy);        //计算线段的方向角,即从起点指向终点的角度,使用 Math.atan2 函数得到弧度值        const angle = Math.atan2(dy, dx);        //定义箭头头部的大小,这是一个常量,用来决定箭头三角形两边的长度        const arrowHeadSize = 10;        // 计算箭头三角形的两个顶点坐标        //根据角度减去π/6(30度),计算箭头左侧顶点相对于线段终点的X坐标。stroke矩形边框颜色:给定默认值、更改样式等。        this.svgElement.appendChild(arrowHead);    }    //定义了一个名为connectTo的方法,用于连接两个SVG图形    connectTo(otherShape, startAnchor = { side: 'right', verticalAlign: 'center' }, endAnchor = { side: 'left', verticalAlign: 'center' }) {        const myBBox = this.rectElement.getBBox();        const otherBBox = otherShape.rectElement.getBBox();        let startX, startY, endX, endY;        switch (startAnchor.side) {            case 'left':                startX = myBBox.x;                startY = startAnchor.verticalAlign === 'top' ? myBBox.y : myBBox.y + myBBox.height / 2;                break;            case 'right':                startX = myBBox.x + myBBox.width;                startY = startAnchor.verticalAlign === 'top' ? myBBox.y : myBBox.y + myBBox.height / 2;                break;            case 'top':                startX = startAnchor.horizontalAlign === 'left' ? myBBox.x : myBBox.x + myBBox.width / 2;                startY = myBBox.y;                break;            case 'bottom':                startX = startAnchor.horizontalAlign === 'left' ? myBBox.x : myBBox.x + myBBox.width / 2;                startY = myBBox.y + myBBox.height;                break;            default: // 默认为中心点                startX = myBBox.x + myBBox.width / 2;                startY = myBBox.y + myBBox.height / 2;                break;        }        switch (endAnchor.side) {            case 'left':                endX = otherBBox.x;                endY = endAnchor.verticalAlign === 'top' ? otherBBox.y : otherBBox.y + otherBBox.height / 2;                break;            case 'right':                endX = otherBBox.x + otherBBox.width;                endY = endAnchor.verticalAlign === 'top' ? otherBBox.y : otherBBox.y + otherBBox.height / 2;                break;            case 'top':                endX = endAnchor.horizontalAlign === 'left' ? otherBBox.x : otherBBox.x + otherBBox.width / 2;                endY = otherBBox.y;                break;            case 'bottom':                endX = endAnchor.horizontalAlign === 'left' ? otherBBox.x : otherBBox.x + otherBBox.width / 2;                endY = otherBBox.y + otherBBox.height;                break;            default: // 默认为中心点                endX = otherBBox.x + otherBBox.width / 2;                endY = otherBBox.y + otherBBox.height / 2;                break;        }        this.createArrow(startX, startY, endX, endY);    }    // 新增setLink方法,处理超链接逻辑    setLink(url) {        const linkElement = document.createElementNS("http://www.w3.org/2000/svg", 'a');        linkElement.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', url);        // linkElement.setAttribute('target', '_blank'); // 使链接在新窗口打开        // 如果矩形框和文本不在同一个父节点下,或者不在linkElement内        if (this.rectElement.parentNode !== linkElement && this.textElement.parentNode !== linkElement) {            // 移除它们原先所在的位置            this.rectElement.parentNode.removeChild(this.rectElement);            this.textElement.parentNode.removeChild(this.textElement);            // 将矩形和文本都添加到链接元素内部            linkElement.appendChild(this.rectElement);            linkElement.appendChild(this.textElement);            // 确保链接元素被添加到SVG容器内            this.svgElement.appendChild(linkElement);            // 更新类的成员变量引用为链接元素            this.linkElement = linkElement;        } else if (this.linkElement) {            // 如果linkElement已经存在但href需要更新            this.linkElement.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', url);        } else {            // 如果linkElement不存在但在同一父节点下,可以直接将它们包裹进新的linkElement            this.rectElement.parentNode.insertBefore(linkElement, this.rectElement);            linkElement.appendChild(this.rectElement);            linkElement.appendChild(this.textElement);            this.linkElement = linkElement;        }    }}

this.svgElement.appendChild(line); //将创建好的箭头头部(多边形)元素也添加到相同的SVG容器元素中,这样就形成了一个带有箭头的线段图形。 const headX2 = x2 - arrowHeadSize * Math.cos(angle + Math.PI / 6); // 计算箭头右侧顶点相对于线段终点的Y坐标。 let textElement = document.createElementNS("http://www.w3.org/2000/svg", 'text'); // 'x' 属性设置文本元素在水平方向上的起始位置:为矩形容器的起始x坐标加上宽度的一半 textElement.setAttribute('x', initialX + width / 2); // 'y' 属性设置文本元素在竖直方向上的起始位置:为矩形容器的起始y坐标加上高度的一半 textElement.setAttribute('y', initialY + height / 2); //设置字体颜色 textElement.setAttribute('fill', font_color); // 设置字体颜色为红色 // 设置SVG文本元素的对齐方式:居中 textElement.setAttribute('text-anchor', 'middle'); // 这会让文本水平居中 textElement.setAttribute('dominant-baseline', 'middle'); // 竖直居中,在某些浏览器中可能需要其他值,比如 'central' // 将先前创建的SVG矩形元素(this.rectElement) 添加为 this.svgElement 的子元素 this.svgElement.appendChild(this.rectElement); // 将先前创建的SVG矩形元素(this.textElement) 添加为 this.svgElement 的子元素 this.svgElement.appendChild(textElement); // 将文本元素引用赋值给了类的成员变量 this.textElement,这样后续可以通过 this.textElement 直接访问和操作这个文本元素,比如设置文本内容、 arrowHead.setAttribute('points', [`${x2},${y2}`, `${headX1},${headY1}`, `${headX2},${headY2}`].join(' ')); //设置箭头头部多边形的填充颜色,使其与线段颜色一致。svgElement容纳新创建的矩形框、