利用了css样式 transform: matrix() 控制卡片组滚动,来完成动画效果
:style="`transform: matrix(1, 0, 0, 1, 273, ${dataList[i]})`"
补充:
matrix(scaleX(),skewY(),skewX(),scaleY(),translateX(),translateY())
- scaleX() (水平缩放):控制元素水平方向的缩放。如果值为 1,则不进行水平缩放;如果大于 1,则放大;如果在 0 和 1 之间,则缩小。
- skewY() (垂直倾斜):控制元素在垂直方向上的倾斜。
- skewX() (水平倾斜):控制元素在水平方向上的倾斜。
- scaleY() (垂直缩放):控制元素垂直方向的缩放。如果值为 1,则不进行垂直缩放;如果大于 1,则放大;如果在 0 和 1 之间,则缩小。
- translateX() (水平平移):控制元素在水平方向上的平移量。
- translateY() (垂直平移):控制元素在垂直方向上的平移量。
即在不变换的情况下是
matrix(1, 0, 0, 1, 0, 0)
<!-- 自下而上动画 -->
<div class="anime-box">
<div
:style="`transform: matrix(1, 0, 0, 1, 273, ${dataList[i]})`"
v-for="(item, i) in data"
:key="item"
>
<p>{{ item.year }}</p>
</div>
</div>
.anime-box {
background-color: #b2ea97;
height: 670px;
overflow-y: scroll;
> div {
height: 250px;
width: 250px;
background-color: #9c7070;
display: flex;
align-items: center;
justify-content: center;
color: #ede0e0;
font-size: 30px;
}
}
动画实现主要思路:
1.从接口获取展示用的数据data后,算出每个被渲染出的卡片应有的初始位移,保存到一个代表Y轴位移的数;
// 模拟接口返回数据
const data = [
{ year: "1991", value: 3 },
{ year: "1992", value: 4 },
{ year: "1993", value: 3.5 },
{ year: "1994", value: 5 },
{ year: "1995", value: 4.9 },
{ year: "1996", value: 6 },
{ year: "1997", value: 7 },
{ year: "1998", value: 9 },
{ year: "1999", value: 13 },
];
// 计算初始位移,保存至数组
const dataList = ref([]);
const getDataList = () => {
let n = 0;
data.forEach((item, i) => {
dataList.value.push(n);
n += 30;
});
//开始动画
dataListChangeDown(); // 需要哪个方向调哪个
// dataListChange();
};
2.使用定时器,每过一段时间,数组每个值加或减一定的偏移量;
let intervalId;
// 从下到上动画
const dataListChange = () => {
intervalId = setInterval(() => {
dataList.value.forEach((item, i) => {
if (item < -(280 * (i + 1))) {
// 代表Y轴位移的数一旦触底后回归初始值
dataList.value[i] += (30 + 250) * dataList.value.length;
} else {
dataList.value[i] = item - 1;
}
});
}, 10);
};
// 从上到下动画
const dataListChangeDown = () => {
intervalId = setInterval(() => {
dataList.value.forEach((item, i) => {
if (item > 670 - 250 * i) {
// 代表Y轴位移的数一旦到顶后回归初始值
dataList.value[i] -= (30 + 250) * dataList.value.length;
} else {
dataList.value[i] = item + 1;
}
});
}, 10);
};
3.代表Y轴位移的数一旦触底/到顶后回归初始值。
页面销毁前记得清定时器
onUnmounted(() => {
clearInterval(intervalId);
});
打开页面时根据需求先获取数据,之后加载计算位移方法
onMounted(() => {
getDataList();
});
横滚
// 快速翻页 | 左
const quickScrollLeft = () => {
const maxMove = cardWidth * moveNumList.value.length - 1920;
moveNumList.value.forEach((item, i) => {
if (maxMove - cardWidth * (i + 1) > item) {
moveNumList.value[i] += cardWidth * 3;
} else {
// 代表Y轴位移的数一旦触底后回归初始值
moveNumList.value[i] -= cardWidth * moveNumList.value.length;
}
});
};
// 快速翻页 | 右
const quickScrollRight = () => {
moveNumList.value.forEach((item, i) => {
if (item > 0 - cardWidth * (i + 1)) {
moveNumList.value[i] -= cardWidth * 3;
} else {
// 代表X轴位移的数一旦触底后回归初始值
moveNumList.value[i] += cardWidth * moveNumList.value.length;
}
});
};