乐趣区

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

回顾上一次咱们胜利应用 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>
退出移动版