探索在网页中使用“标注”
github地址:https://github.com/1314mxc/yunUI ,欢迎star!
说起“标注”,在HTML5之前,你可能想起的是各种浏览器插件,emmmmmmm或者说你根本不认为浏览器上可以有这种玩意。
但是HTML5来了,这是它的时代。
我们完全可以不借助CSS、JavaScript的力量实现这个东西 —— 因为浏览器实现了 <ruby></ruby>
这个神奇的标签:
<ruby>
<rb>中文</rb>
<rp>(</rp><rt>zhongwen</rt><rp>)</rp>
</ruby>
它是这样表现的:
据说在不支持ruby的浏览器中也能这样适应:
除此之外,随着前端的发展,CSS3也给我们带来了“惊喜” —— 文字强调装饰 text-emphasistext-emphasis家族总共有4个CSS属性,分别是:
- text-emphasis
- text-emphasis-color
- text-emphasis-style
- text-emphasis-position
其中,text-emphasis
是text-emphasis-color
和text-emphasis-style
这两个CSS属性的缩写,注意,并不包含text-emphasis-position
属性,text-emphasis-position
属性是独立的!text-emphasis-position属性用来指定强调装饰符的位置,默认位置是在正文的上方,我们可以指定强调装饰符在正文的下方,也可以指定垂直排版的时候强调装饰符是左侧还是右侧。语法如下:
text-emphasis-position: [ over | under ] && [ right | left ]
使用示意:
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,但是随即想到了这个string怎么插入到父p标签中,而且要插入到原位置!
辗转了一上午,想到了一个“取巧的方法”:因为选中的文本已经是一个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!
- use vue vuex vue-router, not use webpack
- 从尾到头打印链表
- Webpack+Vue如何导入Jquery和Jquery的第三方插件
- [Hadoop大数据]——Hive部署入门教程
- Vuex原来可以这样上手
- 《Hive编程指南》—— 读后总结
- Event(事件)的传播与冒泡
- [Hadoop大数据]——Hive数据的导入导出
- 区块链技术在电子游戏与博彩行业备受追捧 有望实现数字商品货币化
- vue原来可以这样上手
- [Hadoop大数据]——Hive连接JOIN用例详解
- 扑克牌的顺子
- 数组前半部分和后半部分有序的全排序
- restful Api 风格契约设计器:Swagger-editor和swagger-ui的应用
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- TypeScript里的.d.ts语法
- 宋宝华:当Linux内核遭遇鲨鱼—kernelshark
- 基于Pytorch的动态卷积复现
- SAP Spartacus的StorefrontConfig对象
- Linux内核虚拟内存管理之匿名映射缺页异常分析
- Elasticsearch:如何把 Elasticsearch 中的数据导出为 CSV 格式的文件
- Nginx 负载均衡配置(实战教程)
- 教懂你什么是 “ 流量劫持 ”
- SAP Spartacus中使用到的Angular ModuleWithProviders类型
- 架构设计 | 基于消息中间件,图解柔性事务一致性
- 结构与算法(02):队列和栈结构
- 用Gaussian寻找圆锥交叉点
- kubernetes用户安全管理模型简析
- Unity3D网络通讯(一)--Asp.Net Core WebApi创建发布注意事项
- Unity3D网络通讯(二)--UnityWebRequest及JsonUtility请求Http Restful