马黑黑 发表于 2022-12-26 09:42

伪元素点击事件(一)

伪元素不属于DOM节点,常规操作下,JS难以对之进行读写操作,需要额外手段。本帖以伪元素独霸鼠标点击操作权限为例,简单探讨一下JS如何通过特殊手段对伪元素的点击操作(方法之一)进行处理。

CSS引入了一个属性,pointer-events,用于设置元素的鼠标指针事件,缺省值为 auto,表示元素具备接受鼠标操作权限,若需要取消此权限,设值为 none 即可,如此,该元素连 cursor: pointer; 都不能令鼠标指针呈手型样式。依此原理,我们给元素设置 pointer-events: none; 之后,鼠标经过和点击等动作在该元素上都不会有响应,然后我们给它的伪元素设置 pointer-events: auto; ,就能将接受鼠标操作的权限赋予了伪元素,效果同等于伪元素可以接受鼠标操作。

其实伪元素默认是能接受鼠标操作的,但它们是代表主元素接受的,不是代表伪元素自己,实践中,可以利用这一特点用伪元素协助偏细偏小的元素提升其接收鼠标操作的范围。而上述的骚操作,令伪元素霸占了鼠标操作,貌似是伪元素能够代表自己接受鼠标操作,还是挺有新意的。但问题来了:两个伪元素,到底是点击了哪一个?

这就需要祭出JS终极大杀器:

window.getComputedStyle(element,)

此法,能够获取元素(element)最后渲染的CSS样式,支持获取伪元素(pseudo)的最后CSS渲染样式。pseudo参数可选,省略时表示获取主元素CSS样式,想获取 ::before 或 ::after 伪元素的CSS样式,则加上参数 '::before' 或 '::after'。

然后配套 getPropertyValue(valName),就能拿到元素或伪元素的CSS指定的属性值,比如 left、width 等。

拿到伪元素的相关属性值,是 JS 判断是点击了 ::before 还是 ::after 伪元素的依据。比方说,两个不重合的左右并排伪元素,我们只需要判断 event 鼠标数据xy坐标值中 x 值不超过第二个伪元素的 left 值,就能确定鼠标指针处在第一个伪元素上,反之则处在第二个伪元素之上。

示例代码:

<style>
#papa {
        margin: auto;
        width: 600px;
        height: 460px;
        border: 1px solid olive;
        position: relative;
        pointer-events: none;
        cursor: pointer;
}
#papa::before, #papa::after {
        position: absolute;
        content: '伪元素1';
        top: 100px;
        left: 100px;
        width: 100px;
        height: 100px;
        border: 1px solid silver;
pointer-events: auto;
}

#papa::after {
        content: '伪元素2';
        left: 220px;
}
#clickMsg { position: absolute; top: 20px; left: 20px; }
</style>

<div id="papa">
        <div id="clickMsg">点击消息 ...</div>
</div>

<script>

papa.onclick = (e) => {
        let v2 = window.getComputedStyle(papa,'::after').getPropertyValue('left');
        clickMsg.innerText = e.offsetX < v2.replace(/[^\d]/ig,'') ? '点击了伪元素1' : clickMsg.innerText = '点击了伪元素2';
}

</script>

马黑黑 发表于 2022-12-26 09:43

本帖最后由 马黑黑 于 2022-12-26 10:43 编辑 <br /><br /><style>
#papa {
      margin: auto;
      width: 600px;
      height: 460px;
      border: 1px solid olive;
      position: relative;
      pointer-events: none;
      cursor: pointer;
}
#papa::before, #papa::after {
      position: absolute;
      content: '伪元素1';
      top: 100px;
      left: 100px;
      width: 100px;
      height: 100px;
      border: 1px solid silver;
        pointer-events: auto;
}

#papa::after {
      content: '伪元素2';
      left: 220px;
        text-align: center;
        border-radius: 50%;
}
#clickMsg { position: absolute; top: 20px; left: 20px; }
</style>

<div id="papa">
      <div id="clickMsg">点击消息 ...</div>
</div>

<script>

papa.onclick = (e) => {
      let v2 = window.getComputedStyle(papa,'::after').getPropertyValue('left');
      clickMsg.innerText = e.offsetX < v2.replace(/[^\d]/ig,'') ? '点击了伪元素1' : clickMsg.innerText = '点击了伪元素2';
}

</script>

马黑黑 发表于 2022-12-26 09:46

