aardio 文档
aardio 范例: av.video 缓动与弹簧 - plus 控件界面动效
av.video 使用指南 | plus 控件使用指南
//av.video 缓动与弹簧 - plus 控件界面动效
//av.video 使用指南: https://www.aardio.com/zh-cn/docs/library/av/video/
//plus 控件使用指南: https://www.aardio.com/zh-cn/docs/library-guide/std/win/ui/ctrl/plus.html
import win.ui;
/*DSG{{*/
var winform = win.form(text="av.video - 缓动与弹簧";right=599;bottom=389;bgcolor=0xFFFFFF)
winform.add(
btnAdd={cls="plus";text="+ 随机";left=474;top=203;right=560;bottom=233;bgcolor=0xF0F0F0;border={radius=6};color=0x333333;font=LOGFONT(h=-14);notify=1;z=4};
btnOk={cls="plus";text="确定";left=474;top=282;right=560;bottom=312;bgcolor=0xF0F0F0;border={radius=6};color=0x333333;font=LOGFONT(h=-14);notify=1;z=6};
btnSpring={cls="plus";text="移上来,按下去";left=317;top=22;right=573;bottom=84;bgcolor=0xD47800;border={radius=14};color=0xFFFFFF;font=LOGFONT(h=-15);notify=1;z=1};
code1={cls="bkplus";text='$.spring(t,4,0.35) \u2192 plus.scale';left=40;top=56;right=320;bottom=76;align="left";color=0x8A8A8A;font=LOGFONT(h=-13;name='Consolas');z=8};
code2={cls="bkplus";text="$.spring(t,3,0.6) + $.mixColor";left=40;top=140;right=320;bottom=160;align="left";color=0x8A8A8A;font=LOGFONT(h=-13;name='Consolas');z=10};
code3={cls="bkplus";text='$.ease("easeOutExpo",p)';left=40;top=220;right=320;bottom=240;align="left";color=0x8A8A8A;font=LOGFONT(h=-13;name='Consolas');z=12};
code4={cls="bkplus";text='$.decay(t,6,6) \u2192 setPos';left=40;top=300;right=320;bottom=320;align="left";color=0x8A8A8A;font=LOGFONT(h=-13;name='Consolas');z=14};
counter={cls="plus";text="0";left=330;top=198;right=470;bottom=238;align="left";color=0x333333;font=LOGFONT(h=-28;weight=700);z=3};
input={cls="plus";left=330;top=282;right=466;bottom=312;align="left";border={bottom=1;color=0xC0C0C0};editable=1;font=LOGFONT(h=-15);textPadding={top=6;bottom=2};z=5};
line1={cls="bkplus";left=40;top=100;right=560;bottom=101;bgcolor=0xEEEEEE;z=15};
line2={cls="bkplus";left=40;top=180;right=560;bottom=181;bgcolor=0xEEEEEE;z=16};
line3={cls="bkplus";left=40;top=260;right=560;bottom=261;bgcolor=0xEEEEEE;z=17};
note={cls="bkplus";text="动画是时间的纯函数:随时打断都从当前值出发,不跳变,也不累积误差。";left=40;top=346;right=560;bottom=370;align="left";color=0x9A9A9A;font=LOGFONT(h=-13);z=18};
title1={cls="bkplus";text="悬停与按下";left=40;top=30;right=300;bottom=54;align="left";color=0x333333;font=LOGFONT(h=-16;weight=700);z=7};
title2={cls="bkplus";text="开关";left=40;top=114;right=300;bottom=138;align="left";color=0x333333;font=LOGFONT(h=-16;weight=700);z=9};
title3={cls="bkplus";text="数字滚动";left=40;top=194;right=300;bottom=218;align="left";color=0x333333;font=LOGFONT(h=-16;weight=700);z=11};
title4={cls="bkplus";text="输错抖动";left=40;top=274;right=300;bottom=298;align="left";color=0x333333;font=LOGFONT(h=-16;weight=700);z=13};
toggle={cls="plus";left=330;top=120;right=394;bottom=154;notify=1;z=2}
)
/*}}*/
import av.video;
var $ = av.video;
/*
plus 控件的 startAnimation(间隔,起点,变化量,时长) 定时回调 onAnimation 并重绘,
回调参数 timestamp 是已经过的毫秒数。av.video 的曲线都是时间的纯函数,直接拿 timestamp 求值。
动画中途被打断(例如鼠标刚移入又移出)时,把当前值作为新的起点重新开始即可,不会跳变。
*/
//---- 1. 悬停与按下:弹簧推动 plus 的 scale(缩放内容,不改控件大小)----
winform.btnSpring.skin({
background = {default=0xFF0078D4;hover=0xFF1084D9;active=0xFF005A9E};
color = {default=0xFFFFFFFF};
})
//scale 超过 1 的部分会被控件边界裁掉,所以平时显示 0.9 倍,给弹簧过冲留余量(控件比看到的按钮大 10%)
var btnScale = 0.9;
winform.btnSpring.onAnimation = function(prevState,beginning,change,timestamp,duration){
btnScale = beginning + change * $.spring(timestamp / 1000,4,0.35); //4Hz、阻尼比 0.35:回弹明显
if(timestamp >= duration) btnScale = beginning + change;
owner.scale = btnScale;
if(timestamp < duration) return true; //返回 null 停止动画
}
//skin 切换状态时会重置 scale,所以在 onStateChange 里按状态定目标,从记下的当前值出发
winform.btnSpring.onStateChange = function(state){
var target = state.active ? 0.84 : (state.hover ? 0.95 : 0.9);
owner.startAnimation(10,btnScale,target - btnScale,700);
}
winform.btnSpring.scale = btnScale;
//---- 2. 开关:弹簧带动滑块,底色跟着插值 ----
var toggleOn,knob = false,0; //knob:0 关,1 开(弹簧过冲时略超出)
winform.toggle.cursor = "hand";
winform.toggle.onDrawForeground = function(graphics,rc){
var x0,y0,w,h = rc.left,rc.top,rc.right - rc.left,rc.bottom - rc.top;
var brush = gdip.solidBrush($.mixColor(0xFFD0D4DA,0xFF34C759,math.clamp(knob,0,1)));
graphics.fillRoundRect(brush,x0,y0,w,h,h / 2);
var pad = h * 0.1;
var d = h - pad * 2;
var x = x0 + pad + (w - h) * knob;
brush.color = 0x30000000;
graphics.fillEllipse(brush,x,y0 + pad + h * 0.04,d,d); //滑块的影子
brush.color = 0xFFFFFFFF;
graphics.fillEllipse(brush,x,y0 + pad,d,d);
brush.delete();
}
winform.toggle.onAnimation = function(prevState,beginning,change,timestamp,duration){
knob = beginning + change * $.spring(timestamp / 1000,3,0.6);
if(timestamp < duration) return true;
knob = beginning + change;
}
winform.toggle.oncommand = function(){
toggleOn = !toggleOn;
var target = toggleOn ? 1 : 0;
winform.toggle.startAnimation(10,knob,target - knob,800); //连点时从滑块当前位置折返
}
//---- 3. 数字滚动:缓动曲线决定节奏,先快后慢 ----
var shown,total = 0,0;
var fmt = function(n){ //千分位
var s,count = tostring(math.round(n)),1;
while(count) s,count = string.replace(s,"^(\d+)(\d\d\d)","\1,\2");
return s;
}
winform.counter.onAnimation = function(prevState,beginning,change,timestamp,duration){
var p = math.min(timestamp / duration,1);
shown = beginning + change * $.ease("easeOutExpo",p);
owner.text = fmt(shown);
if(p < 1) return true;
}
winform.btnAdd.oncommand = function(){
total += math.random(300,3000);
winform.counter.startAnimation(10,shown,total - shown,900); //连点时从当前显示的数继续滚
}
//---- 4. 输错抖动:衰减振荡,任意控件都能用 ----
var shake = function(ctrl){
ctrl.shakeStart = time.tick();
if(ctrl.shakeX !== null) return; //正在抖:重新计时,原位不变
ctrl.shakeX,ctrl.shakeY = ctrl.getPos();
var amp = winform.dpiScale(10); //振幅 10 像素(按 DPI 缩放)
winform.setInterval(function(){
var t = (time.tick() - ctrl.shakeStart) / 1000;
if(t >= 0.6){
ctrl.setPos(ctrl.shakeX,ctrl.shakeY);
ctrl.shakeX = null;
return false; //停止定时器
}
ctrl.setPos(ctrl.shakeX + math.round($.decay(t,6,6) * amp),ctrl.shakeY);
},10);
}
winform.input.setCueBannerText("输入 aardio");
winform.btnOk.oncommand = function(){
if(winform.input.text == "aardio"){
winform.input.border = {bottom=2;color=0xFF34C759};
}
else {
winform.input.border = {bottom=2;color=0xFFE5484D};
shake(winform.input);
}
winform.input.redraw();
}
for(i,btn in [winform.btnAdd,winform.btnOk]){
btn.skin({background = {default=0xFFF0F0F0;hover=0xFFE6E6E6;active=0xFFDADADA}});
}
winform.show();
win.loopMessage();
Markdown 格式