欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

基于C#WPF框架——动画

程序员文章站 2022-06-11 16:19:48
WPF提供了一个更高级的模型,通过该模型可以只关注动画的定义,而不必考虑它们的渲染方式。这个模型基于依赖项属性基础架构。本质上,WPF动画只不过是在一段时间间隔内修染方式。这个模型基于依赖项属性基础架构。本质上,WPF动画只不过是在一段时间间隔内修改依赖项属性值的一种方式。 尽管目前WPF可为动画使 ......

wpf提供了一个更高级的模型,通过该模型可以只关注动画的定义,而不必考虑它们的渲染方式。这个模型基于依赖项属性基础架构。本质上,wpf动画只不过是在一段时间间隔内修染方式。这个模型基于依赖项属性基础架构。本质上,wpf动画只不过是在一段时间间隔内修改依赖项属性值的一种方式。

尽管目前wpf可为动画使用三种方法(线性插值、关键帧以及路径),但完全也可以创建更多的使用完全不同的方式来修改值的动画类.唯一要求是自定义的动画类必须根据时间修改值。
多的使用完全不同的方式来修改值的动画类.唯一要求是自定义的动画类必须根据时间修改值。

animation 类

所有动画类都以“类型名+animation”方式命名。这种观点很接近实际情况,但不是非常准确。

  • 17个“类型名+animation”类,这些类使用==插值==。
  • 22 个“类型名+animationusingkeyframes"类,这些类使用==关键帧动画==。
  • 3个“类型名+animationusingpath"类,这些类使用==基于路径==的动画。
    所有这些动画类都继承自抽象的“类型名+animationbase”类,这些基类实现了一些基本功能,从而为创建自定义动画类提供了快捷方式。如果某个数据类型支持多种类型的动画,那么所有的动画类都继承自抽象的动画基类。

    这42个类并不是system.windows.media.animation名称空间中的唯- -内容。每个关键帧动画还使用自己的关键帧类和关键帧集合类,这两部分类会导致一些混乱。 总之,在==system.windows.media.animation==名称空间中有100多个类。

booleananimationusingkeyframes byteanimation
byteanimationusingkeyframes charanimationusingkeyframes
coloranimation coloranimationusingkeyframes
decimalanimation decimalanimationusingkeyframes
doubleanimation doubleanimationusingkeyframes
doubleanimationusingpath int16animation
intl 6animationusingkeyframes int32animation
int32animationusingkeyframes int64animation
int64animationusingkeyframes matrixanimationusingkeyframes
matrixanimationusingpath objectanimationusingkeyframes .
pointanimation pointanimationusingkeyframes
pointanimationusingpath point3danimation
point3danimationusingkeyframes quarternionanimation
quarternionanimationusingkeyframes rectanimation
rectanimationusingkeyframes rotation3danimation
rotation3danimationusingkeyframes singleanimation
singleanimationusingkeyframes sizeanimation
sizeanimationusingkeyframes stringanimationusingkeyframes
thicknessanimation thicknessanimationusingkeyframes
vectoranimation vectoranimationusingkeyframes
vector3danimation vector3danimationusingkeyframes

这42个类开不是system. windows.media.animation名称空间中的唯一内 谷.每个关键帧动画
还使用自己的关键帧类和关键帧集合类,这两部分类会导致一些混乱。总之,在system.windows.
media.animation名称空间中有100多个类。

任何使用线性插值的动画最少需要三个细节:
==开始值(from)==、==结束值(to)==和==整个动画执行的时间(duration)==。
即使不使用to属性,也可以使用by属性。by属性用于创建按设置的数量改变值的动画,而不是按给定目标改变值。
可结合使用by和from属性,但这并不会减少任何工作. by值被简单地增加到from值上,使其达到to值。
大部分使用插值的动画类通常都提供了by属性,但并非全部如此。例如,对于非数值数据类型来说,by 属性是没有意义的,比如coloranimation类使用的color结构。
另有一种方法可得到类似的行为,而不需要使用by属性一可通 过设置isadditive属性创建增加数值的动画。当创建这种动画时,当前值被自动添加到from值和to值。

动画的生命周期

