我正在做的开源项目:du-editor,一个基于X6的图编辑器


要在 X6 中实现手绘/素描风格,核心是 SVG 滤镜 (Filter) 和 SVG 填充模式 (Pattern) 。X6 的节点和边都基于 SVG,因此我们可以充分利用 SVG 的强大功能来创建这种独特的视觉效果。
这种风格主要包含三个要素:
- 抖动、不规则的边框 :这通过 SVG 的
feTurbulence
和feDisplacementMap
滤镜实现。 - 阴影线填充效果 :这通过 SVG 的
<pattern>
元素创建可平铺的填充图案来实现。 - 手写体字体:选择一个合适的手写风格字体
第 1 步:定义 SVG 滤镜和填充模式
首先,需要在你的 HTML 文件中,通常是在图表容器 <div>
的旁边,定义好我们需要的 SVG 资源。我们将它们放在一个 <svg>
标签的 <defs>
元素中,这样 X6 就可以通过 ID 引用它们。
HTML
ini
<div id="container"></div>
<svg width="0" height="0">
<defs>
<filter id="filter-sketch">
<feTurbulence
type="fractalNoise"
baseFrequency="0.01"
numOctaves="5"
result="noise"
/>
<feDisplacementMap
in="SourceGraphic"
in2="noise"
scale="5"
xChannelSelector="R"
yChannelSelector="G"
result="displaced"
/>
</filter>
<pattern
id="pattern-hatch"
patternUnits="userSpaceOnUse"
width="8"
height="8"
patternTransform="rotate(45)"
>
<path
d="M -1,1 l 2,-2 M 0,8 l 8,-8 M 7,9 l 2,-2"
stroke="#c58d6a"
stroke-width="1"
/>
</pattern>
</defs>
</svg>
-
<filter id="filter-sketch">
:feTurbulence
: 用于生成一种叫做 "Perlin noise" 的伪随机噪点图。baseFrequency
控制噪点的"波纹"大小,值越小,线条抖动越平缓。numOctaves
决定了细节层次。feDisplacementMap
: 将上面生成的噪点图应用到原始图形上,使其像素发生位移,从而产生抖动的"手绘"效果。scale
属性控制抖动的剧烈程度,是调整效果最关键的参数。
-
<pattern id="pattern-hatch">
:- 我们创建了一个 8x8 像素大小的单元格,并将其旋转了 45 度。
- 在单元格内部,我们用
<path>
画了几条斜线。 - 这个 pattern 会像瓷砖一样自动平铺,以填充整个形状。你可以通过修改
width
,height
和<path>
的stroke-width
来调整阴影线的密度和粗细。
第 2 步:在 X6 中注册自定义节点和样式
接下来,我们在 X6代码中注册新的节点,并在其 attrs
中引用上面定义的滤镜和填充。
JavaScript
// 准备好图表实例
const graph = new Graph({
container: document.getElementById('container'),
// ... 其他配置
});
// --- 注册手绘风格的节点 ---
// 1. 手绘风格 - 圆角矩形 (对应图片右侧的形状)
Graph.registerNode('sketch-rect', {
inherit: 'rect', // 继承自矩形
attrs: {
body: {
// 关键样式
stroke: '#a26740',
strokeWidth: 2,
fill: 'url(#pattern-hatch)', // 使用阴影线填充
filter: 'url(#filter-sketch)', // 应用手绘滤镜
},
label: {
// 推荐使用手写体
fontFamily: '"Comic Sans MS", "Caveat", cursive',
fill: '#a26740',
fontSize: 14,
},
},
});
// 2. 手绘风格 - 菱形 (对应图片左侧的形状)
// 菱形需要自定义 SVG 路径
const diamondPath = 'M 30 0 L 60 30 L 30 60 L 0 30 Z';
Graph.registerNode('sketch-diamond', {
inherit: 'path', // 继承自路径
width: 60,
height: 60,
attrs: {
body: {
// 关键样式
refD: diamondPath,
stroke: '#a26740',
strokeWidth: 2,
fill: 'url(#pattern-hatch)',
filter: 'url(#filter-sketch)',
},
label: {
fontFamily: '"Comic Sans MS", "Caveat", cursive',
fill: '#a26740',
fontSize: 14,
},
},
});
第 3 步:配置边的样式
边的样式也需要应用相同的滤镜,可以在图表初始化配置中统一设置。
JavaScript
const graph = new Graph({
container: document.getElementById('container'),
grid: true,
// ...
// --- 配置边的连接样式 ---
connecting: {
router: 'manhattan',
createEdge() {
return new Shape.Edge({
attrs: {
line: {
stroke: '#a26740',
strokeWidth: 2,
filter: 'url(#filter-sketch)', // 为边线应用滤镜
targetMarker: {
name: 'block', // 箭头样式
width: 12,
height: 8,
// 注意:需要给箭头也加上滤镜和填充/描边
attrs: {
filter: 'url(#filter-sketch)',
}
},
},
},
});
},
},
});
效果调整
可以实现一个完整的手绘风格主题。如果你想微调效果,可以重点关注:
- 抖动程度 :修改
<filter>
中的scale
值。值越大,抖动越厉害。 - 阴影密度 :修改
<pattern>
的width
,height
和内部<path>
的stroke-width
。 - 颜色 :直接在 X6 节点的
attrs
中修改stroke
和fill
颜色,以及在<pattern>
中修改stroke
颜色。 - 字体 :为了更好的效果,你可以通过 CSS 引入一些免费的在线手写字体,例如 Google Fonts 上的 Caveat 或 Patrick Hand。