精华内容
下载资源
问答
  • 一加手机开机动画教程,一加手机如magisk更换开机动画入开机动画最新教程,本教程以一加手机为例,系统地详解一加手机入开机动画的步骤,感兴趣的用户一起来试试吧刷机教程:本教程以一加手机为例,理论上...

    一加手机开机动画教程,一加手机刷如magisk更换开机动画,刷入开机动画最新教程,本教程以一加手机为例,系统地详解一加手机刷入开机动画的步骤,感兴趣的用户一起来试试吧

    刷机教程:

    本教程以一加手机为例,理论上支持安卓全部机型,设置开机动画,在这之前手机需获取ROOT权限,可以下载magisk最新版,如果手机已经有twrp适配,也可刷入TWRP

    获得面具magisk完美并且root后,就是刷入开机动画模块了,模块为ZIP格式,下载好模块放进手机相关文件夹,我们推荐更新为MagiskManager-v8.0.2版本

    afc412b6b745284c83e4d1dff58bc207.png

    然后就可以根据以下教程开始了打开桌面上的面具新版

    2ec799711a43249798ea2d2e8b60a7ad.png

    点击右下角的模块按钮-再点击【从本地安装】功能,会进入存储相关功能,再点击左上角的【三个横线】-显示文件管理等内容,点击【文件管理】这就进入了内置卡了,找到我们之前放进去的开机动画模块,格式为.zip,点击下,再选择确定,就开始自动刷入了,刷入完成后,右下角出现重启按钮,我们重启手机,轻松完成

    开机动画模块下载:

    提取码:MNSJ

    注意:

    刷机有风险操作需谨慎

    该模块支持氢OS10以及氢OS11系统

    来源:xcl

    展开全文
  • iOS 动画队列-仿映客礼物效果

    千次阅读 2016-07-19 11:27:57
    最近在研究直播的相关知识,在网上看到了不少优秀的开源项目,GrayJIAXU 的520Linkee,比较完备的实现了作为一个直播 App 的基本功能,比如本地视频流采集、播放、美颜、礼物、点赞出心等。...

    最近在研究直播的相关知识,在网上看到了不少优秀的开源项目,GrayJIAXU 的520Linkee,比较完备的实现了作为一个直播 App 的基本功能,比如本地视频流采集、播放、美颜、礼物、点赞出心等。http://t.cn/Rtv6oyq 2. SunLiner的MiaowShow,高仿<喵播APP> ,http://t.cn/R5rdlPW

    可惜都没有看到映客那个刷礼物的效果,于是手痒痒,决定自己做一个~

    这里写图片描述

    1. 首先从简单的开始,文字描边+连击效果,这个比较简单,只要重写 UILabel 的- (void)drawTextInRect:(CGRect)rect 就可以达到文字描边的效果;然后开定时器,让数字增加,动画效果用关键帧动画控制。

    2. 然后仿照映客的 UI 自定义 View ,控制动画,从屏幕外面进入,然后显示连击效果,最后隐藏,恢复到初始位置。

    3. 上面的动画效果只要稍微有点动画基础,很容易就搞定了。做到这里我冷静下来,不再往下面做了,因为事情远远没有想象的那么简单。首先考虑的是,在收到礼物消息的回调时去赋值数据源, 运行动画,但是这个回调是是一个字典数组,里面包含了一段时间内多条消息,他们是有顺序的,这是其一;其二,这个回调调用次数会很频繁,短时间内就会收到更多的消息数组。所以需要把这些消息处理成队列,然后播放动画效果,一个动画效果播放完成后,再从消息队列中取下一个消息,继续播放下一个动画,这样才能保证动画的播放顺序不回乱。
      说到队列的话就想到了多线程,NSOperation ,我们可以重写它,然后在 start 方法中添加动画,但是注意我们只是需要让这些消息排队,更新 UI 还是要在主线程操作;我们还要手动触发 NSOperation 的 KVO,告诉这个操作什么时候开始,什么时候算是结束,我们想在一个动画播放完毕后再执行下一个动画,于是我这里定义了一个 block ,在动画结束时,传递给 NSOperation ,告诉它动画结束了。

    @synthesize finished = _finished;
    @synthesize executing = _executing;
    
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            _executing = NO;
            _finished  = NO;
        }
        return self;
    }
    
    - (void)start {
    
        if ([self isCancelled]) {
            self.finished = YES;
            return;
        }
        self.executing = YES;
    
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            _presentView = [[PresentView alloc] init];
            _presentView.model = _model;
            // i % 2 控制最多允许出现几行
            _presentView.frame = CGRectMake(-self.listView.frame.size.width / 2, 300 - (_index % 2) * 70, self.listView.frame.size.width / 2, 40);
            _presentView.originFrame = _presentView.frame;
            [self.listView addSubview:_presentView];
            [self.presentView animateWithCompleteBlock:^(BOOL finished) {
                self.finished = finished;
            }];
        }];
    
    }
    
    #pragma mark -  手动触发 KVO
    - (void)setExecuting:(BOOL)executing
    {
        [self willChangeValueForKey:@"isExecuting"];
        _executing = executing;
        [self didChangeValueForKey:@"isExecuting"];
    }
    
    - (void)setFinished:(BOOL)finished
    {
        [self willChangeValueForKey:@"isFinished"];
        _finished = finished;
        [self didChangeValueForKey:@"isFinished"];
    }   
    
    

    注意这里 :

     _presentView.frame = CGRectMake(-self.listView.frame.size.width / 2, 300 - (_index % 2) * 70, self.listView.frame.size.width / 2, 40);// i % 2 控制最多允许出现几行
    
     queue.maxConcurrentOperationCount = 2; // 队列分发 
    

    当时其实只是实现了一个队列,按顺序一个一个播放,如何实现 N 列并发呢?其实把这些并发的动画队列想象成图片的多并发异步下载就好了,下意识地就加了上面两句控制并发列数的代码。能这么顺利做出来,是因为最近仔细研究了 SDWebImage 的源码,不觉得重写 NSOperation 那个方式很熟悉么~哈哈。最近工作忙,动画的细节和封装性没有再完善,不过易用性我感觉还是很好的,最后附上 demo 地址和使用方法,祝大家玩得开心~

    Demo 地址:https://github.com/cooxu/PresentAnimView.git

    问题交流:icooxu@163.com

    展开全文
  • //// attrs.xml 自定义属性,该属性主要是控制动画播放的时间 <?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="SlidingText"> <attr...

     

    首先看看效果:

     2011041022523753.gif

    ///项目布局

    2011041022530693.png

    attrs.xml    自定义属性,该属性主要是控制动画播放的时间

    
      
    <? xml version="1.0" encoding="utf-8" ?>

    < resources >

    < declare-styleable name ="SlidingText" >

    < attr name ="animationDuration" format ="integer" />

    </ declare-styleable >

    </ resources >

     

    / main.xml   

    
      
    <? xml version="1.0" encoding="utf-8" ?>

    < LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android"

    android:orientation
    ="vertical" android:layout_width ="fill_parent"

    xmlns:slidingtext
    ="http://schemas.android.com/apk/res/com.testSildingTextView"

    android:layout_height
    ="fill_parent" >





    < com.testSildingTextView.SlidingTextView

    android:id ="@+id/sliding_textview" android:layout_width ="fill_parent"

    android:layout_height
    ="wrap_content"

    slidingtext:animationDuration
    ="500"

    android:layout_gravity
    ="center" >

    < TextView android:layout_width ="fill_parent" android:gravity ="center_horizontal"

    android:layout_height
    ="wrap_content" android:text ="sssssss" />

    </ com.testSildingTextView.SlidingTextView >



    </ LinearLayout >

     

    首先自定义名称xmlns:slidingtext=http://schemas.android.com/apk/res/com.testSildingTextView

    这里使用了自定义的名称

    slidingtext:animationDuration="500"

     

    下面是动画效果的关键代码,大概说明一下它的功能。这个动画效果主要是每次开出一条线程来运行的,首次运行后等2点5秒,就将textview以动画效果向左运行,等0.5秒后从右边出现,动画结束后隐藏,不断循环

    / SlidingTextView

    
      
    private String[] showTexts = new String[] { " ssssss " , " aaaaaa " , " bbbbbb " };
    // 用来记录显示哪个字符串
    private int count = 0 ;
    private int mDuration;
    private TextView text;
    private int textWidth = 200 ;

    // 获取自定义变量
    public SlidingTextView(Context context, AttributeSet attrs) {
    super (context, attrs);
    TypedArray a
    = context.obtainStyledAttributes(attrs,
    R.styleable.SlidingText);
    mDuration
    = a
    .getInteger(R.styleable.SlidingText_animationDuration,
    750 );
    }
    // 设置要显示的字符串
    public void setShowText(String[] showTexts){
    this .showTexts = showTexts;
    }

    // 回调函数 界面初始化快结束时调用
    protected void onFinishInflate() {
    super .onFinishInflate();

    text
    = (TextView) this .getChildAt( 0 );

    mHandler.postDelayed(appear,
    1000 );
    }
    private Handler mHandler = new Handler() {

    @Override
    public void handleMessage(Message msg) {
    // 1为出现,2为隐藏
    switch (msg.arg1) {
    case 1 :
    doAnimationOpen();
    break ;
    case 2 :
    doAnimationClose();
    break ;
    }
    }
    };

    public void doAnimationOpen() {
    post(appear);
    }

    // 出现的效果
    Runnable appear = new Runnable() {
    public void run() {
    TranslateAnimation animation;
    int fromXDelta = 0 , toXDelta = 0 , fromYDelta = 0 , toYDelta = 0 ;
    int calculatedDuration = 0 ;

    fromXDelta
    = textWidth;
    toXDelta
    = 0 ;
    calculatedDuration
    = mDuration * Math.abs(toXDelta - fromXDelta)
    / textWidth;

    animation
    = new TranslateAnimation(fromXDelta, toXDelta,
    fromYDelta, toYDelta);
    animation.setDuration(calculatedDuration);
    animation.setAnimationListener(
    new AnimationListener() {

    @Override
    public void onAnimationStart(Animation animation) {
    if (showTexts.length != 0 ){
    count
    = (count + 1 ) % showTexts.length;
    text.setText(showTexts[count]);
    }
    text.setVisibility(VISIBLE);
    }

    @Override
    public void onAnimationRepeat(Animation animation) {

    }

    @Override
    public void onAnimationEnd(Animation animation) {
    mHandler.postDelayed(hide,
    2500 );
    }
    });
    startAnimation(animation);

    }
    };

    public void doAnimationClose() {
    post(hide);
    }
    // 隐藏的效果
    Runnable hide = new Runnable() {
    public void run() {
    TranslateAnimation animation;
    int fromXDelta = 0 , toXDelta = 0 , fromYDelta = 0 , toYDelta = 0 ;
    int calculatedDuration = 0 ;

    toXDelta
    = - 1 * textWidth;

    calculatedDuration
    = mDuration * Math.abs(toXDelta - fromXDelta)
    / textWidth;

    animation
    = new TranslateAnimation(fromXDelta, toXDelta,
    fromYDelta, toYDelta);
    animation.setDuration(calculatedDuration);
    animation.setAnimationListener(
    new AnimationListener() {

    @Override
    public void onAnimationStart(Animation animation) {

    }

    @Override
    public void onAnimationRepeat(Animation animation) {

    }
    // 动画结束时 设置textview的状态
    @Override
    public void onAnimationEnd(Animation animation) {
    mHandler.postDelayed(appear,
    500 );
    text.setVisibility(INVISIBLE);
    }
    });
    startAnimation(animation);
    }
    };

     

    本文为原创,如需转载,请注明作者和出处,谢谢!

    代码下载

    http://files.cnblogs.com/not-code/testSildingTextView.zip

    转载于:https://www.cnblogs.com/not-code/archive/2011/04/10/2011929.html

    展开全文
  • 一:形状 在WPF用户界面中,可以通过形状(Shape)来绘制直线、椭圆、矩形及一些多边形的类。通过这些基本的图像,组合成为复杂的图形。 Shape类中,主要的形状有Rectangle(),Ellipse(),Line,...作用 ...

    一:形状

    在WPF用户界面中,可以通过形状(Shape)来绘制直线、椭圆、矩形及一些多边形的类。通过这些基本的图像,组合成为复杂的图形。

    Shape类中,主要的形状有Rectangle(),Ellipse(),Line,Polyline(),Polygon(),Path(),都继承自抽象类System.Windows.Shapes.Shape。

    名称作用
    Rectangle矩形
    Ellipse椭圆
    Line直线
    Polyline一系列相互连接的直线
    Polygon一系列连接的直线的闭合图像
    Path将多个基本形状组合成单独的元素

    在Shape类中,有一些重要的属性,下面用一个矩形和椭圆例子来简单介绍。

        <StackPanel>
            <Ellipse Fill="Yellow" Stroke="Blue" Height="50" Width="100" Margin="5" HorizontalAlignment="Left"></Ellipse>    <!--fill填充对象,stroke边框颜色-->
            <Rectangle Fill="Yellow" Stroke="Blue" Height="50" Width="100" Margin="5" HorizontalAlignment="Left"></Rectangle>
            <Label Content="圆角边距10"></Label>
            <Rectangle Fill="Yellow" Stroke="Blue" Height="50" Width="100" Margin="5" RadiusX="10" RadiusY="10" HorizontalAlignment="Left"></Rectangle><!--Radius影像矩形的圆角大小-->
            
        </StackPanel>

    Fill属性决定填充的颜色,Stroke边框颜色,在Rectangle类中多了RadiusX、RadiusY,决定了矩形圆角的大小。

    小结:

    在图元拜访过程中,一般不使用StackPanel、DockPanel、WrapPanel面板,因为他们被设计成了独立的元素,Grid面板稍微灵活一点,它允许同一个单元格中放置 任意个元素。最理想的是用Canvas容器,直接用为每个形状指定坐标。

    小技巧:

    不要用Canvas占据整个窗口,可以先创建个Grid面板,在Grid面板的某个单元格中使用Canvas容器。对于可以自由流动的动态用户界面中锁定一小部分进行绘图,是一种非常好的方法。

    3.使用Viewbox控件缩放形状

    使用Canvas面板唯一的限制是不能改变图元自身的尺寸适应窗口大小。有些情况下,我们希望图元随着窗口大小改变尺寸,这样可以更好的利用可用空间。而使用Viewbox这个类只接受一个子元素,不过子元素可以是布局容器,在容器中可以包含其他元素。通常我们在Viewbox中放置Canvas,然后再Canvas面板中放置图形。

    下面的例子就是在Viewbox中放置Canvas,Canvas中放置矩形和椭圆,随窗口大小改变进行缩放。

        <Grid Margin="5">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
            </Grid.RowDefinitions> 
            
            <Label Content="The first row of a grid"></Label>
            
            <Viewbox Grid.Row="1" HorizontalAlignment="Left">
                <Canvas Width="200" Height="150">
                    <Ellipse Fill="Yellow" Stroke="Black" Canvas.Left="10" Canvas.Top="50" Width="100" Height="50" HorizontalAlignment="Left"></Ellipse>
                    <Rectangle Fill="Yellow" Stroke="Black" Canvas.Left="30" Canvas.Top="40" Width="100" Height="50"></Rectangle>
                </Canvas>
            </Viewbox>
        </Grid>

     

    在涉及到缩放图形时,最好被缩放的是矢量图,这样的话尺寸改变,图像不会因为分辨率不高,变得不清晰。

     

    Line直线:

    由2个点来控制,X1点和X2点决定线段的起始位置,Line类中没有Fill属性,只能用Stroke属性填充线段的颜色,坐标原点在布局容器的左上角。

    <Line Stroke="Blue" X1="0" Y1="0" X2="50" Y2="50"></Line>

    Polyline折线:

    用多个连续的点控制,依次连接。

    <Polyline Stroke="Blue" Points="0,0 20,60 40,0 60,60 80,0 100,80"></Polyline>

    Polygon多边形:

    Polygon类和Polyline类相似,是一系列点的集合,不过最好加上了一条线,将第一个点和最后一根点连了起来。绘制五角星

    <Polygon  Fill="Green" Stroke="Blue" Points="15,200 68,70 110,200 0,125 135,125"></Polygon>

     

    二:画刷

    画刷填充区域,常见的画刷有

    名称说明
    SolidColorBrush使用单一颜色区域绘制
    LinearGradientBrush可以从一种颜色渐变到另一种颜色,也可以多种颜色渐变,线性渐变
    RadialGradientBrush径向渐变填充,类似圆的放射
    ImageBrush用可被拉伸缩放的图像填充区域
    DrawingBrush使用Drawing对象绘制区域,对象可包含已定义的形状和位图
    VisualBrush可使用该画刷讲部分用户界面复制到另一个区域。
    BitmapCacheBrush使用Visual对象缓冲的内容绘制区域,和VB画刷类似,但效率更高

    使用RadialGradientBrush画刷画一个径向渐变的圆,GradientOrigin设置径向渐变的中心,offset偏移量

            <Ellipse Stroke="Black" Width="200" Height="200">
                <Ellipse.Fill>
                    <RadialGradientBrush RadiusX="1" RadiusY="1" GradientOrigin="0.7,0.3">
                        <GradientStop Color="White" Offset="0"></GradientStop>
                        <GradientStop Color="Blue" Offset="1"></GradientStop>
                    </RadialGradientBrush>
                </Ellipse.Fill>
            </Ellipse>

     

    使用ImageBrush可以用位图填充区域,通过设置ImageSource属性来指定希望的位图,

        <Grid Margin="5">
            <Grid.Background>
                <ImageBrush ImageSource="123.jpg"/>
            </Grid.Background>
        </Grid>

     

    转载于:https://www.cnblogs.com/SeekHit/p/4934219.html

    展开全文
  • 本文将重点探讨2个主要的功能的实现 1.裁剪功能 /**  * 裁剪  */ void drawClips() {  //获取上下文  CGContextRef context = UIGraphicsGetCurrentContext();    //画一个圆  CGContextAddEllipseInRect...
  • 上电>启动内核>优先加载动画驱动>开线程,线程中不断执行读和framebuffer的功能>完进应用层 套路就这个样子。接下去大概说下中间碰到的坑。 大坑: 这个是我自己的原因。我一开始选择并不是开线程,而是...
  • FLASH动画之制作动画

    2021-04-02 13:31:29
    创建补间动画 一、图片的去背 1、导入一张蝴蝶图片(其他图片也行),缩小,给舞台加上颜色。 2、点击蝴蝶图片,修改——分离,然后用套索工具中的魔术棒选中图片白色区域,删除,剩余蝴蝶图形。 3、按F8键创建图形...
  • 关键帧动画 骨骼动画Animated interfaces are full of life and emotions. Animations add life to static things. When it comes to UI interfaces, animations are not just about enthusiasm, but also about ...
  • 【简介】:和小鹿同学一起用动画的方式从零基础学编程,将 Web前端领域、数据结构与算法、网络原理等通俗易懂的呈献给小伙伴。先定个小目标,原创 1000 篇的动画技术文章,和各位小伙伴共同努力一起学习! 公众号...
  • ppt动画拓展库没有试用的,但是最早的版本提供试用功能,可以使用ppt动画格式,非常好用
  • Android 动画详解

    2018-07-16 19:09:41
    其实帧动画也属于View动画的一种,只不过他的表现形式不同而已,View动画通过对场景里的对象不断的做图像变换(平移,缩放,旋转,透明度)从而产生动画效果,他是一种渐进式动画,并且View动画支持自定义,帧动画...
  • iOS动画总结

    2018-12-20 13:11:30
    iOS动画实现方式和效果 ...显示层动画效果:利用UIView图层显示的效果实现各种动画,常用的效果有:位置动画、位移动画、颜色动画、淡入淡出动画、旋转动画、缩放动画、几何形状动画、组合动画(关键帧动画、逐帧...
  • VC Agent动画小人仿OFFICE助手动画,仿默林小人,像一个精灵一样,自动会动,可以做出听、读、写、发高兴、悲伤、思考、困惑、建议等多种表情,还有气泡提示的功能
  • PA动画使用教程

    2019-09-27 14:42:47
    PPT自带的动画刷会覆盖原有动画; 注意: 超级属性的动画复制、粘贴有bug,应使用自带的动画刷; PA动画的复制、粘贴只能实现一对一,一对多,无法实现多对一;但可以实现多对多,如3to3或3to6 快捷键Ctrl+Shift+...
  • 3.0之前,android支撑两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画统系:property animation,这三种动画模式在SDK中被称为property animation,view animation,drawable ...
  • 本篇将记录一下如何在WPF中绘画和设计动画,这方面一直都不是VS的强项,然而它有一套利器Blend;这方面也不是我的优势,幸好我有博客园,能记录一下学习的过程。在本记录中,为了更好的理解绘画与动画,多数的例子...
  • 近年来,H5页面火爆整个移动互联网,这些页面的炫酷展现,都离不开...01H5制作工具自带的动画功能目前市面上用的比较多的H5制作工具有木疙瘩、ih5等。关键帧动画:可以实现常见的动画效果,比如位移、大小、旋转、透...
  • 为了让幻灯片中的对象的动画效果丰富自然,我们可对其添加多个动画效果,例如,我们要对某张图片添加进入屏幕时的动画动作、在屏幕中的运动轨迹以及从屏幕中消失的动画动作,可先将该图片选中,然后依次添加进入式...
  • 动画作为一种表现形式应用在影视广告中,它的独特魅力在于赋予视觉符号生命的创造力;夸张、超越局限的表现力;在有限时间里构建视觉与听觉审美体验的建构能力。观众通过视觉、听觉、知觉参与其中,得到视听空白和...
  • iOS 动画篇 - UIKit动画(一)

    千次阅读 2018-12-04 17:55:15
    在前面文章中,有详细介绍过 Core Animation 动画,UIKit 动画实质上是针对核心动画的封装,不同的是,核心动画操作的是图层级别(CALayer),通常情况下,它不会影响到视图层,而 UIKit 针对的是视图级别(UIView)...
  • Android 动画技术

    千次阅读 2015-03-10 10:32:28
    关于android动画主要有三种:补间动画,逐帧动画和属性动画(android3.0以后引入)详细了解动画的基本知识,可详细阅读该博文http://www.cnblogs.com/angeldevil/archive/2011/12/02/2271096.html 。博文主要对...
  • 功能强大,美观的画图程序,可用于程序开发学习,可画多种图形,兼容DC无闪烁,可更改画图属性,可更改画笔,画的形状,颜色,有标尺与辅助线可帮助完成画图,设及到各种绘图元素,以及消息的流动。有自绘combobox...
  • unity2D动画-角色切片做动画写在前面的话开发环境与准备用角色切片做动画终于可以Key动画了2DAnimation插件做动画总结 写在前面的话 这个不算教程的教程主要是让组里的美术与策划们看的,会写的十分基础与详细,为...
  • VC++版多表情默林小人动画演示代码,可以选择听、读、写、发高兴、悲伤、思考、困惑、建议等多种状态时的表情,憨态可掬的默林先生完全由你控制哦,别外它还附带了一个类似气泡提示功能的讲话模块。
  • ppt学习07——动画

    2020-07-21 13:28:33
    2.添加动画:当图形已经有了动画,想再插入一个动画,则需要点添加动画按94AE 3.进入动画,从无到有;强调动画,做突出动作;退出动画:从有到无 4.路径动画,元素按照预设...7.动画刷:用于复制粘贴动画 动画->高
  • android动画

    2014-07-15 12:52:49
    Android 3.0之前支持两种动画模式,tween animation
  • (最新版的“语音合成”功能已经要收费使用,幸好存有老版本)(请注意32位和64位的区别) 安装程序执行完毕,万彩动画大师已经成功安装到您的电脑,现在您可以开始制作专属的多媒体动画视频、动画宣传片!万彩动画大师...
  • 动画(uwp)

    2020-12-10 18:11:24
    动画概要 动画实质上是一系列静止的图像,随着时间的推移不断进行切换,由于人眼的视觉反应存在误差,使连续播放的静止画面看起来是运动的,而某段时间内所切换的每一个静态画面被称为"帧"。假设在1秒内播放了25个...
  • 得一下就过去了,没有动画 动画就是在一定时间内,不断地调用setTranslationX一点一点的靠近,这个过程要在子线程中进行 下面写一个演示属性动画原理demo final float[] newTranslation = {0}; Runnable ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,172
精华内容 4,468
关键字:

动画刷的功能是