JS + CSS 实现高亮关键词(不侵入DOM)

2024-01-28 11:30

本文主要是介绍JS + CSS 实现高亮关键词(不侵入DOM),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前在做关键词检索高亮功能的时候,研究了下目前前端实现高亮的几种方式,第一就是替换dom元素实现高亮,第二就是利用浏览器新特性Css.highlights结合js选区与光标与CSS高亮伪类实现,实现功能如下:

一、页面布局

一个搜索框,其余要检索关键词的文字,并且给搜索框添加change事件
在这里插入图片描述

二、实现选区

利用TreeWalker遍历遍历DOM结构,通过nextNode()方法,拿到所有文本节点数据,保存到数组里,为接下来的搜索做铺垫

let wrap = document.querySelector('.content')// 创建 createTreeWalker 迭代器,用于遍历文本节点,保存到一个数组const treeWalker = document.createTreeWalker(wrap, NodeFilter.SHOW_TEXT);const allTextNodes = [];let currentNode = treeWalker.nextNode();while (currentNode) {allTextNodes.push(currentNode);currentNode = treeWalker.nextNode();}

可以看到,到这一步,拿到所有文本节点数据
在这里插入图片描述
接下来,我们根据搜索的结果,拿到匹配到的dom节点内容的位置信息这里处理下英文小写,这里要注意,可能每句话会出现多次关键词,这里的indexOf要拼开始检索的参数,开始检索的参数这里记录下,也就是上一个检索关键词的结尾

let search = document.getElementById('search')search.onchange = event => {let value = event.target.value // 获取关键词let indices = []; // 位置信息const ranges = allTextNodes.map((el) => {// 英文全部小写return { el, text: el.textContent.toLowerCase() };}).map(({ text, el }) => {// 拿到匹配到dom节点的位置信息,并且保存为数组while (startPos < text.length) {let startPos = 0while (startPos < text.length) {const index = text.indexOf(value, startPos);if (index === -1) breakindices.push({el,start: index,end: index + value.length});startPos = index + value.length;}} });
}

我们可以看下位置信息结果
在这里插入图片描述
接下来,创建选区,进行高亮,这里用到了Highlight,用法如下:Highlight(range1, range2, range3)

// 根据搜索词的位置创建选区
let result = indices.map(item => {let range = new Range();range.setStart(item.el, item.start);range.setEnd(item.el, item.end);return range
});// 创建高亮对象
const searchResultsHighlight = new Highlight(...result);// 注册高亮
CSS.highlights.set("search-results", searchResultsHighlight);

添加css highlight样式:

.content .item::highlight(search-results) {background-color: #ffff00;color: #000;
}

可以看下效果,基本成型,但是当我们切换的时候,上一次的检索结果还在,需要清除高亮记录

// 清除上个高亮
CSS.highlights.clear();

在这里插入图片描述