单向动画(如增长按钮的动画)在运行结束后会保持处于活动状态,这是因为动画需要将按钮的宽度保持为新值。这会导致如下不常见的问题一如 果尝试使用代码在动画完成后修改属性值,代码将不起作用。因为代码只是为属性指定了一个新的本地值,但仍会优先使用动画之后的属性值。
根据准备完成的工作,可通过如下几种方法解决这个问题:
● 创建将元素 重新设置为原始状态的动画。可通过创建不设置to属性的动画达到该目的。
例如,将按钮的宽度减小到最后设置的尺寸的按钮缩小动画,之后就可以使用代码改变该属性了。
●创建可翻转的动画。通过将autoreverse属性设置为true 来创建可翻转的动画。例如,当按钮增-长动画不再增加按钮的宽度时,将反向播放动画,返回到原始宽度。动画的总持续时间也将翻倍。
●改变fillbehavior属性。通常,fillbehavior 属性被设置为holdend,这意味着当动画结束时,会继续为目标元素应用最后的值。如果将fillbehavior 属性改为stop,只要动画结束,属性就会恢复为原来的值。
●当动画完成时通过处理动画对象的completed事件删除动画对象。
前3种方法改变了动画的行为。不管使用哪种方法,它们都将动画后的属性设置为原来的数值。如果这并非所希望的,那就需要使用最后-种方法。
首先,在启动动画前,关联事件处理程序以响应动画完成事件:
widthanimation. completed += animation_ completed;
==注意:==
completed事件是常规的.net事件,使用常规的没有附加信息的eventargs 对象。该事件不是路由事件。

timeline类
名称 说明
begintime 设置将被添加到动画开始之前的延迟时间(timespan类型)。这一-延迟时间被加到总时间,所以具有5秒延迟的5秒动画,总时间是10秒。当同步在同一时间开始,但按顺序应用效果的不同动画时,begintime 属性是很有用的
duration 使用duration对象设置动画从开始到结束的运行时间
speedratio 提高或减慢动画速度。通常,speedratio 属性值是1。如果增加该属性值,动画会加快(例如,如果speedratio属性的值为5,动画的速度会变为原来的5倍);如果减小该属性值,动画会变慢(例如,如果speedratio属性的值为0.5,动画时间将变为原来的两倍)。可通过改变动画的duration属性值得到相同结果。当应用begintime 延迟时,不考虑speedratio属性的值
accclerationratio;decelerationratio 使动画不是线性的,从而开始时较慢,然后增速(通过增加acelerationratio 属性值):或者结束时降低速度(通过增加decelerationratio属性值)。这两个属性的值都在0~1之间,并且开始时都设置为0。此外,这两个属性值之和不能超过1
autoreverse 如果为true,当动画完成时会自动反向播放,返回到原始值。这也会使动画的运行时间加倍。如果增加speedratio属性值,就会应用到最初的动画播放以及反向的动画播放。begintime属性值只应用于动画的开始一不 延迟反向动画
fillbehavior 决定当动结束时如何操作。通常,可将属性值保持为固定的结束值(fillbchavior. holdend),但是也可选择将属性值返回为原来的数(fillbehavior stop)
repeatbehavior 通过该属性,可以使用指定的次数或时间间隔重复动画。用于设置这个属性的repeatbehavior对象决定了确切的行为
故事板

在所有声明式动画中都会用到如下两个要素:
故事板: 故事板是beginanimation( )方法的xaml等价物。通过故事板将动画指定到合适的元素和属性。
事件触发器: 事件触发器响应属性变化或事件(如按钮的click事件),并控制故事板。例如,为了开始动画,事件触发器必须开始故事板。
小案例:
基于C#WPF框架——动画

以上小案例为点单击按钮时,原形先向右移动到达to值后继续向左移动,矩形向右下角移动,当到达to值后原路返回向左上角移动,此动画为重复执行动画

首先需要引入动画类命名空间;

using system.windows.media.animation;

创建故事板:

        storyboard sto = new storyboard(); // 故事板
        storyboard stt = new storyboard(); // 向下故事板

初始化图形大小,位置:

            border bod = new border(); // 圆形
            bod.width = 100;
            bod.height = 100;
            bod.borderthickness =new thickness(10); // 设置原形边框厚度
            bod.borderbrush = brushes.yellow; // 边框颜色
            bod.background = brushes.purple; // 圆形背景色
            bod.cornerradius = new cornerradius(50); // 画圆
            bg.children.add(bod);
            border boo = new border(); // 矩形
            boo.width = 100;
            boo.height = 100;
            boo.background = brushes.cyan;
            canvas.setleft(boo, 100);
            canvas.settop(boo, 300);
            boo.cornerradius = new cornerradius(20);
            bg.children.add(boo);

