美文网首页
uniapp短视频APP继续改造升级:加入购物车与红包功能

uniapp短视频APP继续改造升级:加入购物车与红包功能

作者: 智密科技 | 来源:发表于2021-12-25 20:46 被阅读0次

    回顾上一次我们成功使用HbuilderX + uni-app + 智密原生仿抖音上下滑动插件创建了属于自己的第一个短视频App,在这里我给他取名瓜皮视频,然后我又使用了官方的demo进行了一波改造,接下来看看我们的瓜皮视频与抖音的对比图呗:

    实际还是有一些细微的区别的,但是呢相似度和流畅度已经算得上是不错的了。实现了基础的功能,我们不免要看看还有啥功能可以附带上。这里我们看了下,短视频App不免在视频页增加了“小红包”和“购物车”的功能,这是俩个流量收割利器,这里我们接着上回的项目,继续来扩展功能。


    小红包 界面分析

    智密原生仿抖音上下滑动插件使用的是给asv_list_player组件传入控件配置的方式去控制原生控件的展示,所以界面上很简单只有这写代码

    <template>

      <view>

        <asv_list_player ref="listPlayer" class="player"></asv_list_player>

        <bottom-popover v-if="showBottomPopover" ref="popover" @close="onClosePopover">

          <t-pop-commit-list></t-pop-commit-list>

        </bottom-popover>

      </view>

    </template>

    实现小红包

    在这里我们实现“小红包”的功能固然也可以使用传入控件配置的方式,但是考虑到还有红包进度条以及控制显隐,这里我们可以用nvue布局,自己实现一个红包控件,上代码

    <template>

      <view>

        <asv_list_player ref="listPlayer" class="player"></asv_list_player>

        <!-- 这下面就是我们新增的红包控件,为了方便我们使用了简单的组件,圈圈 + 红包 -->

        <view class="float-red-paper">

          <image class="float-red-paper-elem" mode="widthFix" src="../../static/icon_redPaper.png"></image>

        </view>

        <bottom-popover v-if="showBottomPopover" ref="popover" @close="onClosePopover">

          <t-pop-commit-list></t-pop-commit-list>

        </bottom-popover>

      </view>

    </template>

    .float-red-paper {

        position: fixed;

        top: 80px;

        left: 15px;

        width: 60px;

        height: 60px;

        align-items: center;

        justify-content: center;

        background-color: rgba(0, 0, 0, 0.6);

        border-radius: 100%;

      }

      .float-red-paper-elem {

        width: 40px;

      }

    在这里需要注意几点,首先nvue的控件是从上到下依次从前到后的层级排序的,并且无法通过zindex调整元素层级,因此我们插入“小红包”要在asv_list_player之后。css的话不支持层级语法,因此这里我们还是采用BEM命名的方式来写样式。现在我们看看加上“小红包”的效果,虽然这里我们还没添加完点击事件啥的,后面再来补充嘛。

    购物车 界面分析

    实现完成了小红包,接下来我们要实现购物车的功能,因为这里购物车是可能每个视频都会有的,并且每个视频关联的数据可能不一样,因此我们直接通过插件自带的配置JSON来处理。

    在这里我们构思的是将购物车设置在昵称简介下面,也就是绿色的区域,然后将昵称信息向上调整,也就是蓝色区域。

    asvListPlayer.getView('titleBox').isLayer().position(['left', 'bottom']).width(screenWidth * 0.6).height(100).bgc('#55000000').marginLeft(15).marginBottom(15).radius(10)

                .children([

                  asvListPlayer.getView('userBox').isLayer().position(['left']).width('100%').height('auto').marginLeft(10).marginTop(10)

                    .children([

                      asvListPlayer.getView('userIcon').isImage().position('left').width(15).height(15).marginTop(3).radius(10).toJSON(),

                      asvListPlayer.getView('userName').isText().position('left').width('100%').height(20).lines(2).color('#ffffff').marginLeft(20).toJSON(),

                    ])

                    .toJSON(),

                  asvListPlayer.getView('title').isText().position('left').width('100%').height('auto').color('#ffffff').marginLeft(10).marginTop(35).marginBottom(10).fontSize(14).marginRight(10).toJSON(),

                ])

                .toJSON(),

    在原先的配置中,昵称信息这里是距离底部15px,也就是如下代码

    asvListPlayer.getView('titleBox').isLayer().position(['left', 'bottom']).width(screenWidth * 0.6).height(100).bgc('#55000000').marginLeft(15).marginBottom(15)

    而我们需要给购物车留出大概40像素的地方,再加上上下间隔之后,我们把这块的15px调整成为75px就可以完美留出来购物车的地方,如下所示。

    asvListPlayer.getView('titleBox').isLayer().position(['left', 'bottom']).width(screenWidth * 0.6).height(100).bgc('#55000000').marginLeft(15).marginBottom(75)

    然后我这里直接给出购物车部分相关的代码,首先是json配置部分:

    asvListPlayer.getView('goodCar').isLayer().position(['left', 'bottom']).width(110).height(40).bgc('#55000000').marginLeft(15).marginBottom(15).radius(30)

                .children([

                  asvListPlayer.getView('goodCarImage').isImage().position(['left']).width(30).height(30).marginTop(5).marginLeft(5).toJSON(),

                  asvListPlayer.getView('goodCarText').isText().position(['left']).width(80).height(30).marginLeft(45).marginTop(5).lines(1).fontSize(16).color('#ffffff')

                ])

              .toJSON()

    这里我们设计大概是110px的宽度,然后购物车标记是30px,留出来80px左右的位置提供给视频,这里就先写上购物车三个字,然后这里我在给绑定数据部分的代码。

    this.genData().forEach(item => {

              let data = asvListPlayer.getItem(item.i)

                .video(item.v)

                .cover(item.c)

                .bindImage('head', 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3533321036,2623280788&fm=15&gp=0.jpg', true)

                .bindImage('like', item.like ? 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/c94c1a75-094a-482a-9acf-f1eefbd24792.png':'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/5a17a78c-f923-41f3-8916-271b4d5d528f.png')

                .bindText('likeText', parseInt((item.i * 1 + 1) * (new Date().getTime()) / 1000000000000) + '.4w')

                .bindImage('commit', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/003910f2-92cf-40c5-9d8a-870401be6e41.png')

                .bindText('commitText', parseInt((item.i * 1 + 1) * (new Date().getTime()) / 10000000000) + '')

                .bindImage('share', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/353edf1a-c2f1-481a-87fc-b9d5df98fb9e.png')

                .bindText('shareText', '分享')

                .bindText('userName', `UserName`)

                .bindImage('userIcon', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/89898f94-c3b8-4e14-9d06-7ccb1f27d3ab.png')

                .bindText('title', `这是第${item.i * 1}个视频,悄悄是离别的笙箫,沉默是今晚的康桥,再别康桥,再见我终将逝去的青春,愿一切安好,愿你永远都在。`)

                .bindImage('goodCarImage', 'https://files.qiadoo.com/CareBoBo/Common/2021/06/20/35177433-c373-49c7-8c21-f7db6c9d5c8f.png')

                .bindText('goodCarText', '购物车')

                .toJSON()

              datas.push(data)

            })

    这里新增的关键就是最后俩个,也就是下面俩个:

    .bindImage('goodCarImage', 'https://files.qiadoo.com/CareBoBo/Common/2021/06/20/35177433-c373-49c7-8c21-f7db6c9d5c8f.png')

    .bindText('goodCarText', '购物车')

    不得不说,插件本身已经帮我们做好大量配置的工作了,这里我只需要bindImage和bindText就可以将购物车标记的图片和文字绑定完成啦。虽然这里我们还没有绑定事件,但是长城也不是一日建成的,一步步扩展功能呗。先看看效果图。

    虽然不能说很完美,但是已经开始有那味道了,现在我把改造一半的代码直接给大家,有意思的可以继续接着扩展我们的瓜皮视频哦

    <template>

      <view>

        <asv_list_player ref="listPlayer" class="player"></asv_list_player>

        <view class="float-red-paper">

          <image class="float-red-paper-elem" mode="widthFix" src="../../static/icon_redPaper.png"></image>

        </view>

        <bottom-popover v-if="showBottomPopover" ref="popover" @close="onClosePopover">

          <t-pop-commit-list></t-pop-commit-list>

        </bottom-popover>

      </view>

    </template>

    <script>

      import asvListPlayer from './jssdk.js'

      import bottomPopover from './bottomPopover.nvue'

      import tPopCommitList from '../../components/nPopCommitList'

      export default {

        components: { bottomPopover, tPopCommitList },

        data() {

          return {

            asvListPlayer: false,

            viewHeight: uni.getSystemInfoSync().windowHeight - 50,

            presetCur: 0,

            list: [],

            loading: false,

            showBottomPopover: false

          }

        },

        onShow () {

          this.asvListPlayer && this.asvListPlayer.play()

        },

        mounted() {

          uni.$on('pause-video', () => {

            this.asvListPlayer.pause()

            this.showBottomPopover = false

          })

          //初始化

          this.$nextTick(e => {

            this.asvListPlayer = new asvListPlayer(this.$refs.listPlayer)

            // this.$refs.listPlayer.setScaleMode(0)

            let screenWidth = uni.getSystemInfoSync().screenWidth

            let views = [

              asvListPlayer.getView('rightBox').isLayer().position(['right', 'bottom']).width(60).height('auto').marginRight(15).marginBottom(15)

                .children([

                  asvListPlayer.getView('head').isImage().position(['right', 'bottom']).width(50).height(50).marginBottom(245).radius(30).toJSON(),

                  asvListPlayer.getView('like').isImage().position(['right', 'bottom']).width(50).height(45).marginBottom(185).radius(0).toJSON(),

                  asvListPlayer.getView('likeText').isText().position(['right', 'bottom']).width(50).height(20).marginBottom(165).textAlign('center').fontSize(14).toJSON(),

                  asvListPlayer.getView('commit').isImage().position(['right', 'bottom']).width(50).height(50).marginBottom(111).radius(0).toJSON(),

                  asvListPlayer.getView('commitText').isText().position(['right', 'bottom']).width(50).height(20).marginBottom(90).textAlign('center').fontSize(14).toJSON(),

                  asvListPlayer.getView('share').isImage().position(['right', 'bottom']).width(50).height(50).marginBottom(38).radius(0).toJSON(),

                  asvListPlayer.getView('shareText').isText().position(['right', 'bottom']).width(50).height(20).marginBottom(15).textAlign('center').fontSize(14).toJSON(),

                ])

                .toJSON(),

              asvListPlayer.getView('titleBox').isLayer().position(['left', 'bottom']).width(screenWidth * 0.6).height(100).bgc('#55000000').marginLeft(15).marginBottom(75).radius(10)

                .children([

                  asvListPlayer.getView('userBox').isLayer().position(['left']).width('100%').height('auto').marginLeft(10).marginTop(10)

                    .children([

                      asvListPlayer.getView('userIcon').isImage().position('left').width(15).height(15).marginTop(3).radius(10).toJSON(),

                      asvListPlayer.getView('userName').isText().position('left').width('100%').height(20).lines(2).color('#ffffff').marginLeft(20).toJSON(),

                    ])

                    .toJSON(),

                  asvListPlayer.getView('title').isText().position('left').width('100%').height('auto').color('#ffffff').marginLeft(10).marginTop(35).marginBottom(10).fontSize(14).marginRight(10).toJSON(),

                ])

                .toJSON(),

              asvListPlayer.getView('goodCar').isLayer().position(['left', 'bottom']).width(110).height(40).bgc('#55000000').marginLeft(15).marginBottom(15).radius(30)

                .children([

                  asvListPlayer.getView('goodCarImage').isImage().position(['left']).width(30).height(30).marginTop(5).marginLeft(5).toJSON(),

                  asvListPlayer.getView('goodCarText').isText().position(['left']).width(80).height(30).marginLeft(45).marginTop(5).lines(1).fontSize(16).color('#ffffff')

                ])

              .toJSON()

            ]

            console.log(views)

            this.asvListPlayer.setViewConfig({ views })

            this.onRefresh();

            this.asvListPlayer.on('onClick', this.onClick)

            this.asvListPlayer.on('onLoadMore', this.onLoadMore)

            this.asvListPlayer.on('onRefresh', this.onRefresh)

          })

        },

        methods: {

          uuid() {

            var s = [];

            var hexDigits = "0123456789abcdef";

            for (var i = 0; i < 36; i++) {

              s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);

            }

            s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010

            s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01

            s[8] = s[13] = s[18] = s[23] = "-";

            var uuid = s.join("");

            return uuid;

          },

          genData () {

            let len = this.list.length

            let presetDatas = [

              { v: 'http://txfile-30121.sz.gfp.tencent-cloud.com/1611758544058_4702548_5047449b104091e5dd3acfa00ed7eb99.mp4', c: 'http://txfile-30121.sz.gfp.tencent-cloud.com/1611758623279_1481920_89d5f27064f39fee56e663b050d28d8c.png' },

              { v: 'http://txfile-30121.sz.gfp.tencent-cloud.com/1603991410685_8240447_29b1d0770d6cdf43a1dd1fd3a992f96f.mp4', c: 'http://txfile-30121.sz.gfp.tencent-cloud.com/1604043258739_635757_8fd725d85d2b42ad1a8d878ef286d0bf.png' },

              { v: 'http://txfile-30121.sz.gfp.tencent-cloud.com/1604048716240_10046019_6566a337a503919c68f36a9fad9537b0.mp4', c: 'http://txfile-30121.sz.gfp.tencent-cloud.com/1604048732088_557815_c24e7f6276e650174494aa805fd7e45f.jpg' },

              { v: 'http://txfile-30121.sz.gfp.tencent-cloud.com/1604048722437_2185711_6da27ea482ecb28c549250d09c5abdf1.mp4', c: 'http://txfile-30121.sz.gfp.tencent-cloud.com/1604048734024_824230_198eb706d2052ddea6c2814adfe8d798.jpg' },

            ]

            let newDatas = []

            for (let i = len; i < len + 10; i++) {

              let item = JSON.parse(JSON.stringify(presetDatas[this.presetCur]))

              item.i = i + ''

              item.like = item.i % 3 === 0

              newDatas.push(item)

              this.presetCur = this.presetCur + 1

              if (this.presetCur >= presetDatas.length) {

                this.presetCur = 0

              }

            }

            this.list = this.list.concat(newDatas)

            return newDatas

          },

          onRefresh() {

            this.list = []

            this.presetCur = 0

            var datas = []

            this.genData().forEach(item => {

              let data = asvListPlayer.getItem(item.i)

                .video(item.v)

                .cover(item.c)

                .bindImage('head', 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3533321036,2623280788&fm=15&gp=0.jpg', true)

                .bindImage('like', item.like ? 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/c94c1a75-094a-482a-9acf-f1eefbd24792.png':'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/5a17a78c-f923-41f3-8916-271b4d5d528f.png')

                .bindText('likeText', parseInt((item.i * 1 + 1) * (new Date().getTime()) / 1000000000000) + '.4w')

                .bindImage('commit', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/003910f2-92cf-40c5-9d8a-870401be6e41.png')

                .bindText('commitText', parseInt((item.i * 1 + 1) * (new Date().getTime()) / 10000000000) + '')

                .bindImage('share', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/353edf1a-c2f1-481a-87fc-b9d5df98fb9e.png')

                .bindText('shareText', '分享')

                .bindText('userName', `UserName`)

                .bindImage('userIcon', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/89898f94-c3b8-4e14-9d06-7ccb1f27d3ab.png')

                .bindText('title', `这是第${item.i * 1}个视频,悄悄是离别的笙箫,沉默是今晚的康桥,再别康桥,再见我终将逝去的青春,愿一切安好,愿你永远都在。`)

                .bindImage('goodCarImage', 'https://files.qiadoo.com/CareBoBo/Common/2021/06/20/35177433-c373-49c7-8c21-f7db6c9d5c8f.png')

                .bindText('goodCarText', '购物车')

                .toJSON()

              datas.push(data)

            })

            this.asvListPlayer.loadDatas(datas)

          },

          onLoadMore() {

            if (this.loading) {

              return

            }

            this.loading = true

            var datas = []

            this.genData().forEach(item => {

              let data = asvListPlayer.getItem(item.i)

                .video(item.v)

                .cover(item.c)

                .bindImage('head', 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3533321036,2623280788&fm=15&gp=0.jpg', true)

                .bindImage('like', item.like ? 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/c94c1a75-094a-482a-9acf-f1eefbd24792.png':'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/5a17a78c-f923-41f3-8916-271b4d5d528f.png')

                .bindText('likeText', parseInt((item.i * 1 + 1) * (new Date().getTime()) / 1000000000000) + '.4w')

                .bindImage('commit', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/003910f2-92cf-40c5-9d8a-870401be6e41.png')

                .bindText('commitText', parseInt((item.i * 1 + 1) * (new Date().getTime()) / 10000000000) + '')

                .bindImage('share', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/353edf1a-c2f1-481a-87fc-b9d5df98fb9e.png')

                .bindText('shareText', '分享')

                .bindText('userName', `UserName`)

                .bindImage('userIcon', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/89898f94-c3b8-4e14-9d06-7ccb1f27d3ab.png')

                .bindText('title', `这是第${item.i * 1}个视频,悄悄是离别的笙箫,沉默是今晚的康桥,再别康桥,再见我终将逝去的青春,愿一切安好,愿你永远都在。`)

                .toJSON()

              datas.push(data)

            })

            this.asvListPlayer.loadMoreDatas(datas)

            setTimeout(e => {

              this.loading = false

            }, 1000)

          },

          onClick({ type, data }) {

            uni.showToast({

              icon: 'none',

              position: 'bottom',

              title: '您点击了第' + (data.position + 1) + '个视频的控件,控件名为:' + data.id

            })

            let index = data.position

            let [item] = this.list.filter((R,I) => I === index)

            switch (data.id) {

              case 'like':

                item.like = !item.like

                this.asvListPlayer.setItemData(index,asvListPlayer.getItem(item.i)

                  .video(item.v)

                  .cover(item.c)

                  .bindImage('head', 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3533321036,2623280788&fm=15&gp=0.jpg', true)

                  .bindImage('like', item.like ? 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/c94c1a75-094a-482a-9acf-f1eefbd24792.png':'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/5a17a78c-f923-41f3-8916-271b4d5d528f.png')

                  .bindText('likeText', parseInt((item.i * 1 + 1) * (new Date().getTime()) / 1000000000000) + '.4w')

                  .bindImage('commit', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/003910f2-92cf-40c5-9d8a-870401be6e41.png')

                  .bindText('commitText', parseInt((item.i * 1 + 1) * (new Date().getTime()) / 10000000000) + '')

                  .bindImage('share', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/353edf1a-c2f1-481a-87fc-b9d5df98fb9e.png')

                  .bindText('shareText', '分享66')

                  .bindText('userName', `UserName`)

                  .bindImage('userIcon', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/89898f94-c3b8-4e14-9d06-7ccb1f27d3ab.png')

                  .bindText('title', `这是第${item.i * 1}个视频,悄悄是离别的笙箫,沉默是今晚的康桥,再别康桥,再见我终将逝去的青春,愿一切安好,愿你永远都在。`)

                  .toJSON())

                break

              case 'commit':

                this.showBottomPopover = true

                break

              default:

                uni.showActionSheet({

                  itemList: ['分享到微信']

                })

                break

            }

          },

          onClosePopover (e) {

            this.showBottomPopover = false

          }

        }

      }

    </script>

    <style>

    .player {

    position: fixed;

    top: 0;

    bottom: 0;

    width: 750rpx;

    }

      .float-red-paper {

        position: fixed;

        top: 80px;

        left: 15px;

        width: 60px;

        height: 60px;

        align-items: center;

        justify-content: center;

        background-color: rgba(0, 0, 0, 0.6);

        border-radius: 100%;

      }

      .float-red-paper-elem {

        width: 40px;

      }

    </style>

    相关文章

      网友评论

          本文标题:uniapp短视频APP继续改造升级:加入购物车与红包功能

          本文链接:https://www.haomeiwen.com/subject/lexjqrtx.html