手写一个购买的商品放入购物车的效果
昨天因为看到了一个比较好玩的内容,于是研究了一下,没有更文。今天我就拿出来讲一讲。就是商品卡片,当我们置顶的时候,它的内容会有一个动画将它的商品内容滑出来给我们展示,并且点击加入购物车的时候,会出现一张缩小的图片移动到购物车的位置,并且购物车的数量也会加1。不过,我看到原文使用的jquery实现的,而且没有实现响应式布局.于是昨天我琢磨了一下,终于搞出来了,js版本,并且实现了响应式布局,为了模拟真实性还给它添加了一个判断属性,商品是否还有剩余。当商品显示已抢光时,会有一个alert,告诉我们商品已经没了。
模拟真实的图
自己做的图
效果图
响应式
实现步骤
整体页面布局格式包含了一个购物车和三个商品卡片。购物车包含了一个购物车图标和一个商品数量计数器,商品卡片包含了一个商品图片、商品名称、商品描述、商品价格和两个按钮(加入购物车和立即购买)。
在我的代码里,那个珊瑚的图标我是直接把掘金的页面那个svg全部扒下来的。然后html中引入的js是一个图标库,就是我们的那个购物车图标,大家也可以替换成自己喜欢的库。哦,对了,之前我文章的图片都是网上复制的链接,因为想到链接可能会失效,于是这次我把图片,存到了我的gitte搭建的图床里。
css布局
其实最主要的是为了调成响应式的花了我大部分时间。用@media比较具体,但是真的让我头秃了不止一点。
首先,文字和内容里面的大小都要调整,因为整个盒子都变小了,你不变小,就只能看到文字了。然后把文字部分移动的更远一点,因为这里并不是利用透明度让它消失不见,而是通过定位让它挡住,看不见了。
后面在当屏幕宽度小于等于760px时,我们让卡片变成相对定位,然后里面的图片是绝对定位,保证了图片大小一致,文字部分相对定位,使文字落在盒子的下面。
在最后当屏幕宽度小于等于380px时,我只是对按钮进行了一个调整,让按钮位置更美观。
/* 当屏幕宽度小于等于1000px时 */
@media (max-width:1000px) {
/* 卡片内容部分向上移动,字体大小和间距调整 */
.wrapper .card .content {
bottom: -120%; /* 向上移动卡片内容的高度 */
padding: 5px 10px 11px 10px; /* 调整卡片内容的内边距 */
padding: 10px 20px 22px 20px; /* 调整卡片内容的内边距 */
box-shadow: 0px -2px 5px 0px rgba(0, 0, 0, 0.15); /* 添加底部阴影 */
transition: all 0.3s ease; /* 添加过渡效果 */
}
/* 调整详情部分的字体大小 */
.content .row .details span {
font-size: 18px;
font-weight: 300;
}
/* 调整详情部分的字体大小 */
.content .row .details p {
font-size: 12px;
font-weight: 250;
}
/* 调整价格部分的显示方式 */
.content .row .price {
display: flex;
font-size: 15px;
font-weight: 400;
}
/* 调整按钮部分的上边距 */
.content .buttons {
margin-top: 10px;
}
/* 调整按钮的样式 */
.content .buttons button {
width: 100%;
padding: 6px 0;
font-size: 12px;
font-weight: 300;
border-radius: 6px;
}
/* 调整第一个按钮的右边距 */
.buttons button:first-child {
margin-right: 5px;
}
/* 调整最后一个按钮的左边距 */
.buttons button:last-child {
margin-left: 5px
}
}
/* 当屏幕宽度小于等于760px时 */
@media (max-width:760px) {
/* 卡片图片变成相对定位 */
.wrapper .card {
position: relative;
background: #fff;
}
/* 卡片图片变成绝对定位 */
.wrapper .card img {
position: absolute;
}
/* 卡片内容部分相对于卡片定位 */
.wrapper .card .content {
position: relative;
width: 100%;
margin-top: 100%; /* 卡片内容部分的上边距等于卡片高度 */
background: #fff;
padding: 10px 20px 22px 20px;
box-shadow: 0px -3px 10px 0px rgba(0, 0, 0, 0.15);
transition: all 0.3s ease;
}
}
/* 当屏幕宽度小于等于380px时 */
@media (max-width:380px) {
/* 调整按钮部分的样式 */
.content .buttons {
margin: 0;
padding: 0;
margin-top: 10px;
display: flex;
justify-content: center;
}
/* 调整按钮的样式 */
.content .buttons button {
width: 100%;
padding: 3px 0;
font-size: 12px;
font-weight: 300;
border-radius: 10px;
border: 2px solid #ff7979;
text-transform: uppercase;
transition: all 0.3s ease;
}
}
js具体实现过程如下:
先看一看我们的js是怎么实现的吧! 这段代码实现了一个简单的购物车功能,当用户点击“加入购物车”按钮时,会将对应商品的图片复制一份,并以动画的形式将其移动到购物车图标处。同时,购物车中的商品数量会增加,对应商品的库存数量会减少。
-
首先,我们通过
document.querySelectorAll()函数获取了所有的“加入购物车”按钮、商品图片、商品库存和购物车图标等元素,并将它们分别保存在cartBtns、imgs、ishave和cartNav变量中。 -
然后,我们使用一个
for循环遍历所有的“加入购物车”按钮,并为每个按钮添加一个click事件监听器。在事件处理函数中,我们首先判断对应商品的库存数量是否大于 0,如果是,则执行以下操作:- 获取对应商品的库存数量,并将其减 1。
- 复制对应商品的图片,并设置其样式属性,使其在页面上与原图片重叠。
- 将复制的图片添加到页面中,并以动画的形式将其移动到购物车图标处。
- 在动画结束后,将复制的图片从页面中移除,并将购物车中的商品数量增加 1。
-
如果对应商品的库存数量为 0,则弹出一个提示框,告诉用户该商品已经抢完了。
注意的要点
我这里单独拿出来解释。
- 因为不同的浏览器对于获取页面滚动距离的方式不同,所以这里使用了多个属性来获取页面的滚动距离,最终得到的值就是页面在垂直方向和水平方向上已经滚动的距离。
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; // 获取页面的滚动距离
var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
- 设置图片的定位方式,因为只有绝对定位,我们才能更好的通过知道它们的位置来进行移动。
var imgPosition = 'absolute';
- 图片位置的移动的实现
imgClone.style.transform = 'translate(' + (imgFinalLeft - imgLeft) + 'px, ' + (imgFinalTop - imgTop) + 'px)'; // 设置图片的最终变换
-
这行代码的作用是设置复制的图片的最终位置,具体来说:
imgFinalLeft和imgFinalTop分别表示购物车图标在页面中的左上角的横坐标和纵坐标,加上一些偏移量,就可以得到复制的图片的最终位置。imgLeft和imgTop分别表示复制的图片在页面中的左上角的横坐标和纵坐标,两者的差值就是复制的图片需要移动的距离。translate()函数可以将元素在平面上移动指定的距离,其中第一个参数表示横向移动的距离,第二个参数表示纵向移动的距离。
因此,imgClone.style.transform 的值就是一个 translate() 函数,它的参数是复制的图片需要移动的横向和纵向距离,这样就可以将复制的图片移动到购物车图标的位置。
js源码
// 获取所有的“加入购物车”按钮、商品图片、商品库存和购物车图标等元素
var cartBtns = document.querySelectorAll('.cart-btn'); // 获取所有的“加入购物车”按钮
var itemCount = document.querySelector('.item-count'); // 获取购物车中的商品数量显示元素
var cartNav = document.querySelector('.cart-nav'); // 获取购物车图标元素
var imgs = document.querySelectorAll('img') // 获取所有的商品图片
var ishave = document.querySelectorAll('h6') // 获取所有的商品库存元素
console.log(itemCount)
// 初始化购物车中的商品数量为 0
var count = 0;
// 遍历所有的“加入购物车”按钮,并为每个按钮添加一个 click 事件监听器
for (let i = 0; i < cartBtns.length; i++) {
var cartBtn = cartBtns[i];
cartBtn.addEventListener('click', function () {
// 判断对应商品的库存数量是否大于 0
var ishad = (ishave[i].textContent !== '已抢完');
if (ishad) {
// 复制对应商品的图片,并设置其样式属性,使其在页面上与原图片重叠
var imgToDrag = imgs[i];
var imgClone = imgToDrag.cloneNode(); // 复制图片
var imgRect = imgToDrag.getBoundingClientRect(); // 获取图片在页面中的位置和大小
var cartRect = cartNav.getBoundingClientRect(); // 获取购物车图标在页面中的位置和大小
//因为不同的浏览器对于获取页面滚动距离的方式不同,所以这里使用了多个属性来获取页面的滚动距离,最终得到的值就是页面在垂直方向和水平方向上已经滚动的距离。
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; // 获取页面的滚动距离
var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
var imgTop = imgRect.top + scrollTop; // 计算图片在页面中的绝对位置
var imgLeft = imgRect.left + scrollLeft;
var cartTop = cartRect.top + scrollTop;
var cartLeft = cartRect.left + scrollLeft;
var imgWidth = imgRect.width; // 获取图片的宽度和高度
var imgHeight = imgRect.height;
var imgOpacity = 0.8; // 设置图片的透明度
var imgPosition = 'absolute'; // 设置图片的定位方式
var imgZIndex = 100; // 设置图片的层级
var imgTransform = 'translate(0, 0)'; // 设置图片的初始变换
var imgTransition = 'transform 1s ease-in-out'; // 设置图片的动画效果
var imgFinalWidth = 75; // 设置图片最终的宽度和高度
var imgFinalHeight = 75;
var imgFinalTop = cartTop + 20; // 计算图片最终的位置
var imgFinalLeft = cartLeft + 30;
imgClone.style.opacity = imgOpacity; // 设置图片的透明度
imgClone.style.position = imgPosition; // 设置图片的定位方式
imgClone.style.width = imgWidth + 'px'; // 设置图片的宽度和高度
imgClone.style.height = imgHeight + 'px';
imgClone.style.zIndex = imgZIndex; // 设置图片的层级
imgClone.style.transform = imgTransform; // 设置图片的初始变换
imgClone.style.transition = imgTransition; // 设置图片的动画效果
imgClone.style.top = imgTop + 'px'; // 设置图片的初始位置
imgClone.style.left = imgLeft + 'px';
// 将复制的图片添加到页面中,并以动画的形式将其移动到购物车图标处
document.body.appendChild(imgClone);
setTimeout(function () {
imgClone.style.transform = 'translate(' + (imgFinalLeft - imgLeft) + 'px, ' + (imgFinalTop - imgTop) + 'px)'; // 设置图片的最终变换
imgClone.style.width = imgFinalWidth + 'px'; // 设置图片的最终宽度和高度
imgClone.style.height = imgFinalHeight + 'px';
}, 0);
// 在动画结束后,将复制的图片从页面中移除,并将购物车中的商品数量增加 1
setTimeout(() => {
// 获取对应商品的库存数量,并将其减 1 因为textContent是字符串'库存:1200'所以我们要正则拿到数值
var Number = parseInt(ishave[i].textContent.replace(/\D/g, ""));
count++; // 增加购物车中的商品数量
Number--;
ishave[i].textContent = '库存:' + Number // 更新对应商品的库存数量显示
itemCount.textContent = count; // 更新购物车中的商品数量显示
imgClone.parentNode.removeChild(imgClone); // 移除复制的图片
}, 1000)
} else {
// 如果对应商品的库存数量为 0,则弹出一个提示框,告诉用户该商品已经抢完了
alert('商品已经抢完了')
}
})
}
源码
希望大家能点个赞,谢谢!
源码自取地址掘金/购物车 · Mr-W-Y-P/Html-css-js-demo - 码云 - 开源中国 (gitee.com)