当前位置: 首页 > Web前端 > HTML

如何在CSS中映射鼠标位置,实现通过鼠标移动控制页面元素的效果

时间:2023-04-02 22:06:39 HTML

映射鼠标位置或者实现拖动效果,我们可以在JavaScript中实现。但实际上,在CSS中有更简洁的方法,我们仍然可以在不使用JavaScript的情况下实现相同的功能!仅使用CSS就可以模仿鼠标的“单击和拖动”效果。让我们看看如何获??取用户的鼠标位置并将其映射到CSS自定义属性:--positionX和--positionY。下面是具体的实现步骤。初始化我们的第一个演示将使用--positionX和--positionY自定义属性来设置元素的宽度和高度。

*,*::before,*::after{填充:0;保证金:0自动;box-sizing:border-box;}body{背景色:黑色;高度:100vh;}.content{--positionX:0;--位置Y:0;位置:绝对;顶部:0;右:0;底部:0;左:0;显示:弹性;证明内容:居中;对齐项目:中心;}.square{宽度:100px;高度:100px;background:white;}这是我们的初始状态。我们这里有一个名为.content的容器
,它的宽度和高度填充了body,它是项目的主要内容。类为.square的
是本例中我们要用鼠标控制的元素。我们还向内容添加了两个自定义属性。我们将使用鼠标位置来设置这些属性的值,然后使用它们来设置.square元素的宽度和高度。一旦我们为鼠标位置绘制了自定义属性,我们就可以使用它们来做我们想做的几乎所有事情。比如我们可以用它们来设置绝对定位元素的top/left,控制transform属性,设置background-position,调整颜色,甚至设置伪元素的内容等等。我们会看到其中一些演示和文章末尾相应Codepen项目的链接。网格目标是在屏幕上创建一个不可见的网格,并使用:hover伪类将每个“单元格”映射到我们自定义属性的一组值。此时--positionX的值会在鼠标光标移到屏幕右侧时变高:鼠标移到屏幕左侧时变低。--positionY也是一样:当光标移到顶部时,该值会变低,当光标移到底部时,该值会变高。关于我的网格大小和网格分区的一些注意事项:我们实际上可以制作我们可以达到的任何网格大小。它越大,自定义属性值就越准确。但这也意味着我们会有更多的网格瓦片间隔,太多的网格瓦片可能会导致性能问题,根据实际项目调整网格大小以保持适当的平衡非常重要。现在,假设我们需要一个10x10的网格,所以我们的容器中总共有100个网格块。(实际开发中可以使用pug等语法快速创建表格,例子中100个空格全部用div表示)
/div>
Due对于级联关系,将.cell元素放在.content元素之前。我们想使用.cell类来控制.square。由于CSS的级联关系,一个元素只能控制它的子元素(或子元素的子元素)和它后面的兄弟元素(或兄弟元素的子元素)元素)这意味着两件事:每个。单元格必须位于它需要控制的元素之前(在本例中为.square)。将这些.cell放在容器中是不可能的,如果我们这样做的话,.content元素不再是它们的兄弟姐妹。定位单元格有很多方法可以定位.cells。例如,我们可以使用position:absolute并设置它们的top和left属性;或者我们可以通过transform变换位置;但最简单的选择是使用display:grid。身体{背景颜色:#000;高度:100vh;显示:网格;网格模板:重复(10、1fr)/重复(10、1fr);}.cell{宽度:100%;高度:100%;:1px纯灰色;z-index:2;}border只是暂时的,在开发中所以我们可以在屏幕上看到网格,稍后将被删除。z-index非常重要,因为我们希望单元格出现在内容之上。这是我们目前所做的:*,*::before,*::after{padding:0;保证金:0自动;box-sizing:border-box;}body{背景色:black;高度:100vh;显示:网格;网格模板:repeat(10,1fr)/repeat(10,1fr);}.cell{width:100%;高度:100%;边框:1px纯灰色;z-指数:2;}.content{--positionX:0;--位置Y:0;位置:绝对;顶部:0;右:0;底部:0;左:0;显示:弹性;证明内容:居中;对齐项目:中心;}.square{宽度:100px;高度:100px;background:white;}addvalue我们要设置--positionX和--positionY的值。当我们将鼠标悬停在第一个(左列).cell上时,--positionX值应为0。当我们将鼠标悬停在第二列中的.cell上时,该值应为1。第三个2,依此类推。y轴也是如此。--positionY应该是0当我们将鼠标悬停在第一行(顶部).cell上时,value应该是1当我们将鼠标悬停在第二行的单元格上时,等等。黑色10x10正方形,白色边框和数字从左到右顺序排列.图像中的数字代表网格中每个单元格的数量。如果我们采用单个.cell-单元格编号42-我们可以使用:nth-child()来选择它:.cell:nth-child(42){}但我们需要记住一些事情:我们只想这个选择器只有在悬停在单元格上时才会生效,所以我们需要给它附加附件:悬停。我们想要选择.content元素而不是单元格本身,所以我们需要使用通用的兄弟选择器~来做到这一点。所以现在,要在第42个单元格悬停时将--positionX设置为1并将--positionY设置为3,请执行以下操作:.cell:nth-child(42):hover~.content{--positionX:1;--positionY:3;}但是有100个单元格,谁愿意这样做100次!?有几种方法可以简化上述操作:在Sass中使用@for循环遍历所有100个单元格,并做一些数学运算,为每次传递设置相应的--positionX和--positionY值。要分离x轴和y轴,请使用带:nth-child的函数符号分别选择每一行和每一列。结合这两种方法,同时使用Sass@for循环和:nth-child特征符号。我想过什么是最简单最好的方法,虽然所有的方法都有优点和缺点。要编写的代码量、编译代码的质量以及考虑的数学复杂性最终导致我选择了第三种方法。如果你有更好的方法,请在评论中告诉我。使用@for循环设置值@for$i从0到10{.cell:nth-child(???):hover~.content{--positionX:#{$i};}.cell:nth-child(???):hover~.content{--positionY:#{$i};}}这是一个基本的循环框架,我们需要循环10次,因为上面构建的网格有10行10列。将网格划分为x和y轴,为每一列设置--positionX,为每一行设置--positionY。我们现在要做的是找到一个合适的数学表达式,填入???选择每一行和每一列。让我们回到上面的网格图像,数字从x轴开始,我们可以看到第2列中的所有单元格的数字都是10加2的倍数。第2列中的单元格是10加3的倍数。.现在,让我们将其转换为:nth-child的函数表达式。以下是第2列的表示方式::nth-child(10n+2)10n表示选择10的每一个倍数。2是列号,在我们的循环中,我们将用#{$i+替换列号1]按顺序重复。.cell:nth-child(10n+#{$i+1}):hover~.content{--positionX:#{$i};}现在让我们处理y轴并再次查看网格图像,关注第4行,网格数在41到50之间。第5行的网格数在51到60之间,依此类推。要选择每一行,我们需要定义它的范围。例如,第四行的范围是:.cell:nth-child(n+41):nth-child(-n+50)(n+41)是范围的开始。(-n+50)是范围的结尾。现在,我们用$i的值替换数学公式中的数字。你得到(n+#{10*$i+1})范围的开始和(-n+#{10*($i+1)})范围的结束。所以最后的@for循环是:@for$ifrom0to10{.cell:nth-child(10n+#{$i+1}):hover~.content{--positionX:#{$i};}.cell:nth-child(n+#{10*$i+1}):nth-child(-n+#{10*($i+1)}):hover~.content{--positionY:#{$i};}}映射完成!当我们将鼠标悬停在元素上时,--positionX和--positionY的值会根据鼠标位置发生变化。这意味着我们可以使用它们来控制内容中的元素。处理自定义属性好了,现在我们已经将鼠标位置映射到两个自定义属性,接下来就是用它们来控制.square元素的宽高值了。让我们从宽度开始,假设我们希望.square元素的最小宽度为100px(即当鼠标光标位于屏幕左侧时),并且我们还希望鼠标光标每次增长20px向右走。使用calc(),这可以实现:.square{width:calc(100px+var(--positionX)*20px);}对于高度,我们做同样的事情,但使用--positionY代替:.square{width:calc(100px+var(--positionX)*20px);高度:计算(100px+var(--positionY)*20px);}就是这样!现在我们有了一个简单的.square元素,其宽度和高度由鼠标位置控制。在界面周围移动鼠标光标,可以看到正方形的宽度和高度如何相应变化。下面是整个示例的完整代码。*,*::before,*::after{填充:0;保证金:0自动;box-sizing:border-box;}body{背景色:black;高度:100vh;显示:网格;网格模板:重复(10、1fr)/重复(10、1fr);}.cell{宽度:100%;高度:100%;//边框:1px纯灰色;z-index:2;}@for$ifrom0to10{.cell:nth-child(10n+#{$i+1}):hover~.content{--positionX:#{$i};}.cell:nth-child(n+#{10*$i+1}):nth-child(-n+#{10*($i+1)}):hover~.content{--positionY:#{$i};}}.content{--positionX:0;--位置Y:0;位置:绝对;顶部:0;右:0;底部:0;左:0;显示:弹性;证明内容:居中;对齐项目:中心;}.square{宽度:calc(100px+var(--positionX)*20px);高度:计算(100px+var(--位置Y)*20px);背景:白色;transition:all0.3s;}我添加了一个小的过渡效果,看起来更平滑当然,这不是必需的。我还注释掉了.cell元素的边框。让我们尝试一个替代方案。可能会有这样一种情况,你想“绕过”--positionX和--positionY并直接在@for循环中设置最终值。对于我们的示例,它可以这样实现:@for$ifrom0to10{.cell:nth-child(10n+#{$i+1}):hover~.content{--squareWidth:#{100+$i*20}像素;}.cell:nth-child(n+#{10*$i+1}):nth-child(-n+#{10*($i+1)}):hover~.content{--squareHeight:#{100+$i*20}px;:#{$i};}}.square元素因此可以像这样自定义属性:.square{width:var(--squareWidth);height:var(--squareHeight);}这种方法更灵活一些,因为它允许使用更高级的Sass数学(和字符串)函数,但其??主要原理与我们的示例完全相同。下一步是什么?好吧,剩下的就看你如何使用它了——而且可能性是无穷无尽的!你能在CSS中更进一步地使用映射鼠标位置技巧吗?下面是几个会随鼠标变化的页面图形示例:跳跃粒子3D文字透视图打字机效果