GUI-Challenges 系列之 Card-Stack
简介
卡片堆叠,是一个比较有意思的组件,并且其实现也很简洁。布局上主要通过 grid 实现。 卡片堆叠和旋转效果通过rotate 以及 translate 等变换函数实现,最后加上transition平滑过渡就可以得到一个好看的 card stack UI 组件啦 ^^
结构
由两部分组成
- 左边属性设置区域
<form>
<fieldset>
<legend>Transform Origin</legend>
<input type="radio" name="transform-origin" id="origin-center" value="center" />
<label for="origin-center">center</label>
...
<input type="radio" name="transform-origin" id="top-right" value="top right" />
<label for="radio-top-right">top right</label>
<br />
</fieldset>
...
</form>
- 右边卡片堆叠区域
<div class="card-stack">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</div>
实现 Card Stack
要实现卡片堆叠的效果,我们需要将卡片堆叠在一起,然后将卡片旋转一定角度,这里的旋转角度是通过--scalar这个 css 变量来控制的,所以我们需要在父元素.card-stack上设置这个变量的值
<div class="card-stack" style="--scalar: 10;">
...
</div>
堆叠
首先通过 grid 布局,将所有卡片堆叠在一起,所有的卡片都通过grid-area属性设置在同一个区域,这样卡片就会从上至下依次堆叠在一起
.card-stack {
display: grid;
}
.card {
grid-area: 1 / 1 / 2 / 2;
width: 200px;
aspect-ratio: 2 / 2.5;
}
旋转
左右两边的卡片分别向两边旋转了一定角度,左边卡片的旋转度数是负数,右边卡片旋转度数是正数,一共有五张卡片。两两相邻的卡片,旋转的相对度数是固定的,这个固定的度数通过 Gap 范围选择器来控制,将这个度数用变量 --scalar 表示,那么每张卡片的旋转度数就是
- 第一张卡片
- 第二张卡片
- 第三张卡片
- 第四张卡片
- 第五张卡片
这里的--scalar 变量的大小由 Gap 范围选择器来控制,我们可以通过 JS 来动态的设置这个变量的值
const scalar = document.querySelector("#scalar")
const cardStack = document.querySelector(".card-stack")
scalar.addEventListener("input", (e) => {
const value = e.target.value
// 设置对应的 css 变量值
cardStack.style.setProperty("--scalar", value)
})
由于每张卡片旋转的度数是不一样的,所以我们需要分别设置每张卡片的旋转度数,可以通过 nth-of-type 来选择对应卡片
.card:nth-of-type(1) {
--r: calc(-2 * var(--scalar) * 1deg);
}
.card:nth-of-type(2) {
--r: calc(-1 * var(--scalar) * 1deg);
}
.card:nth-of-type(3) {
--r: calc(0 * var(--scalar) * 1deg);
}
.card:nth-of-type(4) {
--r: calc(1 * var(--scalar) * 1deg);
}
.card:nth-of-type(5) {
--r: calc(2 * var(--scalar) * 1deg);
}
然后在 .card上通过rotate函数进行旋转,应用上面设置的旋转度数
.card {
transform: rotate(var(--r));
}
至此旋转卡片已经完成,并且可以设置卡片的旋转角度。需要注意的是,如果要设置旋转的中心点,需要用到transform-origin属性,这个属性可以接受 "top bottom center left right"关键词来指定变换的原点,也就是旋转的中心点
平移
在Hover卡片时,会有一个向上的平移效果,也是通过transform来实现。指定一个 css 变量--t来代表在 Y 轴上平移的距离。正常情况下不平移,hover的时候设置变量为-50px,也就是向上平移50px
.card {
transform: rotate(var(--r)) translateY(var(--t), 0px);
}
.card:hover {
--t: -50px;
}
这里的旋转→平移和平移→旋转的顺序不一样,最后产生的效果也是不同的
知识点
[1] grid-layout
[2] transform-origin
[3] transform