preface

When I was working on the project, I needed a barrage effect, but I didn’t find a suitable barrage library at that time, so I wrote a Vue-custom-Barrage myself. Here is the implementation principle of barrage library, you can also develop your own barrage library later.

Development capabilities

  1. Crash-free barrage
  2. Pause/start
  3. Custom ammunition display area
  4. Customize the barrage style and do not require innerHTML to prevent XSS attacks
  5. A full barrage also requires an FPS closer to 60

The basic idea

You can think of the bullet screen as an athlete, and then think of the screen as a playground, where the athletes are running on different tracks without interfering with each other.

There can be more than one athlete on the same runway. The time when the last athlete starts is when the first athlete enters the runway completely. It is not good for two athletes to run close to each other, so the athletes behind can wait and then enter the runway.

Crash-free barrage

When you watch the video, you will find that the length of the barrage must be different, and the speed is also different. Suppose there is an athlete A on the track, and we know the following data:

  1. Total length of runway: L
  2. Width: L1
  3. Total exercise time (refers to the length of running L + L1) : t
  4. Own starting time: T1
  5. Current time: T2
  6. Active duration: T3 = T2-T1
  7. Remaining exercise duration: T4 = T-T3
  8. Velocity: V1 = (L + L1)/t

The extreme collision position between athlete B and Athlete A is on the far left of the track:

We can know the data of player B:

  1. Width: L2
  2. Maximum speed: V2 = L/T4
  3. Total duration of exercise: T5 = (L + L2)/v2

In this way, we can successively calculate the maximum speed of the next barrage, so that all the barrage will not collide.

Pause/start

For our motion animation, we use animation, because CSS variables have inherited effects, so we just set the container style and all the bullets will stop or continue:

