If there is a miracle in life, it must be the path of hard work!Copy the code

Hello, everyone. I am Koba, an ordinary front-end development engineer who is unwilling to be ordinary

Hey hey hey, good brothers, is not very unexpected, the series of articles suddenly updated !!!!

Actually, there are two reasons.

One is that Hiro even came out, and I almost eunuchs my first series, which made me feel devastated.

The other is to see partners’ enthusiasm for learning, I did not expect to break more than half a year, or a lot of partners to come up and chat with Koha, Koha is still very happy. Koha is currently moving to the React stack, but in order to live up to her friends’ expectations for this series of articles, she will first improve the main process.

This topic is mainly to talk with friends about how to achieve the bullet barrage orbit.

1. What is a barrage track?

In the last issue, we have simply implemented the function of bullet screen, but there is a problem that all bullet screen are played on the same horizontal line. When the number of bullets is a little too large, it is not clear what is in the bullets. Then, is there any way for us to realize the full-screen bullet-screen broadcasting similar to the live broadcasting platform, without affecting other bullet-screens as much as possible?

The answer is yes, koha calls it barrage orbit.

As shown in the figure below, the visual area of our live video screen is dynamically divided into several tracks. Then we randomly push our barrage to these barrage tracks, and then the barrage moves from the right side to the left in order to complete the function of our barrage.

2. Added missile barrage track component

SRC /views/live added barragestream.vue

<! -- * @description: * @author: Koha * @Lasteditors: Koha * @Date: 2021-06-07 21:53:30 * @LasteditTime: The 2021-06-08 23:53:25 -- -- >
<template>
  <div class="barrage-stream" ref="barrageStream">
    
  </div>
</template>

<script>
import { mapState, mapMutations } from "vuex";
export default {
  name: "barrageStream".data() {
    return {
      barrageStreamRect: {},
      barrageStreamList: [].// Barrage track
      barrageStreamListNum: null.// The number of projectile tracks
    };
  },
  computed: {
    ...mapState({
      barrageMsgList: (state) = > state.barrage.barrageMsgList,
    }),
  },
  methods: {},watch: {},mounted(){}};</script>

<style lang="less" scoped>
.barrage-stream {
  position: absolute;
  width: 100%;
  height: 100%;
  overflow: hidden;
  z-index: 9999;
  .barrage-block {
    z-index: 1;
    position: relative;
    height: 40px;
    //border-bottom: #fff 1px solid;
    width: 100%;
    color: #fff;
    &-item {
      position: absolute;
      display: inline-block;
      width: 200px;
      animation: barrage 5s linear;
      animation-fill-mode: forwards; }}}@keyframes barrage {
  from {
    left: 100%;
    transform: translateX(0);
  }
  to {
    left: 0;
    transform: translateX(-200%); }}</style>
Copy the code

3. Dynamically calculate the number of projectile trajectory

Why dynamically count the number of projectile trajectories? I directly write the number of dead tracks, simple and quick, it does not smell??

Good brothers, think about it, we now screen variety is not a lot, and then the size of the resolution is not the same, right? The number of projectile trajectories displayed in different resolutions must be different, right? In addition, our users may not be watching the live broadcast in full screen. Maybe he’d like to open a little window to see it. In order to solve this kind of problem, we need to dynamically calculate the number of projectile trajectory.

GetBoundingClientRect () = getBoundingClientRect()

This method returns the size of the element and its position relative to the window.

In the standard box-sizing: content-box model, the size of the element is equal to the sum of width/height + padding + border-width. In box-sizing: border-box, the size of the element equals width/height.

Simply obtain the DOM structure of our live video area by ref/ ID, and then call getBoundingClientRect() to output it in the console. You can see that you get the width and height of the DOM structure and its position in the window.

Combined with the height of the bullet screen and the height of the display area of the bottom player bar, it is not difficult to get such a method

methods: {
    // Get the number of streams played in the barrage track
    getBarrageStreamList() {
      console.log(this.$refs.barrageStream.getBoundingClientRect());
      // Get the dom element information
      this.barrageStreamRect = this.$refs.barrageStream.getBoundingClientRect();
      // Count the number of tracks
      this.barrageStreamListNum = Math.floor(
        (this.barrageStreamRect.height - 100) / 36
      );
      // Initialize the track
      this.barrageStreamList = [];
      for (let i = 0; i < this.barrageStreamListNum; i++) {
        this.barrageStreamList.push([]);
      }
      console.log(this.barrageStreamList); }},Copy the code

Ok, now that we have the method, when should we call it?

Should we call it when we initialize it? So plus.

mounted() {
    this.getBarrageStreamList();
  },
Copy the code

But now the problem is, some users like to be naughty, like to scale the browser arbitrarily, so we initialize the wrong number of tracks, what do we do?