动画情节:

doubleanimation move = new doubleanimation(); // 移动情节
            move.from = 0; // 初始值
            move.to = 400; // 结束值
            move.duration = new duration(new timespan(0, 0, 0, 3, 0)); // 需要的时间
            move.autoreverse = true; // 设置成返回
            move.repeatbehavior = repeatbehavior.forever; // 重复执行
            storyboard.settarget(move,bod); // 情节添加给对象
            //storyboard.settargetproperty(move, new propertypath(canvas.leftproperty)); // 改变lef位置
            storyboard.settargetproperty(move, new propertypath("(canvas.left)"));
            sto.children.add(move);

            coloranimation bianse = new coloranimation(colors.purple,colors.orange,timespan.frommilliseconds(300)); // 改背景色情节
            storyboard.settarget(bianse, bod);
            storyboard.settargetproperty(bianse, new propertypath("(border.background).(solidcolorbrush.color)"));
            sto.children.add(bianse);

            coloranimation biankuse = new coloranimation(colors.blue, colors.darkviolet,timespan.fromseconds(3));  // 改变边框颜色
            storyboard.settarget(biankuse, bod);
            storyboard.settargetproperty(biankuse, new propertypath("(border.borderbrush).(solidcolorbrush.color)"));
            sto.children.add(biankuse);

            thicknessanimation kuang=new thicknessanimation(new thickness(10),new thickness(20),timespan.frommilliseconds(30));  // 改变边框厚度
            storyboard.settarget(kuang, bod);
            storyboard.settargetproperty(kuang, new propertypath("borderthickness"));
            sto.children.add(kuang);

            doubleanimation zhuan = new doubleanimation(0, 360, new duration(timespan.fromseconds(3))); // 旋转情节
            storyboard.settarget(zhuan, bod);
            zhuan.autoreverse = true;
            zhuan.repeatbehavior = repeatbehavior.forever;
            storyboard.settargetproperty(zhuan, new propertypath("rendertransform.angle"));
            sto.children.add(zhuan);
            rotatetransform xuanzhuan = new rotatetransform(); // 旋转对象
            bod.rendertransform = xuanzhuan;
            bod.rendertransformorigin = new point(0.5,0.5);

            // 控制boo  向下移动并 旋转
            doubleanimation yidong = new doubleanimation();// 移动右
            yidong.from = 0;
            yidong.to = 500;
            yidong.duration = new duration(timespan.fromseconds(3)); // 设置毫秒数
            yidong.autoreverse = true; // 返回原路
            yidong.repeatbehavior = repeatbehavior.forever; // 重复执行
            storyboard.settarget(yidong, boo);
            storyboard.settargetproperty(yidong, new propertypath("(canvas.left)"));
            stt.children.add(yidong);
            doubleanimation yidong_ = new doubleanimation(canvas.gettop(boo),(canvas.gettop(boo)+400),new duration(timespan.fromseconds(3))); // 移动下
            yidong_.autoreverse = true;
            yidong_.repeatbehavior = repeatbehavior.forever;
            storyboard.settarget(yidong_, boo);
            storyboard.settargetproperty(yidong_,new propertypath("(canvas.top)"));
            stt.children.add(yidong_);
            doubleanimation xiazhuan = new doubleanimation(0, 360, new duration(timespan.fromseconds(3))); //旋转情节
            storyboard.settarget(xiazhuan, boo);
            xiazhuan.autoreverse = true; //可原路返回
            xiazhuan.repeatbehavior = repeatbehavior.forever;// 重复执行
            storyboard.settargetproperty(xiazhuan, new propertypath("rendertransform.angle"));
            stt.children.add(xiazhuan);
            rotatetransform xuanzhuan = new rotatetransform(); // 旋转对象
            boo.rendertransform = xuanzhuan;
            boo.rendertransformorigin = new point(0.5, 0.5);

点击按钮:

        private void btn_click(object sender, routedeventargs e)
        {
            sto.begin(); // 开启动画
            stt.begin();
        }