/ / set the container style container. Style. SetProperty (' - playState, suspended | |)Copy the code
// Barrage {animation: XXX; animation-play-state: var(--playState); }Copy the code

However, note that the current time should be recorded when pausing and playing each time to calculate the movement time of each barrage, otherwise the following barrage will collide

Custom ammunition display area

This is to create a separate runway class, each runway will look for new barrage, if there is to add their own runway, so we know to close the runway observation, can be done to show specific areas.

Custom barrage style

Because a barrage doesn’t have to be just text, it can have a lot of user-defined stuff. I’ve seen some of the innerHTML in the barrage library before, but this can lead to XSS attacks, which we can easily do by standing on the shoulders of giants. Here’s a Vue example:

{{data}}</div> </template> </Barrage>Copy the code
// Get the contents of the slot in the barrage component, $scopedslot.default (data) // Get a Vue subclass const BarrageVNode = Vue. Extend ({render(h) {  return h('div', Slots)}}) // Get the vm const barrageInstance = new BarrageVNode().$mount() // append to container. Append (barrageDom.$el)Copy the code

So no matter what the user wants to do.

fps

We use animation and Transform to generate the animation, because the transform animation will be promoted to the composition layer, which will trigger GPU acceleration, and layout and paint will not be triggered during the animation process, so the performance is very high:

extension

When you look at Station B, you will find that the barrage does not block the people in the video. Here is how it is achieved.

The effect

cutout

The front end will constantly request the character matting of the current video, and the character matting of each frame of the video should be done by machine learning.

CSS implementation

He added a mask-image attribute to the barrage container, and the URL corresponds to the figure figure just picked out. Such a simple attribute realized the effect of shielding the barrage

Local test

I went to put the previous character matting into the local test effect, exactly the same.

.container { position: relative; border: 1px solid; width: 600px; height: 600px; } .masked { position: absolute; z-index: 2; width: 100%; height: 100%; -webkit-mask-image: url("data:image/svg+xml; base64,PHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKIHdpZHRoPSIyOTUuNDg4ODYyODM3MDQ1N3B4IiBoZ WlnaHQ9IjUyMnB4IiB2aWV3Qm94PSIwIDAgMTgwLjAwMDAwMCAzMjAuMDAwMDAwIgogcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQgbWVldCI+CjxnI HRyYW5zZm9ybT0idHJhbnNsYXRlKDAuMDAwMDAwLDMyMC4wMDAwMDApIHNjYWxlKDAuMTAwMDAwLC0wLjEwMDAwMCkiCmZpbGw9IiMwMDAwMDAiIHN0cm9rZ T0ibm9uZSI+CjxwYXRoIGQ9Ik0wIDE2MDUgbDAgLTE1OTUgMjQxIDAgMjQxIDAgLTcgMTEzIGMtMyA2MSAtMTEgMTQxIC0xOCAxNzYgLTE0IDc3IDYgMjE0I DUyCjM1NiA2MCAxODIgNjIgMTk0IDY2IDMzOCA1IDEzMyAtNiAyNDcgLTI0IDI0NyAtOSAwIC00MSAtNTUgLTQxIC03MSAwIC0yNQotNTQgLTgyIC05NiAtM TAxIC02MyAtMjcgLTg4IC0xMyAtMTI3IDc1IC0zMCA2OCAtMzAgNjkgLTE4IDE1MCAyMCAxMjkgNTgKMjY4IDg4IDMyMyAzNiA2NSA5OCAxMjAgMTYwIDE0M iA0NyAxNyA3NyAzMyAxNzYgOTUgNjQgNDEgNzcgODUgNTAgMTcyIC0xMwo0NCAtMTggOTEgLTE4IDE3NSAwIDEwNSAzIDEyMCAyOCAxNzIgMzIgNjQgNzIgO TkgMTM4IDExNyA0MiAxMiA1MCAxMSA5NCAtMTEKNDQgLTIxIDUwIC0yOSA3MiAtODggMjQgLTYzIDQ5IC0xNTIgNTkgLTIxNSA0IC0yMiAtMiAtNDIgLTI0I C03NSAtNjQgLTk2Ci00OCAtMTgyIDQzIC0yMzIgNzggLTQyIDE4OCAtOTUgMjEyIC0xMDIgMzggLTEyIDkyIC04OSAxMDggLTE1OCA5IC0zNSAyNwotOTkgN DAgLTE0MyAxMyAtNDQgMzggLTE0NyA1NSAtMjMwIDE2IC04MiAzNSAtMTcyIDQwIC0xOTggMTEgLTU1IDEzIC0xMTUgNAotMTcwIC02IC0zMiAtMTAgLTM3I C0zMyAtMzcgLTI4IDAgLTYxIC0zMCAtNjEgLTU1IDAgLTkgMTcgLTIwIDQ1IC0yNyA0OSAtMTMKNTAgLTE1IDMzIC03MyAtNiAtMjIgLTExIC00MyAtMTAgL TQ3IDMgLTEzIC0yNiAzIC0zMiAxOCAtNCAxMCAtMTQgMTIgLTMwIDgKLTMzIC04IC00MCAxNiAtMzkgMTM0IDEgMTA5IC0xNSAxNzMgLTQ0IDE4NiAtMjQgM TEgLTU3IDc5IC03MyAxNTAgLTIwIDkwCi00MyAxMTEgLTU1IDQ5IC01IC0yNiAtOSAtMzMgLTE1IC0yMyAtMTYgMjcgLTIwIC0xMCAtMTYgLTE1MCAzIC0xM TggOCAtMTQ4CjM2IC0yMzUgMzcgLTExNCA3MSAtMjQxIDkyIC0zMzUgMTIgLTUzIDE5IC02NyA0MSAtNzggMTYgLTggMjcgLTIxIDI3IC0zMyAwCi0xMSA3I C0yMiAxNSAtMjUgMTggLTcgMTkgLTUxIDIgLTExNyBsLTEyIC00OCAtMzkgNDcgYy0zOCA0NSAtMzkgNDYgLTU4IDI3Ci0xNSAtMTUgLTIwIC0zNyAtMjIgL TEwNiBsLTQgLTg3IDIyOSAwIDIyOSAwIDAgMTU5NSAwIDE1OTUgLTkwMCAwIC05MDAgMCAwCi0xNTk1eiIvPgo8L2c+Cjwvc3ZnPgo="); } .val { position: absolute; left: 20px; top: 130px; } <div class="container"> <div class="masked"> <div class="val">Copy the code

The last

You can learn from or use my Vue-custom-Barrage, a basic barrage function which I mentioned above. If you have any questions, please feel free to contact me in the comments section.