This is the 25th day of my participation in the August Genwen Challenge.More challenges in August

☀  preface

  • The thing is, some time ago, I got the company’s data large screen prototype drawing and asked me to make a whole page in one day.
  • A quick look at it, it’s one3840 * 1840The big screen and then a few lists and a few legends don’t look too complicated.
  • Swish! I worked a little overtime and got the whole page ready and showed it to the product manager with confidence.
  • Product manager frowned: you this word cloud won’t move??

đŸŒ€ïž before the effect

  • Hearing this, I realized that the situation was wrong. I thought that the word cloud of the prototype diagram could not tell that he had not asked me to move, and it was clear that what I did would move.

🎱 diagram

  • I started withechartsthegraphDiagrams, which have the characteristic of having some dynamic effect at the beginning because the repulsive forces of each word are separated from each other, but do not continue to move because the force-guided layout stabilizes after several iterations.

  • I: be I didn’t cheat people? It does move.
  • Product manager: This effect is not good, there is no sense of science and technology, and I want the font size of each is different, tomorrow I will show the customer a version, it is urgent, forget it, you do not move let him word cloud fill up and then the size of each word is not the same.

🎠 word cloud

  • Do not do the verb cloud that is not easy, directly useechartsthewordCloudFigure ah, direct shua Shua configuration is good.

  • Product manager: The customer finished reading it, the whole is good, but I still want it to move the word cloud, so, you think of a way.

🚄 Write by yourself

  • I was really obsessed with this word cloud at first and decided to use itechartsTo do it, but actuallywordCloudThe official website also does not provide information, there really seems to be no way to get it moving.
  • Think for a moment…. Wait, the word cloud has to be different sizes and colors and then it has to move around the region randomly, since I’m not familiar with itcanvasI wonder if I can use itjsandcssTo write a2dTo put it bluntly, it is a word in a container of random movement and then each word move to sa, as if can go…. Open dry.

🚅 ToDoList

  • Prepare containers and required configuration items
  • Generate all static word clouds
  • Get the word cloud moving

🚈 Just Do It

  • Because my tech stack isvue 2.xSo we’re going to usevue 2.xSyntax to share, but actually convert to nativejsThere is no difficulty, I believe we can accept.

🚎 Prepare containers and configuration items

  • We start by building a container around which to wrap our word cloud, and we do all the rest of our operations around this container.
<template>
  <div class="wordCloud" ref="wordCloud">
  </div>
</template>
Copy the code

  • Because our word cloud needs to have different colors, we need to implement a word list and a color list, and prepare an empty array to store the words generated later.
. data () {return {
            hotWord: ['All the best'.'Everything goes well'.'Everything goes well'.'Smooth sailing'.'All is well'.'Good luck'.'Up the ladder'.'Step by step'.'Three Sheep kaitai'.'In one's element'.'Money is coming in'.'Tao is not comparable'.'Happy Family'.'Spirit of Dragon horse'].color: [
                    '#a18cd1'.'#fad0c4'.'#ff8177'.'#fecfef'.'#fda085'.'#f5576c'.'# 330867'.'#30cfd0'.'#38f9d7'].wordArr: []}; }...Copy the code
  • Prepared these words are to read the article now you say ~ if you think I said right might as well after reading the article to give apraise ~
  • All joking aside, now that the preparation is complete, start generating our word cloud.

