登录/注册
占位
占位
浏览量
占位
粉丝
占位
关注
如何在CSS中映射鼠标位置,并实现通过鼠标移动控制页面元素效果
2021-05-11 11:14:34 2021-05-11
99
0

映射鼠标位置或实现拖拽效果,我们可以在 JavaScript 中做到这一点。但实际上,在CSS中有更加简洁的方法,我们可以在不使用JavaScript 的情况下,仍然可以实现相同的功能!

只使用CSS就可以实现模仿鼠标"点击和拖动"效果,让我们来看看如何获得用户的鼠标位置,并将其映射到 CSS 自定义属性:--positionX 和 --positionY 中。下面是具体实现步骤。

初始化

我们的第一个 demo 将使用 --positionX 和 --positionY 自定义属性来设置元素的宽度和高度。

<div class="content">
<div class="square"></div>
</div>
*, *::before, *::after {
padding: 0;
margin: 0 auto;
box-sizing: border-box;
}
body {
background-color: black;
height: 100vh;
}
.content {
--positionX: 0;
--positionY: 0;
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
display: flex;
justify-content: center;
align-items: center;
}
.square {
width: 100px;
height: 100px;
background: white;
}

这是我们最初的状态。我们这里有一个了名为 .content 的容器

,它的的宽度和高度填充满 body,它是项目的内容主体。类名为 .square 的
是在这个例子中我们想用鼠标来进行控制的元素。

我们还在内容中添加了两个自定义属性。我们将使用鼠标位置来设置这些属性的值,然后使用它们来设置 .square 元素的宽高。

一旦我们为鼠标位置绘制了自定义属性,我们几乎可以使用它们来做我们想要的任何事情。例如,我们可以使用它们来设置一个绝对定位元素的 top/left、控制 transform 属性、设置 background-position、调整 color,甚至设置伪元素的内容等。我们将在文章的结尾看到一些这样的演示效果及对应的Codepen 项目链接。

grid 网格

目标是在屏幕上创建一个不可见的网格,并使用 :hover 伪类将每个"单元格"映射成我们自定义属性的一组值。此时,当鼠标光标移动到屏幕的右侧时,--positionX 的值将更高:当鼠标向左移动时,它变得更低。对于 --positionY 也是一样的:当光标移动到顶部时,值将更低,当光标移动到底部时,值会更高。

关于我网格大小及网格分块需要注意的地方:实际上我们可以使任何我们可以达到的网格尺寸。它越大,自定义属性值就越准确。但这也意味着我们将有更多网格分块区间,网格分块过多可能会导致性能问题,根据实际项目保持适当的平衡地调整网格大小是非常重要的。

现在,假如我们需要一个10×10网格,所以总共100个网格分块在我们容器中。(在实际开发中可以使用pug等语法快速创建表格,例子中100个空间全部用 div 表示出来了)

<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<!-- 97 more cells -->
<div class="content">
<div class="square"></div>
</div>

由于级联关系,将 .cell 元素放在 .content 元素前面。

我们希望使用 .cell 类来控制 .square,由于CSS的级联关系,一个元素只能控制其子子元素(或子元素的子元素)及位置在它的后面的兄弟元素(或兄弟元素的子元素)

这意味着两件事:

  • 每个 .cell 必须先于需要控制的元素(在这个例子中为 .square)。
  • 不能把这些 .cell 放在一个容器里,如果我们这样做.content 元素就不再是他们的兄弟元素。

定位单元格

有很多方法可以定位 .cells。比如我们可以使用 position: absolute,并设置它们的 top 和 left 属性;或者我们也可以通过 transform 来转换位置;但最简单的选择其实是使用 display: grid。

body {
background-color: #000;
height: 100vh;
display: grid;
grid-template: repeat(10, 1fr) / repeat(10, 1fr);
}
.cell {
width: 100%;
height: 100%;
border: 1px solid gray;
z-index: 2;
}

border 只是暂时的,在开发中所以我们可以看到屏幕上的网格,稍后会删除它。

z-index 非常重要,因为我们希望单元格出现在内容顶层。

以下是我们目前完成的内容:

<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<!-- 97 more cells -->
<div class="content">
<div class="square"></div>
</div>

```

*, *::before, *::after {
padding: 0;
margin: 0 auto;
box-sizing: border-box;
}
body {
background-color: black;
height: 100vh;
display: grid;
grid-template: repeat(10, 1fr) / repeat(10, 1fr);
}
.cell {
width: 100%;
height: 100%;
border: 1px solid gray;

暂无评论