二楼,点击两个伪元素,JS均能准确判断是点击的哪一个;点击其他区域,没有响应。

由于主元素设置了 pointer-events: none;,其 cursor: pointer; 设置不起作用,但伪元素继承了这个设定——伪元素并没有设定 cursor 值。

马黑黑 发表于 2022-12-26 10:42

此法,若伪元素弄成圆形也是可以的,只有圆形区域能响应鼠标操作。

缺点是主元素牺牲了鼠标操作功能,无需主元素鼠标操作交互的可以考虑。

樵歌 发表于 2022-12-26 13:59

路过走过,知道是天书。{:4_189:}

红影 发表于 2022-12-26 14:32

两个伪元素可以单独设定某个pointer-events: auto么?

红影 发表于 2022-12-26 14:35

replace(/[^\d]/ig,'' 这个是什么?

马黑黑 发表于 2022-12-26 15:43

红影 发表于 2022-12-26 14:35
replace(/[^\d]/ig,'' 这个是什么?

getComputedStyle(element).getPropertyValue(vName)得到的是带单位的值,比如 left,它会得到像这样的结果:

25px

这些值要进行数学运算,需要去掉 px 字样。我们不确定都是什么单位符号,所以用正则来替换所得结果,只保留数字(可能还应该考虑小数点)。/ ... / 里,两个 / 表示这是一个正则表达式,... 才是真的正则表达式内容。内容中,[^\d] 表示不是数字,中括号 [] 用来组织一个表达法,\d 是数字,等同于 0-9,^ 表示不是;ig 是附加条件,表示忽略大小写、全部替换,逗号后面的 '' 表示替换成空字符。整个表达式的意思是,不是数字的统统替换成空,不论大小写

红影 发表于 2022-12-26 19:25

马黑黑 发表于 2022-12-26 15:43
getComputedStyle(element).getPropertyValue(vName)得到的是带单位的值,比如 left,它会得到像这样的结 ...

这里有这么多含义呢,不是黑黑解释,完全不知道。谢谢黑黑{:4_187:}

马黑黑 发表于 2022-12-26 19:41

红影 发表于 2022-12-26 19:25
这里有这么多含义呢,不是黑黑解释,完全不知道。谢谢黑黑

对吧?松散语言,智慧多多。JS,我说过,一下子可以入门,但是学到头发全白了,也没能掌握全部

马黑黑 发表于 2022-12-26 19:44

红影 发表于 2022-12-26 14:32
两个伪元素可以单独设定某个pointer-events: auto么?

可以

马黑黑 发表于 2022-12-26 19:44

樵歌 发表于 2022-12-26 13:59
路过走过,知道是天书。
天书天天读,不懂也读

樵歌 发表于 2022-12-27 08:18

马黑黑 发表于 2022-12-26 19:44
天书天天读,不懂也读

除非返回童年,从三字经开始{:4_189:}

马黑黑 发表于 2022-12-27 08:22

樵歌 发表于 2022-12-27 08:18
除非返回童年,从三字经开始

任何时候开始都不为晚

樵歌 发表于 2022-12-28 19:42

马黑黑 发表于 2022-12-27 08:22
任何时候开始都不为晚

迷迷糊糊小老头,还能学,我自己都不相信。{:4_189:}

马黑黑 发表于 2022-12-28 19:54

樵歌 发表于 2022-12-28 19:42
迷迷糊糊小老头,还能学,我自己都不相信。

小老头是科技南

红影 发表于 2022-12-28 21:08

马黑黑 发表于 2022-12-26 19:41
对吧?松散语言,智慧多多。JS,我说过,一下子可以入门,但是学到头发全白了,也没能掌握全部

入门本身也挺难的,不是你说的可以一下子入门呢{:4_173:}

红影 发表于 2022-12-28 21:09

马黑黑 发表于 2022-12-26 19:44
可以

那样就不用判断它们的位置了。

马黑黑 发表于 2022-12-28 21:57

红影 发表于 2022-12-28 21:09
那样就不用判断它们的位置了。

对的

马黑黑 发表于 2022-12-28 21:59

红影 发表于 2022-12-28 21:08
入门本身也挺难的,不是你说的可以一下子入门呢

差不多是可以一下子入门的。我当时对JS一直不敢兴趣,后来吧,做网页,总要用,但从来不去看JS的书,用到什么,才去查一下文档,用了N次后,就会了,剩下的就是后来的扩展、深入,这就难了
页: [1] 2
查看完整版本: 伪元素点击事件(一)