猫史档案馆


Animation.js - 客户端GUI动效

用户:NomenNomen查看:0 回复:2 评论:0 创建时间:2024-01-03T06:14:19


这里是没有开场白的Nomen,我注意到很多作品优秀的UI,但是出现和消失都略显突兀,dao3没有为GUI提供动画效果相关的API,所以,我用interval做了一个简易的动效,目前这个类还过于简陋,没有什么功能,欢迎你提出意见或向仓库推送修改!

示例中使用了UiWrapper,可以从Box3-Tools仓库获取

// 这个例子,将创建一个提示文字,并在显示的时候从屏幕左上角移动到视野内

const UiNodeWrapper = createUiNodeWrapper();
const uiWrapper = new UiNodeWrapper(ui);

const Animation = GUIAnimation();

let r = uiWrapper.createChildNode(UiText)
    .config("position", UiNodeWrapper.createCoord2({ x: -100, y: 25 })) // 开始时将文字隐藏在屏幕外面
    .config("textContent", "欢迎加入游戏!")


let ani = new Animation({
    easingFunction: Animation.easing.easeInOutSine, // 使用easeInOutSine作为填充效果
    begin: 0,   // 开始时
    end: 100,   // 结束时
    time: 1000, // 持续时间
    delay: 1    // 动画刷新间隔,越小动画越流畅
});

ani.start(c => {
    // 当动画刷新时,调用工具更改文字的位置
    r.config("position", UiNodeWrapper.createCoord2({ x: c, y: 25 }));
});
ani.onStop((a) => {
    console.log("stop!");
});
ani.onStart((a) => {
    console.log("start!");
});

/*
ani.cancel()可以取消事件
GUIAnimation可以传入配置参数
interval指的是全局刷新时间,如果这个值调高,那么全局刷新速度就会降低,注意,这会更改动画持续时间,通常建议为1
easeFunctions是一个对象,将会被赋值到easing上用于扩展easing函数
*/
function GUIAnimation({ interval = 1, easeFunctions } = {}) {
    let animations = [], time = 0;
    let timer = setInterval(() => {
        time++;
        animations.filter(a => ((time - a.startTime) % a.delay === 0)).forEach(v => {
            if (time - v.startTime >= v.time) {
                animations = animations.filter(t => t !== v);
                v.stop();
            }
            else v.animate(time);
        });
    }, interval);
    class Animation {
        static easing = {
            easeInSine: (x) => (1 - Math.cos((x * Math.PI) / 2)),
            easeOutSine: (x) => (Math.sin((x * Math.PI) / 2)),
            easeInOutSine: (x) => (-(Math.cos(Math.PI * x) - 1) / 2)
        };
        static stop() {
            clearInterval(timer);
        };
        constructor(config) {
            let def = {easingFunction: (x) => x,begin: 0,end: 1,time: 1000,delay: 10};
            Object.keys(def).forEach(k => this[k] = config[k] ? config[k] : def[k]);
            this._onStop = [];
            this._onStart = [];
            this.current = 0;
            this.pending = false;
        }
        start(trigger) {
            if (!this.pending) {
                this.pending = true;
                this.startTime = time;
                this.trigger = trigger;
                this.current = 0;
                animations.push(this);
                this._onStart.forEach(v => v(this));
            }
        }
        animate() {
            this.current += this.delay;
            this.trigger(this.begin + (this.end - this.begin) * this.easingFunction(this.current / this.time));
        }
        stop() {
            this.pending = false;
            this._onStop.forEach(v => v(this));
        }
        onStop(f) {
            this._onStop.push(f);
            return {
                cancel: () => this._onStop = this._onStop.filter(v => v !== f)
            }
        }
        onStart(f) {
            this._onStart.push(f);
            return {
                cancel: () => this._onStart = this._onStart.filter(v => v !== f)
            }
        }
    };
    if (easeFunctions) Object.assign(Animation.easing, easeFunctions);
    return Animation;
}

 


回复

上一页1 页 / 共 1下一页
NomenNomen

七莓大佬制作的用户界面包装器UiNodeWrapper github.com/helloyork/Box3-Tools/tree/main/src/GUI/UiWrapper 以及本文所涉及的Animation.client.js github.com/helloyork/Box3-Tools/tree/main/src/GUI/Animation

点赞1


评论


神岛吉吉喵神岛吉吉喵

imgsrc="https://static.codemao.cn/emoji/codemao/%E7%BC%96%E7%A8%8B%E7%8C%AB_%E5%8A%A0%E6%B2%B9.gif"alt="emotion_编程猫_加油"

点赞1


评论