搞不懂购物车动画咋整?,别怕这招“无限点击”用CSS+单选按钮就能搞定

2,419字
10–15 分钟
in

买东西加购物车这事儿,谁还没干过呢。从点外卖到买衣服,那个小图标一跳一跳的,看着就带劲。但真到自己动手做这个效果,是不是有点懵?既要让东西飞过去,还得记住加了多少个,咋搞?今天就掰开揉碎,说说怎么用CSS和一组单选按钮,弄出个能无限点、还能自动飞入购物车的小玩意儿。这法子可能不是最完美的,但绝对够巧妙,看完就能上手。

目录

这玩意儿叫啥,无限选择

无限选择,听着玄乎,其实说白了就是让页面上那些商品卡片,随便点哪个,它都能像被施了魔法一样,嗖地一下飞到购物车里去。想加多少加多少,没有数量限制,全靠CSS在背后撑场子,除了那个数数的小标记得用点JavaScript帮忙。核心就是玩转单选按钮那点事儿。

先搭架子,把商品摆好

做这事之前,得先把商品摆上桌。每个商品其实就是一个盒子,里面藏着两个长得一模一样的单选按钮,而且它们俩名字得一样,这样才是一个小组。

<div class="items flat-white">
  <input type="radio" name="r3" title="Flat White">
  <input type="radio" name="r3" title="Flat White">
</div>

为啥要放俩?这就是个障眼法。点一下,其中一个被选中,另一个自动就弹开。这样一来一去,就有了“加购”这个动作的触发器。

为了让这些商品卡片能乖乖待在位置上,得给它们定好位。整个卡片盒子用绝对定位,里面的两个单选按钮也得绝对定位,并且铺满整个盒子。

.items {   
  position: absolute;

  input { 
    position: absolute; 
    inset: 0; 
  }
}

这个inset: 0;可是个好东西,它让按钮的上下左右都贴着盒子的边缘,这样点图片点文字,都能点到按钮,不会出现点不着的尴尬情况。

接下来就是把这些商品卡片,从购物车那个中心点,摆到它们各自该待的位置上。这就好比从圆心出发,把点发散到四周。用transform: translate来挪动它们,可以控制上下左右的距离。

.items {
  --y: 100px; /* 从上往下飞的垂直距离 */

  &:not(.cart) {
    transform: translate(var(--x), calc(-1 * var(--y)));
  }
  &.espresso { 
    --x: 0px;  /* 水平距离 */
  }
  &.cappuccino { 
    --x: -100%; 
  }
  &.flat-white { 
    --x: 100%; 
  }
}

这里用到了CSS变量,像--x--y,就是为了方便调整每个商品的起始位置。比如浓缩咖啡就在正上方,卡布奇诺就往左偏,拿铁往右偏。这些数值可能需要微调,直到看着顺眼为止。

让商品飞起来,加点动效

布局搞定,重头戏来了。怎么让点击的那个商品,动画般地飞到购物车里去?关键就在:checked这个状态上。

当单选按钮被选中,也就是商品被点了一下之后,就让它发生位移和缩放,最终变成一个小点,消失在购物车的位置上。

input:checked {
  transform: translate(calc(-1 * var(--x)), var(--y)) scale(0);
  transition: transform .6s linear;
}

这里有个小技巧,位移的距离正好是初始位置的相反数。比如原来在--x: 100%的位置,那就往左移动-100%,这样就能精准地飞回到原点。加上scale(0),让它消失在购物车那个点。最后加上.6s的过渡动画,就有了那个丝滑的飞行感。

数数加了多少,心里有数

光飞过去还不行,总得知道加了多少个吧。这时候就得请出JavaScript来帮个小忙,负责统计点击次数并更新显示。

let n = 0;
const CART_CNT = document.querySelector("output");
document.querySelectorAll("[type='radio']").forEach(radio => {
  radio.onclick = () => {
    CART_CNT.innerText = ++n;
    CART_CNT.setAttribute("arial-label", `${n}`)
  }
});

这段代码干了这么几件事:先找到那个显示数量的地方(比如一个<output>标签),然后监听页面上所有的单选按钮。每点一下,就把计数n加一,然后更新显示的数字。顺带还更新一下arial-label,方便读屏软件读出当前有多少商品。

有一点得提一嘴,这版demo里加进去的东西可没法退出来,点了就认了,想好了再点哈。

屏幕阅读器那点事儿,得留心

说到这儿,得泼盆冷水。这个设计虽然看着酷,但对屏幕阅读器不太友好。每个商品里塞了两个功能相同的单选按钮,读屏软件可能会把它读成两个选项,或者来回切换时状态变化让用户摸不着头脑。虽然可以在代码里藏点提示文字,但终究不是最完美的方案。如果特别在意无障碍访问,可能得琢磨琢磨其他路子。

还有没有更香的法子

其实想让东西飞进购物车,不只有这一条路。现在浏览器有了个新玩意儿,叫视图过渡API。这玩意儿只用两个元素就能搞定过渡,一个商品,一个购物车,用CSS给它们起个名字,定义好动画,点一下就触发,干净利落,没有多余的按钮,也不用费心思维护状态。如果项目不用考虑太老旧的浏览器,这个方案绝对值得一试。

另外,如果商品就那么几样,用复选框也能凑合,每个商品一个复选框,点一下算一次,简单直接。但缺点就是加购次数有限,没那么灵活。

方案优点缺点适用场景
双单选按钮无限次数,纯CSS动画无障碍支持差,结构稍复杂商品多,需无限添加,可接受一定局限
视图过渡API结构简洁,动画流畅较新API,旧浏览器不支持现代浏览器项目,追求极简代码
复选框方案代码最简单无法统计无限次数商品数量少,加购次数有限

所以,如果项目里需要无限加购,又用不了视图过渡API,那这套双单选按钮的玩法,绝对是个值得往工具箱里收的好把式。虽然有点小瑕疵,但架不住它思路清奇,上手也快。