发布于 2年前
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 ,这些情况直接返回就可以啦
实现的效果如上图所示。欢迎讨论
</body>