Text animation effects based on HTML5 Canvas

foreword

Text is the most basic element in web pages. Generally, we display static text on web pages, but in terms of effect, it is still relatively boring. The animation effect of text fading in and out is very practical in the project. If there are some key texts, this dynamic effect can be used to remind users to read.

Dynamic renderings

http://www.hightopo.com/demo/GraphAnimation/index.html

This Demo is to repeatedly set the size and transparency of the text. These English letters are also drawn by myself using the HT vector, and the overall effect is good.

Code

There are about 100 lines of code in total, which is relatively simple. As mentioned earlier, my English letters are drawn with vectors. There are many advantages to drawing graphics with vectors. You need to provide pictures of different sizes; there is a way to describe the vector in JSON, the format is relatively simple and so on.

vector image

Next draw these vector pictures (only the first H is taken out for illustration):

{
    "width": 10,//Set the width of the vector
    "height": 10,//Set the height of the vector
    "comps": [//The component Array array of vector graphics, each array object is an independent component type , and the order of the array is the order in which the components are drawn
    {
        "type": "text",//text type
        "text": "H",//text content
        "color": "rgb(69,69,69)",//text color
        "align": "center",//The alignment of the text in the vector
        "opacity": {//Text transparency
            "func": "[email protected]",//Set business attributes, data binding of transparency to text
            "value": 1//If the value in func is empty or undefined, then use this value directly
        },
        "clipDirection": "bottom",//The cutting direction is "top to bottom"
        "rect": [//Specify the rectangle boundary that the component draws in the vector
            0,//represents the upper left corner coordinate x
            0,//represents the upper left corner coordinate y
            10,//Represents the width of the component
            10//Represents the height of the component
        ]
    }]
}

Drawing vector graphics is written in JSON format. There are three main parameters: width, height and comps. These three parameters must be written, where width is the width of the vector graphic, height is the height of the vector graphic, and comps is an Array array, which is an independent object, you can set some predefined parameters for this object , you can also set some optional parameter information.

Here I store all the text information in an array for easy calling:

arr = [
    {label: 'H', image: 'symbols/H.json'},
    {label: 'T', image: 'symbols/T.json'},
    {label: 'f', image: 'symbols/f.json'},
    {label: 'o', image: 'symbols / o.json'},
    {label: 'r', image: 'symbols/r.json'},
    {label: 'W', image: 'symbols/W.json'},
    {label: 'e', image: 'symbols/e.json'},
    {label: 'b', image: 'symbols/b.json'},
];

The first label object is the name of the vector graphic, and the second image object is an image in json format, but it can actually be img, canvas object or image url or base64 string.

Create a node object

The image of the object has been generated, and the next step is to create the object. There are 8 English letters in total, so we create 8 node objects:

  var s = 80;
  arr.forEach(function(obj, index) {
      var text = obj.label;
      name = 't' + text;
      window[name] = createNode(obj.image, 100+s*index, 100);
  });

function createNode(image, x, y) {//Node object declaration
    var node = new ht.Node();//This class is the node defined in ht
    node.setSize(0, 0);//Set the node size
    if(image) node.setImage(image);//Set the node image
    if(x && y) node.setPosition(x, y);//Set the node placement position

    dm.add(node);//Add the node to the data container datamodel
    return node;
}

Regarding the generation of the above ht.Node node, in fact, this is just a class encapsulated by HT. There are many convenient APIs on this class. Then add the generated node into the data container dm, which is the data container of the entire topology graph gv.

Topology map generation

Let's see how to generate this topology map:

dm = new ht.DataModel();//Data container
gv = new ht.graph.GraphView(dm);//The topology graph can obtain the underlying div of this topology graph through gv.getView()
gv.addToDOM();//Add gv to body

In fact, the principle of HT is to draw graphics on the canvas in a div, that is to say, the gv is a canvas.

Then get the underlying div of the canvas through getView, so that we can add this div to any place on the html page. The definition of addToDOM is as follows:

addToDOM = function(){   
    var self = this,
        view = self.getView(), //get the underlying div
        style = view.style;
    document.body.appendChild(view); //Add the underlying div to the body      
    style.left = '0';//Because HT sets the component's position to absolute by default, so you need to set the position
    style.right = '0';
    style.top = '0';
    style.bottom = '0';      
    window.addEventListener('resize', function () { self.iv(); }, false);//The window size change triggers an event, and the outermost component invalidate (ie iv) function is called to update.
}

Now refresh the page, you will see a blank space, why? Because the size of the node is set to 0 earlier, how can it be displayed? The effect of this Demo is to grow from nothing to nothing. Then let's see how to "create from nothing".

Text animation

As I just said, in order for the nodes to be displayed, we must set the size of the nodes to be visible to the naked eye, but my purpose is not only to start from scratch, but also from small to large. This can All at once? It seems that the content of the code is simple, but the amount of code is not small. For a task, I defined a function to create nodes from scratch, from small to large:

function setSize(node) {
    if(node) {
         var s = 80,
              size = node.getSize().width;//Get the width in the current size of the node, because I know that the width and height are the same, so it is abbreviated
        var sw = s - size;
        ht.Default.startAnim({//The animation function encapsulated by HT, the content is also an object in JSON format
            duration: 1000, // animation period in milliseconds
            easing: function(t) { return t*t },//animation easing function
            action: function(v, t) {//The action function must be provided to realize the property change during the animation process. The first parameter v represents the value after operation by the easing(t) function, and t represents the progress of the current animation [0~ 1], general attribute changes are made according to the v parameter
                node.setSize(//Set the size of the node (there is an easing process implemented by sw*v)
                    size + sw*v,
                    size + sw*v
                );
            }
        });
    }
}

The process from big to small and from existence to non-existence is similar to the above, so I won't go into details.

To make these letters appear and disappear in the order of time, the setTimeout method must be used. It is very easy to realize the disappearance of the display once, but I fell into a trap of setTimeout in the process of implementation. I can only say myself Not good at learning. Because we need to set different appearance and disappearance times for different letters, generally the simpler method is to set a fixed value, and then multiply it by the corresponding node-specific index:

function animateIn() {
    for(let i = 0; i < arr.length; i++) {
        var name = 't' + arr[i];
    animateLetterIn(window[name], i);//This part sets the animation
    }
}

However, if I directly set the time of setTimeout to change dynamically in the for loop, then the dynamically changing value must only take the last value of the for loop, so I extract the method of setTimeout as a separate function:

function animateLetterIn(node, i) {
    setTimeout(function() {
        setSize(node);
    }, i * 200);//At this time, this i takes the i corresponding to the node instead of the last value

    if(i === arr.length - 1) {//When the node is the last node, set the node fade out animation
        setTimeout(function() {
        animateOut();//Node fade out animation
    }, (arr.length + 3) * 200);
    }
}

The node fade-out animation is also a similar method, but these animation functions need to be called cyclically, so that the size control of the infinite loop letters can be achieved.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325210893&siteId=291194637