Recently, a function similar to the effect of bullet screen was developed in the project. Before making the function, I read “Javascript Design Patterns and Development Practices”, and after finishing it, I looked at the code and found that these were design patterns.

The so-called barrage effect is like this, normal and picture barrage move from right to right.

The initial idea was to use Canvas, but in the middle of the implementation, WE decided to use DOM node after consideration. The main consideration is that it is troublesome for Canvas to draw background, border-radius, load pictures and click events.

The whole idea of my bullet screen effect is as follows:

The controller is the center of harmonic relation and event distribution. It traverses the runway in every frame of Raf, finds the runway in idle state, obtains content from the content center, generates the corresponding carrier subclass according to the content type, initializes the subclass according to the runway, and sets the runway as BUSY.

In this requirement, barrage can be divided into two types, text barrage and picture barrage, both of which inherit from a Carrier parent class Carrier, which has initialization, boundary judgment, event monitoring and other methods, while subclasses only need to be responsible for their own init and render methods.

The barrage starts at the starting line, and when the whole thing passes the starting line, the start_OFF event is triggered, and all listeners of this event (currently only the runway) are notified that the runway can change its state to idle.

When the whole barrage passes the end point, the die event will be triggered, and then the carrier pool will be notified to recycle itself and throw the content back to the content center, waiting to be flipped again.

The carrier pool is a carrier generation factory that returns the corresponding barrage according to the type required by the processor. The returned barrage can be generated from two sources, one is through New and the other is through recycle.

People with God’s vision see this:

Design patterns used

Factory mode and Share mode

Vectors are created in the vector pool, but the vector pool here does not care what is created, just according to the required type and the corresponding constructor, the corresponding relationship is passed in when the vector pool is initialized. This has the advantage of eliminating the need to put type judgments and constructors into the controller. The outside world doesn’t have to know how to produce. I’ll give you what you want.

lerp (value1, value2, amount) {
  amount = amount < 0 ? 0 : amount
  amount = amount > 1 ? 1 : amount
  return value1 + (value2 - value1) * amount
}Copy the code

In addition to creation, the carrier pool also has the function of recycling. Because DOM nodes are expensive, we do not want each independent danmu to be a new DOM, so the carrier pool will also share the generated danmu to avoid the generation of redundant DOM nodes.

lerp (value1, value2, amount) {
  amount = amount < 0 ? 0 : amount
  amount = amount > 1 ? 1 : amount
  return value1 + (value2 - value1) * amount
}Copy the code

Observer model

The carrier parent class implements a simple observer mode, registering events once, clearing all listeners with notify, triggering events in each frame’s edge detection, and notifying listeners (in this case callback).

lerp (value1, value2, amount) {
  amount = amount < 0 ? 0 : amount
  amount = amount > 1 ? 1 : amount
  return value1 + (value2 - value1) * amount
}Copy the code

The proxy pattern

Because DOM is used and uniform bullet screen effect is achieved, for better performance, I didn’t put the offset of translate3D into the container, the bullet screen only sets its offset value relative to the container when initialization, which is not particularly obvious proxy mode ~

The proxy mode is to hand over to a third party the transactions that are inconvenient to be handled by itself, such as click events here. It is described in the requirements document that the picture bullet screen should be able to click to view the larger picture. If all bullet screens are bound with click events, the events should be unbound or replaced when the bullet screen is recovered or removed. Consider using an event broker, which only adds click event bindings to the container and determines the barrage in the click event callback based on event.target.

lerp (value1, value2, amount) {
  amount = amount < 0 ? 0 : amount
  amount = amount > 1 ? 1 : amount
  return value1 + (value2 - value1) * amount
}Copy the code

Other features

Support drag and drop

The container listens to the touch event, pause the original timer when start and enable the draggingTick. The move event moves the container, and executes the update method in the original timer, so that the projectile event will be triggered. The end event stops the draggingTick resume timer. In order to make the drag effect not too stiff, here is the LERP method:

lerp (value1, value2, amount) {
  amount = amount < 0 ? 0 : amount
  amount = amount > 1 ? 1 : amount
  return value1 + (value2 - value1) * amount
}Copy the code

If reproduced, please indicate the source:
W3ctrain.com/2017/12/10/…

My name is Zhou Xiaokai

I am a front-end development engineer now, and I am still a rookie in the way of programming. W3ctrain is the place where I record my learning and growth.