vue——实现飞入购物车效果(重点在于获取元素的位置)

昨天项目负责人问我能否在电商项目中加入购物车时,加一个飞入购物车的功效。

这个效果其实是比较常见的,之前我也有遇到这种需求,因为不太熟,直接拒绝。现在还是想办法实现一下吧。

效果图如下:
在这里插入图片描述

当点击购物车动画按钮时,在商品图部分出现一个图片,这个图片会沿一定的轨迹,飞到购物车中,此时会调取加入购物车接口,购物车中的数值会加1。

基本功能就是这样:

飞入购物车最重要的就是获取元素的位置

其实对于动画,我们已知的就是:animationtransition,都可以实现动画,现在的重点就是如何获取元素的位置。

1.商品图的位置(点击的是右侧的按钮)

关于这个图片,我是这样处理的,我在页面最外面的一层中添加了一个img元素,然后给元素添加position:absolute,则此元素就是脱离文档流的浮动于整个页面之上的元素了。通过修改元素的lefttop值,就可以改变图片的位置了。

在这里插入图片描述

1.点击的是购物车动画的按钮,可以从此按钮入手,找到对应的图片的位置

在这里插入图片描述
如果要获取当前点击元素的位置,则可以将$event传入到点击事件中:

我们是需要获取当前元素距离整个页面顶部的距离,然后赋值给商品图片的top就可以了。

因此此时需要用到下面的函数,获取某一个元素距离整个页面顶部的距离:

2.通过递归的方式获取元素到页面顶部的距离
 getElementTop(element) {
    var actualTop = element.offsetTop;    //这是获取元素距父元素顶部的距离
    var current = element.offsetParent;   //这是获取父元素
    while(current !== null) {      //当它上面有元素时就继续执行
        actualTop += current.offsetTop;   //这是获取父元素距它的父元素顶部的距离累加起来
        current = current.offsetParent;  //继续找父元素
      }
    return actualTop;
}

offsetTop可以获取当前元素距离父级元素的距离,然后通过递归,不停的找元素的父级,并将距离相加,最终就可以拿到当前元素距离整个页面的高度了。

同理:元素距离页面左边的距离也可以获取到:

getElementLeft(element) {
    var actualLeft = element.offsetLeft;    //这是获取元素距父元素顶部的距离
    var current = element.offsetParent;   //这是获取父元素
    while (current !== null) {      //当它上面有元素时就继续执行
        actualLeft += current.offsetLeft;   //这是获取父元素距它的父元素顶部的距离累加起来
        current = current.offsetParent;  //继续找父元素
    }
    return actualLeft;
}

整合上面的代码如下:

var top = this.getElementTop(el);
var left = this.getElementLeft(el);

由于页面的整体布局,按钮左边距离商品图片的距离是1100左右,因此我可以拿到按钮元素距离页面左边的距离后,减去1100,就可以获取到对应图片的位置了。(图片的位置也就是:lefttop)

此时是有一个问题的,因为el-buttonelementUi中的组件,最终渲染完成的html结构中其实是一个button包含span标签,如果点击的元素是span,则上面说的距离1100就不准了。
所以此时需要找到这个button,保证拿到的位置left topbutton的数值。