三、完整代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>CSS高亮</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}.container {width: 100vw;height: 100vh;padding-top: 20px;}.search {width: 100%;padding: 10px 0;display: flex;align-items: center;justify-content: center;}.search input {width: 500px;height: 35px;border: 1px #999 solid;outline: 0;background-color: #fff;border-radius: 3px;padding-left: 10px;}.content {width: 100%;padding: 30px;}.content .item {width: 100%;font-size: 16px;color: #000;margin-bottom: 10px;line-height: 30px;user-select: none;letter-spacing: 0.5px;}.content .item::highlight(search-results) {background-color: #ffff00;color: #000;}</style>
</head>
<body>
<div class="container"><div class="search"><input id="search" type="text" placeholder="输入关键词检索" /></div><div class="content"><div class="item">1、朱自清《荷塘月色》片段路上只我一个人,背着手踱着。这一片天地好像是我的;我也像超出了平常旳自己,到了另一世界里。我爱热闹,也爱冷静;爱群居,也爱独处。像今晚上,一个人在这苍茫旳月下,什么都可以想,什么都可以不想,便觉是个自由的人。白天里一定要做的事,一定要说的话,现在都可不理。这是独处的妙处,我且受用这无边的荷香月色好了。曲曲折折的荷塘上面,弥望旳是田田的叶子。叶子出水很高,像亭亭旳舞女旳裙。层层的叶子中间,零星地点缀着些白花,有袅娜(niǎo,nuó)地开着旳,有羞涩地打着朵儿旳;正如一粒粒的明珠,又如碧天里的星星,又如刚出浴的美人。微风过处,送来缕缕清香,仿佛远处高楼上渺茫的歌声似的。这时候叶子与花也有一丝的颤动,像闪电般,霎时传过荷塘的那边去了。叶子本是肩并肩密密地挨着,这便宛然有了一道凝碧的波痕。叶子底下是脉脉()的流水,遮住了,不能见一些颜色;而叶子却更见风致了。月光如流水一般,静静地泻在这一片叶子和花上。薄薄的青雾浮起在荷塘里。叶子和花仿佛在牛乳中洗过一样;又像笼着轻纱的梦。虽然是满月,天上却有一层淡淡的云,所以不能朗照;但我以为这恰是到了好处——酣眠固不可少,小睡也别有风味的。月光是隔了树照过来的,高处丛生的灌木,落下参差的斑驳的黑影,峭楞楞如鬼一般;弯弯的杨柳的稀疏的倩影,却又像是画在荷叶上。塘中的月色并不均匀;但光与影有着和谐的旋律,如梵婀(ē)(英语violin小提琴的译音)上奏着的名曲。荷塘的四面,远远近近,高高低低都是树,而杨柳最多。这些树将一片荷塘重重围住;只在小路一旁,漏着几段空隙,像是特为月光留下的。树色一例是阴阴的,乍看像一团烟雾;但杨柳的丰姿,便在烟雾里也辨得出。树梢上隐隐约约的是一带远山,只有些大意罢了。树缝里也漏着一两点路灯光,没精打采的,是渴睡人的眼。这时候最热闹的,要数树上的蝉声与水里的蛙声;但热闹是它们的,我什么也没有。</div><div class="item">2、鲁迅《从百草园到三味书屋》片段不必说碧绿的菜畦,光滑的石井栏,高大的皂荚树,紫红的桑椹;也不必说鸣蝉在树叶里长吟,肥胖的黄蜂伏在菜花上,轻捷的叫天子(云雀)忽然从草间直窜向云霄里去了。单是周围的短短的泥墙根一带,就有无限趣味。油蛉在这里低唱,蟋蟀们在这里弹琴。翻开断砖来,有时会遇见蜈蚣;还有斑蝥,倘若用手指按住它的脊梁,便会拍的一声,从后窍喷出一阵烟雾。何首乌藤和木莲藤缠络着,木莲有莲房一般的果实,何首乌有拥肿的根。有人说,何首乌根是有象人形的,吃了便可以成仙,我于是常常拔它起来,牵连不断地拔起来,也曾因此弄坏了泥墙,却从来没有见过有一块根象人样。如果不怕刺,还可以摘到覆盆子,象小珊瑚珠攒成的小球,又酸又甜,色味都比桑椹要好得远。</div><div class="item">3、陈从周《说园》片段园有静观、动观之分,这一点我们在造园之先,首要考虑。何谓静观,就是园中予游者多驻足的观赏点;动观就是要有较长的游览线。二者说来,小园应以静观为主,动观为辅,庭院专主静观。大园则以动观为主,静观为辅。前者如苏州网师园,后者则苏州拙政园差可似之。人们进入网师园宜坐宜留之建筑多,绕池一周,有槛前细数游鱼,有亭中待月迎风,而轩外花影移墙,峰峦当窗,宛然如画,静中生趣。至于拙政园径缘池转,廊引人随,与“日午画船桥下过,衣香人影太匆匆”的瘦西湖相仿佛,妙在移步换影,这是动观。立意在先,文循意出。动静之分,有关园林性质与园林面积大小。象上海正在建造的盆景园,则宜以静观为主,即为一例。中国园林是由建筑、山水、花木等组合而成的一个综合艺术品,富有诗情画意。叠山理水要造成“虽由人作,宛自天开”的境界。山与水的关系究竟如何呢?简言之,模山范水,用局部之景而非缩小(网师园水池仿虎丘白莲池,极妙),处理原则悉符画本。山贵有脉,水贵有源,脉源贯通,全园生动。我曾经用“水随山转,山因水活”与“溪水因山成曲折,山蹊随地作低平”来说明山水之间的关系,也就是从真山真水中所得到的启示。明末清初叠山家张南垣主张用平冈小陂、陵阜陂阪,也就是要使园林山水接近自然。如果我们能初步理解这个道理,就不至于离自然太远,多少能呈现水石交融的美妙境界。</div><div class="item">4、梁实秋《雅舍》片段“雅舍”最宜月夜——地势较高,得月较先。看山头吐月,红盘乍涌,一霎间,清光四射,天空皎洁,四野无声,微闻犬吠,坐客无不悄然!舍前有两株梨树,等到月升中天,清光从树间筛洒而下,地下阴影斑斓,此时尤为幽绝。直到兴阑人散,归房就寝,月光仍然逼进窗来,助我凄凉。细雨蒙蒙之际,“雅舍”亦复有趣。推窗展望,俨然米氏章法,若云若雾,一片弥漫。但若大雨滂沱,我就又惶悚不安了,屋顶浓印到处都有,起初如碗大,俄而扩大如盆,继则滴水乃不绝,终乃屋顶灰泥突然崩裂,如奇葩初绽,砉然一声而泥水下注,此刻满室狼藉,抢救无及。此种经验,已数见不鲜。</div><div class="item">5、冰心《图画》信步走下山门去,何曾想寻幽访胜?转过山坳来,一片青草地,参天的树影无际。树后弯弯的石桥,桥后两个俯蹲在残照里的狮子。回过头来,只一道的断瓦颓垣,剥落的红门,却深深掩闭。原来是故家陵阙!何用来感慨兴亡,且印下一幅图画。半山里,凭高下视,千百的燕子,绕着殿儿飞。城垛般的围墙,白石的甬道,黄绿琉璃瓦的门楼,玲珑剔透。楼前是山上的晚霞鲜红,楼后是天边的平原村树,深蓝浓紫。暮霭里,融合在一起。难道是玉宇琼楼?难道是瑶宫贝阙?何用来搜索诗肠,且印下一幅图画。低头走着,—首诗的断句,忽然浮上脑海来。“四月江南无矮树,人家都在绿阴中。”何用苦忆是谁的著作,何用苦忆这诗的全文。只此已描画尽了山下的人家!</div><div class="item">6、徐志摩《我所知道的康桥》片段康桥的灵性全在一条河上;康河,我敢说是全世界最秀丽的一条水。河的名字是葛兰大(Granta),也有叫康河(Kiver Cam)的,许有上下流的区别,我不甚清楚。河身多的是曲折,上游是有名的拜伦潭——“Byron’s Pool”——当年拜伦常在那里玩的;有一个老村子叫格兰骞斯德,有一个果子园,你可以躺在累累的桃李树荫下吃茶,花果会掉入你的茶杯,小雀子会到你桌上来啄食,那真是别有一番天地。这是上游;下游是从骞斯德顿下去,河面展开,那是春夏间竞舟的场所。上下河分界处有一个坝筑,水流急得很,在星光下听水声,听近村晚钟声,听河畔倦牛刍草声,是我康桥经验中最神秘的一种:大自然的优美、宁静,调谐在这星光与波光的默契中不期然的淹入了你的性灵。</div></div>
</div>
</body>
<script>let wrap = document.querySelector('.content')// 创建 createTreeWalker 迭代器,用于遍历文本节点,保存到一个数组const treeWalker = document.createTreeWalker(wrap, NodeFilter.SHOW_TEXT);const allTextNodes = [];let currentNode = treeWalker.nextNode();while (currentNode) {allTextNodes.push(currentNode);currentNode = treeWalker.nextNode();}let search = document.getElementById('search')search.onchange = event => {let value = event.target.value// 清除上个高亮CSS.highlights.clear();if (!value) {return}let indices = [] // 位置信息const ranges = allTextNodes.map((el) => {return { el, text: el.textContent.toLowerCase() };}).map(({ text, el }) => {let startPos = 0while (startPos < text.length) {const index = text.indexOf(value, startPos);if (index === -1) breakindices.push({el,start: index,end: index + value.length});startPos = index + value.length;}});// 根据搜索词的位置创建选区let result = indices.map(item => {let range = new Range();range.setStart(item.el, item.start);range.setEnd(item.el, item.end);return range});// 创建高亮对象const searchResultsHighlight = new Highlight(...result);// 注册高亮CSS.highlights.set("search-results", searchResultsHighlight);}
</script>
</html>
四、总结

以上就是关于 CSS Custom Highlight API 的使用方法:

  • 1. 获取文字节点 createTreeWalker()
  • 2. 创建选区 new Range()
  • 3. 创建高亮 new Highlight()
  • 4. 自定义样式 ::hightlight()**

highlight()自定义样式只兼容以下:

文本颜色 `color`
背景颜色 `background-color`
文本修饰 `text-decoration`
文本阴影 `text-shadow`
文本描边 `-webkit-text-stroke`
文本填充 `-webkit-text-fill-color`

以下是兼容性,比较差,目前谷歌只兼容 Chrome 105 以上

在这里插入图片描述

这篇关于JS + CSS 实现高亮关键词(不侵入DOM)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/Vue2018/article/details/135262195
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/653505

相关文章

IDEA如何实现远程断点调试jar包

《IDEA如何实现远程断点调试jar包》:本文主要介绍IDEA如何实现远程断点调试jar包的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录问题步骤总结问题以jar包的形式运行Spring Boot项目时报错,但是在IDEA开发环境javascript下编译

Python实现自动化Word文档样式复制与内容生成

《Python实现自动化Word文档样式复制与内容生成》在办公自动化领域,高效处理Word文档的样式和内容复制是一个常见需求,本文将展示如何利用Python的python-docx库实现... 目录一、为什么需要自动化 Word 文档处理二、核心功能实现:样式与表格的深度复制1. 表格复制(含样式与内容)2

python获取cmd环境变量值的实现代码

《python获取cmd环境变量值的实现代码》:本文主要介绍在Python中获取命令行(cmd)环境变量的值,可以使用标准库中的os模块,需要的朋友可以参考下... 前言全局说明在执行py过程中,总要使用到系统环境变量一、说明1.1 环境:Windows 11 家庭版 24H2 26100.4061

Python中bisect_left 函数实现高效插入与有序列表管理

《Python中bisect_left函数实现高效插入与有序列表管理》Python的bisect_left函数通过二分查找高效定位有序列表插入位置,与bisect_right的区别在于处理重复元素时... 目录一、bisect_left 基本介绍1.1 函数定义1.2 核心功能二、bisect_left 与

VSCode设置python SDK路径的实现步骤

《VSCode设置pythonSDK路径的实现步骤》本文主要介绍了VSCode设置pythonSDK路径的实现步骤,包括命令面板切换、settings.json配置、环境变量及虚拟环境处理,具有一定... 目录一、通过命令面板快速切换(推荐方法)二、通过 settings.json 配置(项目级/全局)三、

pandas实现数据concat拼接的示例代码

《pandas实现数据concat拼接的示例代码》pandas.concat用于合并DataFrame或Series,本文主要介绍了pandas实现数据concat拼接的示例代码,具有一定的参考价值,... 目录语法示例:使用pandas.concat合并数据默认的concat:参数axis=0,join=

java中BigDecimal里面的subtract函数介绍及实现方法

《java中BigDecimal里面的subtract函数介绍及实现方法》在Java中实现减法操作需要根据数据类型选择不同方法,主要分为数值型减法和字符串减法两种场景,本文给大家介绍java中BigD... 目录Java中BigDecimal里面的subtract函数的意思?一、数值型减法(高精度计算)1.

C#代码实现解析WTGPS和BD数据

《C#代码实现解析WTGPS和BD数据》在现代的导航与定位应用中,准确解析GPS和北斗(BD)等卫星定位数据至关重要,本文将使用C#语言实现解析WTGPS和BD数据,需要的可以了解下... 目录一、代码结构概览1. 核心解析方法2. 位置信息解析3. 经纬度转换方法4. 日期和时间戳解析5. 辅助方法二、L

使用vscode搭建pywebview集成vue项目实践

《使用vscode搭建pywebview集成vue项目实践》:本文主要介绍使用vscode搭建pywebview集成vue项目实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录环境准备项目源码下载项目说明调试与生成可执行文件核心代码说明总结本节我们使用pythonpywebv

使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)

《使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)》字体设计和矢量图形处理是编程中一个有趣且实用的领域,通过Python的matplotlib库,我们可以轻松将字体轮廓... 目录背景知识字体轮廓的表示实现步骤1. 安装依赖库2. 准备数据3. 解析路径指令4. 绘制图形关键