This is the 10th day of my participation in Gwen Challenge

Program source code

The motivation for making this tool

Occasionally I webpack label found an article, happened to see know uncle wrote to do animation for this night, let everybody understand webpack ten minutes, but I don’t know uncle, but I think he may be bigger than me, considering the eldest brother a so hard share technology, in order to give their light and heat, do a night, that is true to some love dearly, So I want to do my bit, for the big guy and everyone also issued my a hot.

I was hooked

Appreciate the article first, and confirm the “don’t think than I took a deep, big bosses” the “bias”, but the most direct attract me is not webpack 😂, instead of a bunch of “light”, is for who wrote a night of animation, I lament the animation is so delicate, is so significant effect of expression, directly, strongly attracted me.

action

Instead of wallowing in feelings of affection and worship, do something with them. I looked at their existing ability in my heart, and soon came to an idea 💡, I seem to be able to make a whole out of this “light” wheel, OK, say dry dry.

Mapping out your expectations is half the battle

First of all, I don’t want to make static resources, such as videos and GIfs, which have no “life” and can only be called “material”. I simply use “Yin” to refer to them. What I need is the “life and mind” that radiates and creates material based on material, and I call it Yang. To say that TA is “live” is a bit strong, meaning that it can interact, integrate and reuse, and create static resources like videos, GIFs and so on.

Based on expectations, I determined the implementation plan

First of all, as a front end, to open up the technology side, it is easy to access a variety of technologies, and rendering engine is one of them. First of all, for my needs, this will greatly improve the efficiency of development through rendering engine development, and secondly, it can be integrated into my scaffolding “Moderate”, which is an optimal solution.

Design and development

I always want to use the simplest words to describe a thing, and I prefer simplicity, so let’s talk about my design in a simple way.

Slide the mouse or touch to advance the animation process

Video can be fast forward, backwards, just by swiping the progress bar or swiping the screen, and I like that interaction, so let’s do that, comfortable.

Designing the individual is critical

I hope to design a series of independent entities, which can well connect the whole logic. They have basic functions, but also have the ability to expand. They can be connected with each other and independent from each other

entityIn general, you should have the following behaviors:

  • Describe the cycle in which it runs:lenPercentandstartPercent
  • Life cycle function
    • Start:live
    • Render:process
    • The end:end
  • The ability to carry other individuals:entityArr
    • The constituent units are:entity
  • A collection of actions to perform:recationArr
    • The constituent units are:recation.

recationIn general, you should have the following behaviors:

  • Describe the cycle in which it runs:startandend
  • Actions performed:action()

Then the individual design, around the individual of the logic, it becomes a logical.

The code is as follows:

export default cc.Class({
    extends: cc.Component,

    properties: {

        lenPercent: cc.Float,
        startPercent: cc.Float,
        isAutoStart: cc.Boolean,
        entityArr: {
            default: [].type: cc.Node
        }
    },

    //externalDuration: specifies the external time (time transmitted by the parent node), which is determined by the parent node
    //internalDuration: the time determined by oneself,
    // Why distinguish between the two? Since the outside should only determine my playback time, not my playback rate, which should be determined by the individual,
    //startTime and endTime: start and end times specified by the parent (' external time 'depending on the parent's world!!)
    //timeLine- Indicates where the time is, (' external time 'based on the parent node's world!!)
    //totaTime- Indicates the total time I should be playing from the parent (' external time 'depending on the parent's world!!)
    //progressValue is the timeLine passed by the parent node, totaTime. TimeLine tells me the percentage of progress I am in
    // The corresponding pass to its child node must refer to its own
    ctor() {
        this.isLive = false;
        this.startTime = undefined;
        this.endTime = undefined;
        this.internalDuration = 0;// The duration within the individual
        this.externalDuration = 0;// The length of the individual relative to its parent
        this.progressValue = 0;
        this.entryData = [];
        this.recationArr = [];
        this.startPosition = cc.v2();
        this.entityArrEx = [];
    },

    // LIFE-CYCLE CALLBACKS:
    start() {
        this.startPosition = this.node.position;
    },
    onLoad() {
        this.node.comName = this.__classname__;
        this.internalDuration = this.node.getContentSize().height;
        // To prevent the set time from being too long, force the set to the remaining time
        if (this.lenPercent + this.startPercent > 1) {
            this.lenPercent = 1 - this.startPercent;
        }
        if (this.isAutoStart) {
            this.startPercent += Math.abs((this.node.position.y / this.node.parent.getContentSize().height)); }},onEnable() {
        let self = this;
        if (this.entityArr.length) {
            this.entityArrEx = this.entityArr.map((item, index) = > {
                let entity = item.getComponent(item._name);
                if (entity.isAutoStart) {

                }
                this.entryData.push(entity.initData({
                    startTime: this.getStarTime(entity.startPercent),
                    totaTime: self.internalDuration,
                }));
                returnentity; }); }},// Business interface
    getStarTime(value) {
        if (value <= 1) {
            return value * this.internalDuration
        } else {
            return value
        }
    },

    initData({ totaTime, startTime }) {
        this.startTime = startTime;
        this.externalDuration = this.lenPercent <= 1 ? totaTime * this.lenPercent : this.lenPercent;
        // The end time can be the end time of the parent node
        // Because the parent node ends, the child node must also end
        this.endTime = Math.min(totaTime, this.startTime + this.externalDuration);
        return {
            startTime: this.startTime,
            internalDuration: this.internalDuration,
            endTime: this.endTime
        }
    },

    getCurrentTime(percent) {
        return (
            this.startTime + (percent <= 1 ? this.externalDuration * percent : percent)
        );
    },

    live() {
        this.isLive = true;
    },

    calcProgress() {
        this.progressValue = (this.timeLine - this.startTime) / this.externalDuration;
    },

    calcReactionProgress({ start, end }) {
        start = (start <= 1)?this.internalDuration * start : start;
        end = (end <= 1)?this.internalDuration * end : end;
        return Math.min((this.progressValue * this.internalDuration - start) / (end - start), 1);
    },

    process({ timeLine }) {
        this.timeLine = timeLine;
        this.calcProgress();
        this.internalTimeLine = this.progressValue * this.internalDuration;
        let actionArr = this.recationArr.filter((item) = > {
            if (item) {
                let isOk = (timeLine > this.getCurrentTime(item.start) &&
                    timeLine <= this.getCurrentTime(item.end)) || (! item.start && ! item.end)if (isOk) {
                    item.isAction = true
                } else {
                    if (item.isAction) {
                        item.action(this.calcActionData(item, true))
                    }
                    item.isAction = false
                }
                returnisOk; }}); actionArr.forEach((item) = > {
            item.action(this.calcActionData(item));
        });
    },

    update() {
        let self = this;
        this.actionEntityArr = this.entityArrEx.filter((entity) = > {
            if ((self.internalTimeLine) > entity.startTime && self.internalTimeLine <= entity.endTime) {
                if(! entity.isLive) { entity.live(); } entity.process({timeLine: self.progressValue * self.internalDuration,
                });
                return true;
            } else {
                if(entity.isLive) { entity.end(); }}return false;
        });
    },

    calcActionData(item, isEnd) {
        let params = {};
        let actionLen = (item.end - item.start) || 1;
        let progress;
        progress = Math.min((this.progressValue - item.start) / actionLen, 1);
        if (isEnd) {
            let isEndForce = window.GLOBAL.dir > 0;
            let isEndForceStart = window.GLOBAL.dir < 0;
            if (isEndForce) {
                progress = 1
            } else if (isEndForceStart) {
                progress = 0
            }
            params = {
                isEndForce: isEndForce,
                isEndForceStart: isEndForceStart } } params = { actionLen, progress, ... params, ... item }return params;
    },
    end() {
        this.isLive = false;
        // If the slide is very fast, and is fast rather than backward, force the feedback to end directly
        // if (window.GLOBAL.dir > 0) {

        // }
        this.recationArr.forEach(item= > {
            if (item.isAction) {
                item.isAction = false
                item.action(this.calcActionData(item, true))}}); }});Copy the code

Take a look at the effect:

This is an animation made by Runge

My version (it turns out the two are one while doing it)

A bonus for me

Just as I was working on my third animation, trying to figure out how the arrow would work, I had another idea, and I made this.

“Moderate” new home page.

Thanks to Uncle Ran.

conclusion

This is my tenth column for Moderate, and it’s been a very fulfilling, unpopular but enjoyable experience. I met a lot of passionate, talented, honorable coder and digger, and learned a lot. Finally, I sincerely thank the Denver Nuggets for creating a community atmosphere. I feel sorry for each other, but we feel like friends at first sight and have a bright future.