getClientRects应用举例

选中文字可对指定文章内容进行评论啦,绿色背景文字可以点击查看评论额。

上一节我们介绍了getClients的用法,今天我们学习一个简答的应用场景

需求:

我在一篇文章中选中一段文字,然后在文字的下方弹出一个简单的浮动按钮。

思路分析:

1、按钮需要浮动,首先我想到的是在文档中使用一个元素来作为按钮,这个元素我采用绝对定位,当我知道选择区域的大概位置的时候,根据位置修改元素的top和left值,就可以啦。

2、按钮元素最好首先将top和left的位置放置于文档的视口外部,这个我使用比较大的负值就可以啦。

3、如果知道我们选中区域的位置是我们本文的重点,也是本文的主题所在。

 

实现步骤代码:

<!doctype html>
<style>
	.comment {
		width: 35px;
		height:35px;
		background:#FFF;
		position:absolute;
		top: -500px;
		left:-500px;
	}
	button {
		width: 100%;
		height:100%;
	}
</style>
<body>
<p id="p">Select me: <i>italic</i> and <b>bold</b></p>

From <input id="from" disabled> – To <input id="to" disabled>
<script>

  document.onselectionchange = function(e) {
    let {anchorNode, anchorOffset, focusNode, focusOffset} = document.getSelection();
	let selection = document.getSelection();
	let range = selection.getRangeAt(0);
	const clientRects = range.getClientRects();
	let divElement = document.getElementById('comment');
	if (clientRects.length ==0) {
		divElement.style.top = '-500px';
	    divElement.style.left = '-500px';
		return;
	}
	divElement.style.top = (clientRects[0].top+20)+'px';
	divElement.style.left = clientRects[0].left+'px';
	
  };
</script>
<div id="comment" class="comment">
   <button>
	   <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
			<path d="M4 1.5h12A3.5 3.5 0 0 1 19.5 5v8l-.005.192a3.501 3.501 0 0 1-2.927 3.262l-.062.008v1.813a1.5 1.5 0 0 1-2.193 1.33l-.371-.193-.38-.212a13.452 13.452 0 0 1-3.271-2.63l-.062-.07H4A3.5 3.5 0 0 1 .5 13V5A3.5 3.5 0 0 1 4 1.5ZM4 3a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6.924a11.916 11.916 0 0 0 3.71 3.081l.372.194v-3.268L14.962 15H16a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H4Zm1.55 5a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5Zm4.5 0a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5Zm4.5 0a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5Z"></path>
		</svg>
	</button>
</div>
</body>

思路分析:

1、在文档中放置了一个div元素,id和class设置为comment,将它们设置为绝对定位,同时将它们的位置放到视口以外。

2、我们监听document.onselectionchange事件,第一步是获取选择的区域,这个可以根据document.getSelection();

3、我们得到选择区域的范围(range),这里需要注意的是,这里的范围有的浏览器有一个值,有的浏览器有多个值,这里我只需要第一个值就可以啦

4、调用range的getClientRects方法,注意,这个方法返回一个数组,我只需要第一个数组的值就足够,因为我只拿第一个DomRect的top和left

5、如果这个range没有值,或者即使有值,但是选中的range的宽度为0 ,这些情况直接返回就可以啦

实现的效果如上图所示。欢迎讨论

 

 

版权声明:著作权归作者所有。

相关推荐

Python:defaultdict应用示例

class collections.defaultdict([default_factory[, ...]]) defaultdict继承与内置类dict,但对于不存在的键处理方式不同。dict处理缺失的键在Python访问dict不存在的键会抛出KeyError异常。如计数列表里的颜色colors = ('yellow', 'red', 'yellow',

Python3.4 枚举类型的使用

枚举类型是在Python3.4新增到Python的标准库。创建枚举Python提供了两种方法来创建枚举:基于class语法创建枚举基于Function API创建枚举创建枚举首先要导入Enum类>>> from enum import Enum 基于class语法创建枚举示例>>> from 

Vue实例里this的使用

要理解Vue实例里this的使用,首先要理解this在JavaScript里的用法,可以参考理解JavaScript普通函数以及箭头函数里使用的this。这是vue文档里的原话:All lifecycle hooks are called with their 'this' context pointing 

使用Webpack、TypeScript 和React搭建应用

这里简单介绍基于webpack + typescript + react搭建一个应用。初始化项目创建一个空文件夹demo,使用npm在空文件夹初始化项目。npm init npm install --save-dev webpack npm install --save-dev types

CSS应用苹果的San Francisco字体

优先选择苹果字体,并兼容其它平台的字体。font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu,"Helvetica Neue",Arial,sans-serif;

resin 4配置多应用

Resin配置多个应用,每个应用需要有独立的http端口,独立的Server监控端口。共享同一个WatchDog。相关端口如下:app1:8010,6801 app2:8020,6802 WatchDog:默认6600 在resin.xml配置多个cluster  <cluster id="app1">    <serv

SwiftUI Alerts的使用示例

SwiftUI里的Alerts可以分为三类:警告对话框(Alert Dialogs)操作列表(Action Sheets)弹窗(Popovers)警告对话框(Alert Dialogs)示例使用SwiftUI,我们可以很容易地使用声明的方式来创建警告框以及定义操作,示例如下:struct AlertView: View { @State private var showingAlert =

Semaphore信号量用法示例

概要 ​ Semaphore当前在多线程环境下被扩放使用,操作系统的信号量是个很重要的概念,在进程控制方面都有应用。Java 并发库的Semaphore可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire()获取一个许可,如果没有就等待,而release()释放一个许可。用来控制资源同时访问个数 ​ 以一个停车场运作为例。假设停车场只有三个车位,一开

ES6中async的使用案例

在项目中有时会遇到异步操作的问题,async就是解决异步操作的终极操作。我会以终极三问(what,why,when)的形式来说明什么是async。由于这是第一篇文章不知道怎么写,有很大部分是借鉴阮一峰老的原文,事例将会从我的项目中摘取。 async是什么? 官方例子 官方文档 async相当于对Generator 函数的一个语法糖const fs = require

LINQ group by的使用示例

下面通过一个示例来展示linq中group by的使用。类Person如下:class Person { internal int PersonId; internal string car ; }Person列表List<Person>:persons[0] = new Person { PersonID = 1, car = "Ferrari" }; person