In fact, very simple, we just need to monitor the size of the window changes.

So what methods do I need to use to monitor window changes?

window.addEventListener("resize",function())

Now that we’ve added a listener, shouldn’t we remove it when we leave the component?

How do you remove it?

window.removeEventListener("resize",function())

Ok, so we can easily get the following code

mounted() {
    this.getBarrageStreamList();
    window.addEventListener("resize".this.getBarrageStreamList);
  },
  beforeDestroy() {
    window.removeEventListener("resize".this.getBarrageStreamList);
  },
Copy the code

4. Randomly assign a barrage to a barrage orbit

Q: When do I need to assign a barrage to orbit?

A: When the barrage is added.

Q: How do I know if the data changes in the barrage?

A: Listen for the barrage array in vuEX

Therefore, the distribution of bullets should be implemented in the monitor.

Insert a VUE interview question: How do YOU listen for changes in an array in VUE? And how to initialize the listener?

The answer is simple: JS contains basic data types and reference data types, while Watch monitors the change of basic data types by default. For reference data types, it only monitors the corresponding storage address, not the data in the array. When we want to listen on the data in the array, add deep:true to implement deep listening. To initialize the listener, add another parameter, immediate:true

And then how do we get random orbitals?

We can combine math.random () and push the barrage into our random orbit.

In order to save on the cost of subsequent rendering, shouldn’t the barrage we’ve shown continue to exist in our DOM?

So use setTimeout to remove those rendered bullets.

You end up with the following code

watch: {
    barrageMsgList: {
      handler(newval) {
        if (newval.length) {
          // Get the random orbital subscript
          let randomNum = Math.floor(Math.random() * this.barrageStreamListNum);
          // Put the projectile into a random orbit
          this.barrageStreamList[randomNum].push(newval[newval.length - 1]);
          // Delete the barrage after 5s delay. (The time is related to the playing time of the barrage)
          setTimeout(() = > {
            this.barrageStreamList[randomNum].shift();
          }, 5000); }},deep: true,}},Copy the code

5. Render barrage

Modify the code in template and save.

<template>
  <div class="barrage-stream" ref="barrageStream">
    <div
      class="barrage-block"
      v-for="(stream, streamIndex) of barrageStreamList"
      :key="'barrageStreamList' + streamIndex"
    >
      <div
        class="barrage-block-item"
        v-for="(item, index) of stream"
        :key="'barrage-block-item' + index"
      >
        {{ item.msg }}
      </div>
    </div>
  </div>
</template>
Copy the code

Open the page, input barrage, barrage track out

However, my friends, after careful observation, I regret to find that some bullets have disappeared before the end of playing. How is this happening?

Koha will answer a vUE interview question here

Why is index not recommended as the key in V-for?

This is mainly because array operations cause display exceptions.

Let’s explain it with our barrage.

This is mainly because the key value is bound to the index value, as shown in the figure below, whereas some CSS styles are bound to the index value. When we delete a value from the array, the key and index values rebind the content of our barrage, and the style changes accordingly, causing this display exception.

To solve this problem, it is easy to use index as the key.

<template>
  <div class="barrage-stream" ref="barrageStream">
    <div
      class="barrage-block"
      v-for="(stream, streamIndex) of barrageStreamList"
      :key="'barrageStreamList' + streamIndex"
    >
      <div class="barrage-block-item" v-for="item of stream" :key="item.id">
        {{ item.msg }}
      </div>
    </div>
  </div>
</template>
Copy the code

Modified send barrage method (add a random number as the id), paths SRC/views/live/barrage. Vue

// Send a barrage
    chatLiveRoom() {
      console.log(this.currentUser);
      if (!this.currentUser.id) {
        this.$Message.error("Please login to speak again ~");
      } else if (this.battageMsg) {
        let data = {
          room: this.livingRoom,
          func: "chatLiveRoom".data: {
            id: common.getCode(8),
            user: this.currentUser.name,
            msg: this.battageMsg,
          },
        };
        this.$sockBarrage.roomChat(data);
        this.battageMsg = "";
      } else {
        this.$Message.error("Please enter the content of the barrage!"); }},Copy the code

summary

It has been half a year since Koha last wrote this series.

Really long, long enough for Kohane to forget the code.

Plus came to a new company, work or more busy.

But I took some time to look at the code and the content of previous issues, and finally nibbled out the article of this issue.

Think about it or sad, ha ha ha.

If you feel good after reading this series of articles, you can like it and follow it

If you want to communicate with Koha, you can add WX, also welcome friends to talk with Koha, hey, hey ~

Ps: pure original, reproduced please indicate the source

Github link, if you can help to point a small star, thank you ~

Front end: github.com/sulgweb/myl…

The backend: github.com/sulgweb/myl…