准备开发一个应用,需要给新用户自动生成一个默认头像,像本论坛采用 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">
<g>
<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>
</g>
</svg>
wsug
2
好办法,不会svg,不过我把你的代码复制过来,把width="70" height="70"
值改成700,放大以后文字也是居中显示的。
我看Discourse(本站)默认头像只显示一个字母,这样好像也不需要ImageMagick 之类的图片生成库,只要26张图片就可以了,但对于中文用户肯定是不行的。
1 个赞
文本的 x/y 坐标确实有点费解。
不过这里的 width="70" height="70"
不重要(如楼上所说,改成 700 也不影响居中),关键是 viewBox="0 0 38 38"
,它确定了一个 38x38 的正方形(没有单位,无极放大)。
rect 在正方形内居中画了一个直径 36 的圆。
text 看不太懂了,汉字高大于宽,y 坐标应该更小才是。
另外,其实 text 并不完全居中(19(38/2) 更接近居中),加一个小的同心圆就看得很清楚了:
1 个赞
文本的默认 (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">
<g>
<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>
</g>
</svg>
比起用绝对坐标,百分比可能是更好的选择。而且如果想要垂直方向对齐,必需把 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">
<g>
<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>
</g>
</svg>
y 坐标看起来还是有点偏上,51% 可能效果会更好。
我也是趁着这个问题自己顺便学习了一些基本的 svg 知识,总结起来主要有:
- svg 标签的
width
和 height
定义的是画布绝对大小。
- viewBox 定义的是逻辑上的大小,也就是说它可以随画布放大缩小。所以应该以 viewBox 的大小来摆放元素。
- text 对齐的关键因素是 baseline 和 text-anchor 属性。
3 个赞