如何在Sigma v2中动态设置/修改边的箭头尺寸?
Sigma v2(WebGL)动态控制箭头尺寸方案
Sigma v2改用WebGL渲染后,v1里通过minArrowSize控制箭头尺寸的方法已经失效。要实现箭头尺寸独立于边的动态调整,得从自定义渲染程序入手,下面是具体步骤:
1. 自定义支持动态箭头厚度的ArrowEdgeProgram
你看到的静态方案是硬编码thickness值,要动态控制,我们可以继承原ArrowEdgeProgram,新增一个uniform变量来接收外部传入的厚度值:
import { ArrowEdgeProgram } from "@sigma/core"; import { float } from "shader-composer"; class DynamicArrowEdgeProgram extends ArrowEdgeProgram { // 扩展uniform,添加动态箭头厚度变量 static override getUniforms() { return { ...super.getUniforms(), arrowThickness: float("arrowThickness"), }; } // 重写顶点着色器,用自定义uniform替换固定的thickness值 static override vertexShader() { return /* glsl */ ` ${super.vertexShader()} // 替换原固定厚度计算 float thickness = arrowThickness; `; } }
2. 在React组件中动态控制箭头尺寸
通过useSigma获取Sigma实例,然后用setUniform方法动态修改箭头厚度,还可以配合UI组件(比如滑块)让用户直接调整:
import { useSigma } from "@sim51/react-sigma"; import { useState, useEffect } from "react"; export default function GraphComponent(props) { // 存储当前箭头尺寸,初始值设为10 const [arrowSize, setArrowSize] = useState(10); const sigmaInstance = useSigma(); // 箭头尺寸变化时更新uniform useEffect(() => { if (sigmaInstance) { sigmaInstance.setUniform("arrowThickness", arrowSize); } }, [sigmaInstance, arrowSize]); return ( <> {/* 用户控制滑块 */} <div style={{ padding: "10px" }}> 箭头尺寸: <input type="range" min="5" max="30" value={arrowSize} onChange={(e) => setArrowSize(Number(e.target.value))} /> <span>{arrowSize}</span> </div> <SigmaContainer settings={{ nodeProgramClasses: { image: getNodeProgramImage(), circle: CircleNodeProgram }, edgeProgramClasses: { arrow: DynamicArrowEdgeProgram, // 使用自定义渲染程序 }, ...graphSettings, }} style={{ height: '100%', background: props.noBackground ? 'white' : mainBackgroundColor }} > {/* 你的图数据节点/边组件 */} </SigmaContainer> </> ); }
原代码失效原因
- Sigma v2的WebGL渲染架构完全重写,v1的
minArrowSize配置已被移除,写在settings里不会被识别。 - 原代码只是注册了默认的
ArrowEdgeProgram,没有修改其内部的厚度变量,自然无法改变箭头大小。
进阶:给不同边设置不同箭头尺寸
如果需要每条边的箭头尺寸独立,可以把厚度值存在边的data字段里(比如edge.data.arrowThickness),然后修改自定义Program的着色器,从边的属性中读取对应值:
// 在DynamicArrowEdgeProgram中修改 static override fragmentShader() { return /* glsl */ ` ${super.fragmentShader()} // 从edgeAttributes读取自定义厚度 float thickness = edgeAttributes.aThickness; `; } static override getAttributes() { return { ...super.getAttributes(), aThickness: float("aThickness"), }; } // 同时在边的数据中添加arrowThickness字段,Sigma会自动映射为aThickness
内容的提问来源于stack exchange,提问作者Mohamed Baher
相关产品推荐
相关产品推荐

