本文为做者行舟客投稿,点击阅读原文可到达github地址~
github地址:https://github.com/1314mxc/yunUI ,欢迎star!css
提及“标注”,在HTML5以前,你可能想起的是各类浏览器插件,emmmmmmm或者说你根本不认为浏览器上能够有这种玩意。前端
可是HTML5来了,这是它的时代。node
咱们彻底能够不借助CSS、JavaScript的力量实现这个东西 —— 由于浏览器实现了 <ruby></ruby> 这个神奇的标签:ios
<ruby> <rb>中文</rb> <rp>(</rp><rt>zhongwen</rt><rp>)</rp> </ruby>
它是这样表现的:
听说在不支持ruby的浏览器中也能这样适应:git
除此以外,随着前端的发展,CSS3也给咱们带来了“惊喜” —— 文字强调装饰 text-emphasistext-emphasis家族总共有4个CSS属性,分别是:github
text-emphasis-position: [ over | under ] && [ right | left ]
使用示意:web
text-emphasis-position: over left; text-emphasis-position: under right; text-emphasis-position: under left; text-emphasis-position: left over; text-emphasis-position: right under; text-emphasis-position: left under; // text-emphasis-position的初始值是over right。right定位出如今文 字垂直排版的时候,例如设置writing-mode:vertical-rl,此时就能够看到强调装饰符在右侧了
好比:小程序
<p id="p">aishfaoihfoiahfoahdfoiahfdoshoigsoidshioshghudsihfisjhiodshoishoighdihishoighsoiv</p> //css color: red; -webkit-text-emphasis-style: '·'; text-emphasis-style: '·'; -webkit-text-emphasis-color: red; text-emphasis-color:red; -webkit-text-emphasis-position:under; text-emphasis-position: under;
它是这样表现的:微信小程序
稍稍有些小遗憾的是:它不能“针对每一个字体设置不一样的重点标志”,因此经常只用来作辅助突出功能数组
笔者一直认同的是:能用HTML完成的就不用CSS,能用CSS的就不用JS。并在平常实践中愈发以为这是一条“至理”!”
那么问题来了,如今我想实现这样一个功能:如今的「网页翻译」大可能是“页面总体翻译”或者“弹框拖入”,少部分是“选中文字后在文字旁弹出一个提示框”,可是这几种方式不论是哪种都会有一丝丝的影响:好比遮挡页面其他内容、精确度不高等等。那能不能“当用户选中文字后在选中文本下方有突出强调、在文本上方出现翻译”呢?
(这个笔者在本文先不说,以避免形成“长篇大论”,本文只把实现的基础知识全盘托出!)
首先是HTML:这里咱们简单的作一个p标签:
<p id="p">aishfaoihfoiahfoahdfoiahfdoshoigsoidshioshghudsihfisjhiodshoishoighdihishoighsoiv</p>
笔者的思路是:当用户鼠标“抬起”时,去判断有没有选中文本,若是没有则啥事没有、反之则要将这一部分选中的文本替换成标签!
p.onmouseup=function(e){ var txt = window.getSelection(); console.log(txt) var selectStr = txt.toString(); console.log(selectStr) if(selectStr!==''){ replaceSelectedStrByEle(txt,selectStr,'nite-writer-pen') } }
这里 window.getSelection() 是浏览器API,专门用于获取用户选中的文本,其具体值用 .toString() 便可得到。
/** * 用元素替换被选中的文本 */ var replaceSelectedStrByEle = function(selecter,selectStr,className){ if (selectStr.trim != "") { var rang = selecter.getRangeAt(0); var ele = document.createElement("span"); ele.style.cssText="-webkit-text-emphasis-style: '·';text-emphasis-style: '·';text-emphasis-color:red;-webkit-text-emphasis-position:under;text-emphasis-position:under"; ele.className = className; ele.textContent = selectStr; rang.surroundContents(ele); } }
selecter.getRangeAt(0):selection API是将每次选中的都保存到内部的数组里,并且是最新的保存到第一个这样的顺序。没错这里就是用的 -webkit-text-emphasis 突出强调符 —— 若是要为某个元素一次添加多个样式,cssText能够优化性能!
受笔者“信奉”准则的影响,其实在这里一开始还想用纯CSS的 伪类::selection 去作突出强调,可是很不幸的是:这个伪类里面只能改变选中文字的颜色相关:如背景颜色、字体自己颜色。其余的什么都改变不了(不知道为啥,感受很奇怪:虽然说它是子选择器行为,可是其影响应该是和display之流是同样的,并不会产生太大的变更)。诸君请看:”
selection
(如上图)至此,选中状态已经差很少了 —— 至于没说的翻译,这里若是你没有足够的能力建一个“词库”,那么我仍是建议你启用“第三方库/插件”或者在线翻译API。这里还有一个问题是:在笔者实践过程当中发现,ruby标签是没有办法嵌套在行内元素中的:它会带着其内包裹的文字消失不见 !这一点必定注意。
好了,你总不能让用户一直处于这个状态吧。那就要在必定状况下取消上面的状态 —— 这里笔者也遇到了一些“奇葩”问题:
何时结束选中状态?我建议,在点击页面其他空白地方时改变状态 —— 由于为了更好的体验,上面选中使用的mouseup:这里涉及到一个“浏览器事件触发的优先级”。你可让文本处于“高zIndex区域”、或者用JS去隔离。
展转了一上午,想到了一个“取巧的方法”:由于选中的文本已是一个dom了,将选中的文本都转化为string,而后再用字符串替换替换掉父p标签的innerText内容的相同之处!~
/** * 将dom转化为文本 */ function nodeToString ( node ) { //createElement()返回一个Element对象 var tmpNode = document.createElement( "div" ); //appendChild() 参数Node对象 返回Node对象 Element方法 //cloneNode() 参数布尔类型 返回Node对象 Element方法 tmpNode.appendChild( node.cloneNode( true ) ); var str = tmpNode.innerHTML; tmpNode = node = null; return str; }
mxc.onclick=function(){ if(document.querySelector('p .nite-writer-pen')){ let p=document.querySelector('p .nite-writer-pen').parentNode let nite=document.querySelector('p .nite-writer-pen') console.log(nite) console.log(p) p.innerText=(p.innerHTML).replace(nodeToString(nite),nite.innerText) } }
display
笔者开源了微信小程序日期组件扩展:可自定义精确到分、秒;可自定义位置、颜色、是否用默认样式。地址:https://github.com/1314mxc/yunUI 欢迎star!