准备开发一个应用,需要给新用户自动生成一个默认头像,像本论坛采用 Discourse 那样,采用首字符 + 随机背景。
假如像 Discourse 那样 ImageMagick 之类的图片生成库的话,得用特定的中文字体,想到 SVG 图片是 XML 代码,很容易生成,但是文字怎么居中呢?水平 + 垂直方向都需要居中
我注意到腾讯云的控制面板就是采用 SVG 方案,不知道它是怎么实现的?
这头像是服务器端还是浏览器生成的?
字体是怎么选?不同系统的默认中文字体不一样
x=“18.5” y=“25.5” 坐标是如何计算的?我看了【徐】占 33x46,(70 - 33) / 2 = 18.3 能解释 x,但 (70 - 46) / 2 = 12,怎么解释 y?
难道每一个汉字在 Pingfang SC 中都是同样长宽比?33x46
<svg width="70" height="70" viewBox="0 0 38 38" fill="none"
xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="36" height="36" rx="18" fill="#3C89DD"></rect>
<text fill="#ffffff"
x="18.5"
y="25.5"
font-family="PingFang SC"
font-size="18"
font-weight="500"
style="text-anchor: middle;"
>徐</text>
文本的 x/y 坐标确实有点费解。
不过这里的 width="70" height="70"
不重要(如楼上所说,改成 700 也不影响居中),关键是 viewBox="0 0 38 38"
,它确定了一个 38x38 的正方形(没有单位,无极放大)。
rect 在正方形内居中画了一个直径 36 的圆。
text 看不太懂了,汉字高大于宽,y 坐标应该更小才是。
另外,其实 text 并不完全居中(19(38/2) 更接近居中),加一个小的同心圆就看得很清楚了:
svg-text-x-y623×693 31.4 KB
文本的默认 (x,y)
基准点不是左上角,而是文本的 (left, baseline)
,腾讯头像的文字对齐是 text-anchor: middle;
作用的结果,把这句删了,再画了几条辅助线就一目了然了:
圆心的坐标 (19,19)
。
文本 y 坐标是对齐的是默认 baseline。
<svg width="70" height="70" viewBox="0 0 38 38" fill="none" style="border:1px solid #cd0000;" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="36" height="36" rx="18" fill="#3C89DD"></rect>
<rect x="8" y="8" width="22" height="22" rx="11" style="fill:#cd0000;stroke:#cd0000;stroke-width:0.5;"></rect>
<rect x="0" y="0" width="19" height="19" style="fill:none;stroke:blue;stroke-width:0.5;"></rect>
<rect x="0" y="19" width="19" height="19" style="fill:none;stroke:blue;stroke-width:0.5;"></rect>
<rect x="19" y="0" width="19" height="19" style="fill:none;stroke:blue;stroke-width:0.5;"></rect>
<rect x="19" y="19" width="19" height="19" style="fill:none;stroke:blue;stroke-width:0.5;"></rect>
<text fill="#ffffff"
x="19"
y="19"
font-family="PingFang SC"
font-size="18"
font-weight="500"
>徐</text>
比起用绝对坐标,百分比可能是更好的选择。而且如果想要垂直方向对齐,必需把 baseline 往中间推:
svg-text-baseline-2806×661 46.1 KB
<svg width="70" height="70" viewBox="0 0 38 38" fill="none" style="border:1px solid #cd0000;" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="36" height="36" rx="18" fill="#3C89DD"></rect>
<rect x="8" y="8" width="22" height="22" rx="11" style="fill:#cd0000;stroke:#cd0000;stroke-width:0.5;"></rect>
<rect x="0" y="0" width="19" height="19" style="fill:none;stroke:blue;stroke-width:0.5;"></rect>
<rect x="0" y="19" width="19" height="19" style="fill:none;stroke:blue;stroke-width:0.5;"></rect>
<rect x="19" y="0" width="19" height="19" style="fill:none;stroke:blue;stroke-width:0.5;"></rect>
<rect x="19" y="19" width="19" height="19" style="fill:none;stroke:blue;stroke-width:0.5;"></rect>
<text fill="#ffffff"
x="50%"
y="50%"
font-family="PingFang SC"
font-size="18"
font-weight="500"
dominant-baseline="middle"
style="text-anchor: middle;"
>徐</text>
y 坐标看起来还是有点偏上,51% 可能效果会更好。
我也是趁着这个问题自己顺便学习了一些基本的 svg 知识,总结起来主要有:
svg 标签的 width
和 height
定义的是画布绝对大小。
viewBox 定义的是逻辑上的大小,也就是说它可以随画布放大缩小。所以应该以 viewBox 的大小来摆放元素。
text 对齐的关键因素是 baseline 和 text-anchor 属性。