uniapp short video APP continues to be transformed and upgraded: shopping cart and red envelope functions are added

Tiktok: last time we successfully created our first short video App using HbuilderX + uni-app + smart tiktok, the first one, and I named him the skin melon video. Then I used the official demo to make a transformation. Next, let's look at the comparison between our skin and the sound.

In fact, there are still some subtle differences, but the similarity and fluency are good. After realizing the basic functions, we have to see what other functions can be attached. Here we have a look. The short video App inevitably adds the functions of "small red envelope" and "shopping cart" on the video page. These are two traffic harvesting tools. Here we continue to expand the functions of the last project.

Small red envelope interface analysis
The tiktok is the original asv_. list_ The player component controls the display of the native control by passing in the control configuration, so the interface is very simple. This is the only way to write code

<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>

Realize small red envelopes
Here we can realize the function of "small red envelope". Of course, we can also use the way of incoming control configuration, but considering the red envelope progress bar and control display and concealment, we can use nvue layout to realize a red envelope control by ourselves and code it

<template>
  <view>
    <asv_list_player ref="listPlayer" class="player"></asv_list_player>
    <!-- Here is our new red envelope control. For convenience, we use a simple component, circle + Red envelopes -->
    <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;
  }

Here are a few points to note. First, nvue's controls are sorted from top to bottom, from front to back, and the element level cannot be adjusted through zindex. Therefore, we insert the "small red envelope" in ASV_ list_ After the player. css does not support hierarchical syntax, so we still use BEM naming to write styles here. Now let's see the effect of adding "small red envelope". Although we haven't added click events here, we'll add them later.

Shopping cart interface analysis
After the implementation of the small red envelope, we need to realize the function of the shopping cart, because here the shopping cart may be available for each video, and the data associated with each video may be different, so we directly process it through the configuration JSON provided by the plug-in.

Here, our idea is to set the shopping cart under the nickname introduction, that is, the green area, and then adjust the nickname information upward, that is, the blue area.

Implement shopping cart
First of all, we have to look at the original configuration before transformation.

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(),

In the original configuration, the nickname information here is 15px from the bottom, that is, the following code

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

We need to set aside about 40 pixels for the shopping cart. After adding the up-down interval, we can adjust the 15px to 75px to perfectly leave the shopping cart, as shown below.

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

Then I will directly give the relevant codes of the shopping cart. First, the json configuration part:

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()

Here, we design a width of about 110px, and then the shopping cart mark is 30px, leaving a position of about 80px for the video. Here, first write the three words of the shopping cart, and then I'm giving the code of the binding data part.

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', 'share')
            .bindText('userName', `UserName`)
            .bindImage('userIcon', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/89898f94-c3b8-4e14-9d06-7ccb1f27d3ab.png')
            .bindText('title', `This is the second ${item.i * 1}A video, quietly is a farewell Sheng Xiao, silence is Cambridge tonight, goodbye to Cambridge, goodbye to my lost youth, may everything be well, and may you always be there.`)
            .bindImage('goodCarImage', 'https://files.qiadoo.com/CareBoBo/Common/2021/06/20/35177433-c373-49c7-8c21-f7db6c9d5c8f.png')
            .bindText('goodCarText', 'Shopping Cart')
            .toJSON()
          datas.push(data)
        })

The last two keys are added here, that is, the following two:

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

I have to say that the plug-in itself has helped us do a lot of configuration work. Here, I only need bindImage and bindText to bind the image and text of the shopping cart tag. Although we haven't bound events here, the Great Wall wasn't built in a day, so we expanded its functions step by step. Look at the renderings first.

Although it can't be said to be perfect, it has begun to taste like that. Now I give you half of the modified code directly. Interestingly, we can continue to expand our melon skin video.

<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
      })
      //initialization
      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', 'share')
            .bindText('userName', `UserName`)
            .bindImage('userIcon', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/89898f94-c3b8-4e14-9d06-7ccb1f27d3ab.png')
            .bindText('title', `This is the second ${item.i * 1}A video, quietly is a farewell Sheng Xiao, silence is Cambridge tonight, goodbye to Cambridge, goodbye to my lost youth, may everything be well, and may you always be there.`)
            .bindImage('goodCarImage', 'https://files.qiadoo.com/CareBoBo/Common/2021/06/20/35177433-c373-49c7-8c21-f7db6c9d5c8f.png')
            .bindText('goodCarText', 'Shopping Cart')
            .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', 'share')
            .bindText('userName', `UserName`)
            .bindImage('userIcon', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/89898f94-c3b8-4e14-9d06-7ccb1f27d3ab.png')
            .bindText('title', `This is the second ${item.i * 1}A video, quietly is a farewell Sheng Xiao, silence is Cambridge tonight, goodbye to Cambridge, goodbye to my lost youth, may everything be well, and may you always be there.`)
            .toJSON()
          datas.push(data)
        })
        this.asvListPlayer.loadMoreDatas(datas)
        setTimeout(e => {
          this.loading = false
        }, 1000)
      },
      onClick({ type, data }) {
        uni.showToast({
          icon: 'none',
          position: 'bottom',
          title: 'You clicked page' + (data.position + 1) + 'A video control named:' + 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', 'Share 66')
              .bindText('userName', `UserName`)
              .bindImage('userIcon', 'https://files.qiadoo.com/CareBoBo/Common/2021/05/17/89898f94-c3b8-4e14-9d06-7ccb1f27d3ab.png')
              .bindText('title', `This is the second ${item.i * 1}A video, quietly is a farewell Sheng Xiao, silence is Cambridge tonight, goodbye to Cambridge, goodbye to my lost youth, may everything be well, and may you always be there.`)
              .toJSON())
            break
          case 'commit':
            this.showBottomPopover = true
            break
          default:
            uni.showActionSheet({
              itemList: ['Share to wechat']
            })
            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>

Keywords: Javascript Vue.js uni-app uniapp

Added by mickey9801 on Mon, 03 Jan 2022 22:48:30 +0200