不改变文档结构实时渲染彩虹字
本帖最后由 马黑黑 于 2024-6-16 12:18 编辑 <br /><br /><style>#t7 { margin: 20px auto; padding: 10px; width: 740px; height: 360px; font-size: 20px; background: white; -webkit-user-modify: read-write-plaintext-only; border: 1px solid lightblue; border-radius: 3px; outline-width: 4px; outline-color: cornflowerblue; }
#h7 { text-align: center; font-size: 2em; }
.mum { position: relative; margin: 0; padding: 10px; font: normal 16px/20px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; color: black; background: rgba(240, 240, 240,.95); box-shadow: 2px 2px 4px gray; border: thick groove lightblue; border-radius: 6px; }
.mum ::selection { background-color: rgba(0,100,100,.35); }
.mum div { margin: 0; padding: 0; }
.mum cl-cd { display: block; position: relative; margin: 0 0 0 50px; padding: 0 0 0 10px; white-space: pre-wrap; overflow-wrap: break-word; border-left: 1px solid silver; }
.mum cl-cd::before { position: absolute; content: attr(data-idx); width: 50px; color: gray; text-align: right; transform: translate(-70px); }
.tRed { color: red; }
.tBlue { color: blue; }
.tGreen { color: green; }
.tDarkRed { color: darkred; }
.tMagenta { color: magenta; }
</style>
<h2 id="h7">CSS+JS原生文本高亮API测试</h2>
<div id="t7"></div>
<p>代码:<br><br></p>
<div class='mum'>
<cl-cd data-idx="1"><<span class="tDarkRed">style</span>></cl-cd>
<cl-cd data-idx="2"> #t7 { <span class="tBlue">margin:</span> 20px auto; <span class="tBlue">padding:</span> 10px; <span class="tBlue">width:</span> 800px; <span class="tBlue">height:</span> 400px; <span class="tBlue">font-size:</span> 20px; <span class="tBlue">-webkit-user-modify:</span> read-write-plaintext-only; <span class="tBlue">border:</span> 1px solid lightblue; <span class="tBlue">border-radius:</span> 3px; <span class="tBlue">outline-width:</span> 4px; <span class="tBlue">outline-color:</span> cornflowerblue; }</cl-cd>
<cl-cd data-idx="3"> #h7 { <span class="tBlue">text-align:</span> center; }</cl-cd>
<cl-cd data-idx="4"><<span class="tDarkRed">/style</span>></cl-cd>
<cl-cd data-idx="5"> </cl-cd>
<cl-cd data-idx="6"><<span class="tDarkRed">h</span>2 <span class="tRed">id</span>=<span class="tMagenta">"h7"</span>>CSS+JS原生文本高亮API测试<<span class="tDarkRed">/h</span>2></cl-cd>
<cl-cd data-idx="7"><<span class="tDarkRed">div</span> <span class="tRed">id</span>=<span class="tMagenta">"t7"</span>><<span class="tDarkRed">/div</span>></cl-cd>
<cl-cd data-idx="8"> </cl-cd>
<cl-cd data-idx="9"><<span class="tDarkRed">script</span>></cl-cd>
<cl-cd data-idx="10"> </cl-cd>
<cl-cd data-idx="11"><span class="tBlue">const</span> highlights = [];</cl-cd>
<cl-cd data-idx="12"><span class="tBlue">const</span> addStyleSheet = () => {</cl-cd>
<cl-cd data-idx="13"> <span class="tBlue">const</span> colors = [<span class="tMagenta">'#ad26ad'</span>, <span class="tMagenta">'#5d0a99'</span>,<span class="tMagenta">'#0000ff'</span>,<span class="tMagenta">' #07c607'</span>, <span class="tMagenta">'#b3b308'</span>, <span class="tMagenta">'#ffa500'</span>, <span class="tMagenta">'#ff0000'</span>];</cl-cd>
<cl-cd data-idx="14"> <span class="tBlue">const</span> hstr = colors.map((c,k) => `::highlight(rainbow-color-${k+1}) {<span class="tBlue">color:</span> ${c}; <span class="tBlue">text-decoration:</span> underline; }`).join(<span class="tMagenta">'\n'</span>);</cl-cd>
<cl-cd data-idx="15"> <span class="tBlue">var</span> style = <span class="tRed">document</span>.createElement(<span class="tMagenta">'style'</span>);</cl-cd>
<cl-cd data-idx="16"> style.type = <span class="tMagenta">'text/css'</span>;</cl-cd>
<cl-cd data-idx="17"> style.innerHTML = hstr;</cl-cd>
<cl-cd data-idx="18"> <span class="tRed">document</span>.body.appendChild(style);</cl-cd>
<cl-cd data-idx="19"> </cl-cd>
<cl-cd data-idx="20"> <span class="tBlue">for</span> (<span class="tBlue">let</span> i = 0; i < 7; i++) {</cl-cd>
<cl-cd data-idx="21"> <span class="tBlue">const</span> colorHighlight = <span class="tBlue">new</span> Highlight();</cl-cd>
<cl-cd data-idx="22"> highlights.push(colorHighlight);</cl-cd>
<cl-cd data-idx="23"> CSS.highlights.set(`rainbow-color-${i + 1}`, colorHighlight);</cl-cd>
<cl-cd data-idx="24"> }</cl-cd>
<cl-cd data-idx="25">};</cl-cd>
<cl-cd data-idx="26"> </cl-cd>
<cl-cd data-idx="27"><span class="tBlue">const</span> hlight = (ele) => {</cl-cd>
<cl-cd data-idx="28"> <span class="tBlue">const</span> walker = <span class="tRed">document</span>.createTreeWalker(ele, NodeFilter.SHOW_TEXT);</cl-cd>
<cl-cd data-idx="29"> <span class="tBlue">while</span>(walker.nextNode()) {</cl-cd>
<cl-cd data-idx="30"> <span class="tBlue">let</span> textNode = walker.currentNode;</cl-cd>
<cl-cd data-idx="31"> <span class="tBlue">let</span> text = textNode.textContent;</cl-cd>
<cl-cd data-idx="32"> <span class="tBlue">for</span>(<span class="tBlue">let</span> i = 0; i < text.length; i++) {</cl-cd>
<cl-cd data-idx="33"> <span class="tBlue">const</span> range = <span class="tBlue">new</span> Range();</cl-cd>
<cl-cd data-idx="34"> range.setStart(textNode, i);</cl-cd>
<cl-cd data-idx="35"> range.setEnd(textNode, i + 1);</cl-cd>
<cl-cd data-idx="36"> highlights[(i % 7)].add(range);</cl-cd>
<cl-cd data-idx="37"> }</cl-cd>
<cl-cd data-idx="38"> }</cl-cd>
<cl-cd data-idx="39">};</cl-cd>
<cl-cd data-idx="40"> </cl-cd>
<cl-cd data-idx="41"><span class="tBlue">if</span> (CSS.highlights) {</cl-cd>
<cl-cd data-idx="42"> t7.textContent = <span class="tMagenta">'恭喜恭喜!您的浏览器完美支持CSS Custom Highlight API'</span>;</cl-cd>
<cl-cd data-idx="43"> addStyleSheet();</cl-cd>
<cl-cd data-idx="44"> hlight(h7);</cl-cd>
<cl-cd data-idx="45"> hlight(t7);</cl-cd>
<cl-cd data-idx="46"> t7.oninput = () => hlight(t7);</cl-cd>
<cl-cd data-idx="47">} <span class="tBlue">else</span> {</cl-cd>
<cl-cd data-idx="48"> t7.textContent = <span class="tMagenta">'非常遗憾!您的浏览器不支持CSS Custom Highlight API'</span></cl-cd>
<cl-cd data-idx="49">}</cl-cd>
<cl-cd data-idx="50"> </cl-cd>
<cl-cd data-idx="51"><<span class="tDarkRed">/script</span>></cl-cd>
</div>
<script>
(function() {
const highlights = [];
const addStyleSheet = () => {
const colors = ['#ad26ad', '#5d0a99','#0000ff',' #07c607', '#b3b308', '#ffa500', '#ff0000'];
const hstr = colors.map((c,k) => `::highlight(rainbow-color-${k+1}) {color: ${c}; text-decoration: underline; }`).join('\n');
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = hstr;
document.body.appendChild(style);
for (let i = 0; i < 7; i++) {
const colorHighlight = new Highlight();
highlights.push(colorHighlight);
CSS.highlights.set(`rainbow-color-${i + 1}`, colorHighlight);
}
};
const hlight = (ele) => {
const walker = document.createTreeWalker(ele, NodeFilter.SHOW_TEXT);
while(walker.nextNode()) {
let textNode = walker.currentNode;
let text = textNode.textContent;
for(let i = 0; i < text.length; i++) {
const range = new Range();
range.setStart(textNode, i);
range.setEnd(textNode, i + 1);
highlights[(i % 7)].add(range);
}
}
};
if (CSS.highlights) {
t7.textContent = '恭喜恭喜!您的浏览器完美支持CSS Custom Highlight API';
addStyleSheet();
hlight(h7);
hlight(t7);
t7.oninput = () => hlight(t7);
} else {
t7.textContent = '非常遗憾!您的浏览器不支持CSS Custom Highlight API'
}
})();
</script>
本帖最后由 马黑黑 于 2024-6-16 12:22 编辑
如果浏览器支持新的文本高亮渲染方式,一楼的测试中,彩虹字文本框可以输入文本,新输入的文本一样是彩虹的。
CSS Custom Highlight API 是个较新的标准接口,它提供一种全新理念的文本高亮特效,不改变文档树的结构,仅需事先定义好一组伪元素 ::highlight(名称)、再通过JS建立和注册文本高亮设定,便可对特定文本进行高亮渲染。目前火狐浏览器(Firefox)还没有能够实现该功能,其他现代浏览器新版本均已支持。
使用 CSS Custom Highlight API 有点繁琐,它需要一系列的配套操作,包含但不限于CSS的设置、创建高亮并在页面中注册、遍历文本节点、创建选区等等操作。 传统的文本着色实现方法,都是以改变文档结构的方式完成,例如下面的文字:
花潮论坛
花潮两字都上彩,实现手段类似于:
<span style="color: red">花</span><span style="magenta">潮</span>论坛
文本节点中加入了两 span 元素节点,通过改变文档结构来实现给文本着色。
而 CSS Custom Highlight API 无需这么做,所以渲染性能提升100倍不止。 ::highlight() 伪元素支持的CSS属性有;
color
background-color
text-decoration 及其相关属性
text-shadow
-webkit-text-stroke-color、-webkit-text-fill-color 和 -webkit-text-stroke-width CSS Custom Highlight API 实现流程:
一、定义伪元素 ::highligh(custom-name) 样式
二、创建选区
三、创建高亮
四、注册高亮(到 custom-name 样式 )
其中,创建选区要遍历文档节点,找出要高亮的所有文本节点,而后一一为其创建高亮并注册(指定高亮样式)。 去试过了,首层的文本框里可以输入问题,一边输入一边就看到了颜色的变化,真神奇{:4_187:} 感谢黑黑又带来了好东西新东西{:4_199:} 火狐不行,非常遗憾!您的浏览器不支持CSS Custom Highlight API
别的行。。恭喜恭喜!您的浏览器完美支持CSS Custom Highlight API
火狐落后了啊。。 南无月 发表于 2024-6-16 11:42
火狐不行,非常遗憾!您的浏览器不支持CSS Custom Highlight API
别的行。。恭喜恭喜!您的浏览器完美支持 ...
火狐对 ::highlight() 伪元素的支持是局部支持,而对API完全没有支持。继续等待。 红影 发表于 2024-6-16 11:41
感谢黑黑又带来了好东西新东西
这个很新,Chrome 从 105 版本才开始支持 红影 发表于 2024-6-16 11:41
去试过了,首层的文本框里可以输入问题,一边输入一边就看到了颜色的变化,真神奇
这是w3c推出的新理念,非常先进 马黑黑 发表于 2024-6-16 12:15
火狐对 ::highlight() 伪元素的支持是局部支持,而对API完全没有支持。继续等待。
好哒,这个挺稀罕的。。{:4_173:}觉得火狐还挺先进的,怎么这块却没跟上 马黑黑 发表于 2024-6-16 12:16
这个很新,Chrome 从 105 版本才开始支持
真是好东西啊,黑黑带来的好东西走在了最前列了{:4_199:} 马黑黑 发表于 2024-6-16 12:17
这是w3c推出的新理念,非常先进
非常神奇的体验,这个太棒了{:4_187:} 红影 发表于 2024-6-16 22:05
非常神奇的体验,这个太棒了
彩虹字过去早就有的,只是现在这个API,确实令人惊叹 红影 发表于 2024-6-16 22:04
真是好东西啊,黑黑带来的好东西走在了最前列了
还好吧。对这个的介绍,多少有点犹豫,主要是考虑它的兼容性方面 马黑黑 发表于 2024-6-16 22:15
彩虹字过去早就有的,只是现在这个API,确实令人惊叹
是的,它的七彩色非常漂亮{:4_187:} 马黑黑 发表于 2024-6-16 22:16
还好吧。对这个的介绍,多少有点犹豫,主要是考虑它的兼容性方面
还好,应该大多数人的浏览器都没问题的。 红影 发表于 2024-6-17 17:45
还好,应该大多数人的浏览器都没问题的。
不见得的额。很多人都不升级浏览器,包括不少玩音画代码的。 红影 发表于 2024-6-17 17:42
是的,它的七彩色非常漂亮
不错