3.当前点击的元素需要保证是button
var el = e.currentTarget || e.target;
var tagName = e.target.tagName;//可以根据这个tagName来进行判断
if (tagName == 'SPAN') {//如果当前点击的是中间的文字部分,也就是span标签
    el = el.closest("button");//则需要找到最近的button标签,也就是我们想要的标签
}
4.最终找到对应的图片的位置
var el = e.currentTarget || e.target;
var tagName = e.target.tagName;
if (tagName == 'SPAN') {
    el = el.closest("button");
}
console.log(e.target.tagName,el, el.tagName);
var top = this.getElementTop(el);
var left = this.getElementLeft(el);![在这里插入图片描述](https://img-blog.csdnimg.cn/ee88915933214c1590b40977de611214.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3llaGFvY2hlbmc1MjA=,size_16,color_FFFFFF,t_70)

this.$refs['donghuaImg'].style.left = left-1100+'px';//具体数值可以微调一下
this.$refs['donghuaImg'].style.top = top-20+ 'px';//具体数值可以微调一下
this.$refs['donghuaImg'].style.width = "68px";//设置一下宽高,因为动画结束后,宽高设置了为0,因此再次点击时需要恢复原有的宽高
this.$refs['donghuaImg'].style.height = "67px";

到这里为止,找到图片的初始位置了

接下来需要找到图片的最终位置:
在这里插入图片描述

1.页面滚动的距离计算

页面滚动的距离可以通过:document.documentElement.scrollTop来计算

2.固定定位的元素距离页面顶部的距离

还是用最上面的计算距离的函数,这个元素的refcartLan
this.getElementTop(this.$refs['cartLan']);

var topEnd = document.documentElement.scrollTop + cartTop+30;
3.获取元素距离浏览器左侧的距离,可以通过getBoundingClientRect来处理
var leftEnd = this.$refs['cartLan'].getBoundingClientRect().left+30;

最终代码如下:

this.$refs['donghuaImg'].style.transition = "";
this.$refs['donghuaImg'].style.border = "2px solid #f90";
this.srcImg = row.ProPic || '/Content/img/common/pic_big.jpg';
var el = e.currentTarget || e.target;
var tagName = e.target.tagName;
if (tagName == 'SPAN') {
    el = el.closest("button");
}
console.log(e.target.tagName,el, el.tagName);
var top = this.getElementTop(el);
var left = this.getElementLeft(el);
this.$refs['donghuaImg'].style.left = left-1097+'px';
this.$refs['donghuaImg'].style.top = top-20+ 'px';
this.$refs['donghuaImg'].style.width = "68px";
this.$refs['donghuaImg'].style.height = "67px";
var cartTop = this.getElementTop(this.$refs['cartLan']);
//上面的是初始化大小和位置
setTimeout(() => {
	//之后给定动画,并获取终点的位置
    this.$refs['donghuaImg'].style.transition = 'all 0.5s linear,top 0.5s cubic-bezier(.8,0,.94,.28)';
    var leftEnd = this.$refs['cartLan'].getBoundingClientRect().left+30;
    var topEnd = document.documentElement.scrollTop + cartTop+30;
    setTimeout(() => {
    	//指定终点的大小和购物车的动画
        this.$refs['donghuaImg'].style.width = "20px";
        this.$refs['donghuaImg'].style.height = "20px";
        this.$refs['donghuaImg'].style.left = leftEnd + 'px';
        this.$refs['donghuaImg'].style.top = topEnd + 'px';
        this.$refs['cartImg'].style.animation = 'shakeface .5s 0.3s';
        //之后隐藏商品图,也就是将图片大小置为0,边框去除
        setTimeout(() => {
            this.$refs['donghuaImg'].style.width = "0px";
            this.$refs['donghuaImg'].style.height = "0px";
            this.$refs['donghuaImg'].style.border = '0px solid #f90';
            setTimeout(() => {
                this.$refs['cartImg'].style.animation = '';
            }, 1000)
        }, 10)
    }, 20)
}, 10)

现在感觉购物车的位置还是有点不太懂,这个花了我很多时间。因为js实在是有点差……

购物车的位置可以通过下面的方式来计算

整个浏览器可视区域的高度:document.documentElement.clientHeight
页面如果超过一屏高度后,会出现滚动,则整个页面的整体高度就是一屏的高度+滚动条滚动的高度
滚动条滚动的高度:document.documentElement.scrollTop
在这里插入图片描述
var topEnd = document.documentElement.scrollTop + document.documentElement.clientHeight - 250;具体数值可以最后微调一下

最终显示效果也是可以的。这样是比较好理解的一种方式了……

完成!!!!

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叶浩成520

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值