🚒 Generates all static word clouds

  • If we want to fill a container with words, according to the normal logic of our diagram, one for each wordspanSo that’s equivalent to onedivThere is an(hotWordThere is a corresponding quantity in a containerspanLabels are ok.
  • If you need different colors and sizes, pair them separatelyspanAdd different styles to the tags.
. mounted () {this.init();
},
methods: {
        init () {
            this.dealSpan();
        },
        dealSpan () {
            const wordArr = [];
            this.hotWord.forEach((value) = > {
                    // Set font color and size according to the number of span generated by the word cloud
                    const spanDom = document.createElement('span');
                    spanDom.style.position = 'relative';
                    spanDom.style.display = "inline-block";
                    spanDom.style.color = this.randomColor();
                    spanDom.style.fontSize = this.randomNumber(15.25) + 'px';
                    spanDom.innerHTML = value;
                    this.$refs.wordCloud.appendChild(spanDom);
                    wordArr.push(spanDom);
            });
            this.wordArr = wordArr;
        },
        randomColor () {
            // Get a random color
            var colorIndex = Math.floor(this.color.length * Math.random());
            return this.color[colorIndex];
        },
        randomNumber (lowerInteger, upperInteger) {
            // Get a random number between minimum and maximum.
            const choices = upperInteger - lowerInteger + 1;
            return Math.floor(Math.random() * choices + lowerInteger); }}...Copy the code
  • We have tohotWordThe hot word list is iterated, generating one every time there is a wordspanLabel, used separatelyrandomColor()andrandomSize()Set different random colors and sizes.
  • And then I’m going to do thisspanAll in turndivIn the container, so when we’re done, it looks like this.

🚓 get the word cloud moving

  • The words are added, and then we need to make them move, so how do we move themtransformthetranslateXandtranslateYProperties, we need to make one word work first, and then apply it to everything else.
Let’s move the X-axis
  • How do I move it? What we’re going to do here is an infinite loop thing, which is an element that moves indefinitely, since it’s infinite, injsCan you do it with a timer? It’s possible, but it’s going to get stuck, in case your computer explodes with too many words, on the other hand the key to writing animation loops is to know how long the delay is appropriate, if it’s too long or too short it’s not appropriate so don’t use timers.
  • And then I found out by accidentwindow.requestAnimationFramethisAPI.requestAnimationFrameThere is no need to set the interval.

RequestAnimationFrame brings together all DOM operations in each frame in a single redraw or reflow that closely tracks the browser refresh rate, which is typically 60 frames per second.

  • That is, when we loop through infinity let an element inxAxis oryAxis shift, let’s say it moves to the right every second10pxSo it’stranslateXIs the cumulative10pxThat’s true for every element so we need to givespanElement adds an attribute to represent its position.
data () {
    return{...timer: null.resetTime: 0. }; }methods: {
    init () {
            this.dealSpan();
            this.render();
    },
    dealSpan () {
            const wordArr = [];
            this.hotWord.forEach((value) = >{... spanDom.local = {position: {
                                    x: 0.y: 0}}; . });this.wordArr = wordArr;
    },
    render () {
            if (this.resetTime < 100) {
                    // Prevent stack overflow
                    this.resetTime = this.resetTime + 1;
                    this.timer = requestAnimationFrame(this.render.bind(this));
                    this.resetTime = 0;
            }
            this.wordFly();
    },
    wordFly () {
            this.wordArr.forEach((value) = > {
                    // Incrementing each loop by 1
                    value.local.position.x += 1;
                    // Animate the transition for each word
                    value.style.transform = 'translateX(' + value.local.position.x + 'px)';
            });
    },
},
destroyed () {
        // Component destruction, disable timed execution
        cancelAnimationFrame(this.timer);
},
Copy the code
  • At this point, we add one to each elementlocalIt’s in the propertyThe initial positionEvery time we execute itrequestAnimationFrameWhen it wasThe initial positionall+ 1And give this value totranslateXSo we’re moving every time we go around1pxNow let’s look at the effect.

Adjusting range
  • Hey! Boy, there was movement, but how did it go too far?
  • We found that every timetranslateXall+ 1But there is no stopping range for him, so we need to give him one to start at the edge of the containerTurn aroundThe steps.
  • So how do we get him to turn around? Since we can make him move to the right every time1pxSo we can’t detect when it’sxWhen the axis position is greater than the container positionxIf the axis position is less than the container position and it’s good to change the direction and change the direction we just useIs a negative numberTo judge.
init () {
        this.dealSpan();
        this.initWordPos();
        this.render();
},
dealSpan () {
        const wordArr = [];
        this.hotWord.forEach((value) = >{... spanDom.local = {position: {
                            / / position
                            x: 0.y: 0
                    },
                    direction: {
                            // Positive goes to the right and negative goes to the left
                            x: 1.y: 1}}; . });this.wordArr = wordArr;
},
wordFly () {
        this.wordArr.forEach((value) = > {
            // Set the direction of movement to change direction when greater than or less than the boundary
            if (value.local.realPos.minx + value.local.position.x < this.ContainerSize.leftPos.x) {
                    value.local.direction.x = -value.local.direction.x;
            }
            if (value.local.realPos.maxx + value.local.position.x > this.ContainerSize.rightPos.x) {
                    value.local.direction.x = -value.local.direction.x;
            }
            // Each time we move 1 to the right we move -1 to the left when it's negative
            value.local.position.x += 1 * value.local.direction.x;
            // Animate the transition for each word
            value.style.transform = 'translateX(' + value.local.position.x + 'px)';
        });
},
initWordPos () {
        // Calculate the actual position of each word and the container position
        this.wordArr.forEach((value) = > {
            value.local.realPos = {
                    minx: value.offsetLeft,
                    maxx: value.offsetLeft + value.offsetWidth
            };
        });
        this.ContainerSize = this.getContainerSize();
},
getContainerSize () {
        // determine the container size to control the word cloud position
        const el = this.$refs.wordCloud;
        return {
            leftPos: {
                    // The left side of the container and the top side
                    x: el.offsetLeft,
                    y: el.offsetTop
            },
            rightPos: {
                    // The position of the right side of the container and the position of the bottom
                    x: el.offsetLeft + el.offsetWidth,
                    y: el.offsetTop + el.offsetHeight
            }
        };
}
Copy the code
  • Let’s start with oneinitWordPosTo calculate the current position of each word and save its position for usegetContainerSizeGet the left, right, top and bottom positions of our outer container and save them.
  • Give us everyspanAdd a propertydirection The direction ofIf it’s negative, it goes to the left, and if it’s regular, it goes to the right, and I wrote this comment in the code, so you can read it if you don’t clear it.
  • That means our word cloud will bounce around the container repeatedly, so let’s see what happens.

Random displacement
  • Very good, is what we want!!
  • Of course, we can’t write down every displacement1pxAnd to do that, we need to do a random shift.
  • So how do we do random displacement? You can see that we’re talking about constant motion in a straight line and remember the formula for constant motion in a straight line?
  • If you don’t remember, I suggest you go back to your physics book ~ the displacement formula of uniform linear motion isx=vt
  • thisxThat’s the displacement we need, and thistWe don’t have to worry about that because I said that up thererequestAnimationFrameWill help us set the time, so we just need to control thisvThe initial velocity is just random.
dealSpan () {
        const wordArr = [];
        this.hotWord.forEach((value) = >{... spanDom.local = {velocity: {
                            // The initial velocity of each displacement
                            x: -0.5 + Math.random(),
                            y: -0.5 + Math.random() }, }; . });this.wordArr = wordArr;
},
wordFly () {
        this.wordArr.forEach((value) = >{...//ćˆ©ç”šć…ŹćŒ x=vtvalue.local.position.x += value.local.velocity.x * value.local.direction.x; . }); },Copy the code
  • We give each wordspanElement an initial velocity, and this initial velocity can be zero-Will be able to+It means move to the left or move to the right, when we deal with thistranslateXAnd now let’s see what happens.

Improve y
  • nowxThe axis is done exactly as we want it to beThe word cloudUp, down, left, and right so we need to followxSo let’s do it the axis wayyAxis.
  • Due to the length of the code I will not put out, I will give the source code below, you can go to download and have a look ~ we directly to see the finished product! Thank you for reading, and I wish you here:

  • So far a simple word cloud animation is over, the specific source code I put here.

👋 is at the end

  • First of all, thank you for reading here. In fact, there are many different solutions for different effects. You should not be too rigid in one plug-in or method.
  • The front-end world is so wonderful that only careful people can find it interesting. I hope I can help those in need.
  • If you feel that this article has helped to your words might as well 🍉 attention + likes + favorites + comments + forward 🍉 support yo ~~😛 your support is the biggest power OF my update.

🌅 past wonderful

Fix echarts map rotation highlighting ⚡

Read still not clear redraw and rearrangement come over beat me 👊, I say!!

How to elegantly write component examples using Vuepress (1) 👈

How to elegantly write component examples using Vuepress (below) 👈

How hard is style naming? Discussion on BEM naming conventions ⚡