差不多一年后,我重新审视了这个问题,并且我找到了一个使用 SVG 的更令人满意(虽然更冗长)的解决方案。基本上,这与我之前基于 HTML/CSS 的版本类似,但 SVG 使您能够对底层基本字符的抗锯齿边缘进行剪辑/屏蔽。
剩下的唯一真正问题是如何处理覆盖字符(组合字符直接呈现在底层字符之上)。在这种情况下,您要么需要在覆盖层顶部呈现基本字符(在我的用例中不推荐),要么将覆盖层呈现在不一定完全匹配基本字符宽度的占位符空白字符上。这是一个演示:
svg text {
x: 50px;
y: 50px;
alignment-baseline: middle;
text-anchor: middle;
font-size: 55px;
}
svg .backdrop {
x: 1px;
y: 1px;
rx: 15px;
ry: 15px;
width: 98px;
height: 98px;
fill: url(#grad);
}
svg .cc-above { fill: #F00; }
svg .cc-below { fill: #00F; }
svg .cc-overlay { fill: #0FF; }
svg .cc-base { fill: #000; }
svg .cc-mask { stroke: #000; stroke-width: 3px; }
.sample { float: left; }
.caption { display: block; text-align: center; }
<div class="sample">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100px" height="100px" viewBox="0 0 100 100">
<defs>
<text id="base" x="50" y="50">e</text>
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#DDD;stop-opacity:1" />
<stop offset="100%" style="stop-color:#888;stop-opacity:1" />
</linearGradient>
</defs>
<rect class="backdrop" />
<mask id="mask1">
<rect x="0" y="0" width="100%" height="100%" fill="#fff" />
<use xlink:href="#base" class="cc-mask" />
</mask>
<text class="cc-above" x="50%" y="50%" mask="url(#mask1)">è</text>
<use xlink:href="#base" class="cc-base" />
</svg>
<div class="caption">Above</div>
</div>
<div class="sample">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100px" height="100px" viewBox="0 0 100 100">
<defs>
<text id="base" x="50" y="50">e</text>
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#DDD;stop-opacity:1" />
<stop offset="100%" style="stop-color:#888;stop-opacity:1" />
</linearGradient>
</defs>
<rect class="backdrop" />
<mask id="mask1">
<rect x="0" y="0" width="100%" height="100%" fill="#fff" />
<use xlink:href="#base" class="cc-mask" />
</mask>
<text class="cc-below" x="50%" y="50%" mask="url(#mask1)">e̟</text>
<use xlink:href="#base" class="cc-base" />
</svg>
<div class="caption">Below</div>
</div>
<div class="sample">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100px" height="100px" viewBox="0 0 100 100">
<defs>
<text id="base" x="50" y="50">e</text>
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#DDD;stop-opacity:1" />
<stop offset="100%" style="stop-color:#888;stop-opacity:1" />
</linearGradient>
</defs>
<rect class="backdrop" />
<mask id="mask1">
<rect x="0" y="0" width="100%" height="100%" fill="#fff" />
<use xlink:href="#base" class="cc-mask" />
</mask>
<use xlink:href="#base" class="cc-base" />
<text class="cc-overlay" x="50%" y="50%"> ̴</text>
</svg>
<div class="caption">Overlay</div>
</div>
<div class="sample">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100px" height="100px" viewBox="0 0 100 100">
<defs>
<text id="base" x="50" y="50">e</text>
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#DDD;stop-opacity:1" />
<stop offset="100%" style="stop-color:#888;stop-opacity:1" />
</linearGradient>
</defs>
<rect class="backdrop" />
<mask id="mask1">
<rect x="0" y="0" width="100%" height="100%" fill="#fff" />
<use xlink:href="#base" class="cc-mask" />
</mask>
<text class="cc-above" x="50%" y="50%" mask="url(#mask1)">è</text>
<text class="cc-below" x="50%" y="50%" mask="url(#mask1)">e̟</text>
<use xlink:href="#base" class="cc-base" />
<text class="cc-overlay" x="50%" y="50%"> ̴</text>
</svg>
<div class="caption">All</div>
</div>
我对 SVG 没有太多经验,有经验的人可能会找到进一步改进此解决方案的方法。