作者采用vs2008编译,c#代码

Animated Eye Candy for Programmers
By Phillip Piper | 17 Apr 2010
A class library that allows (almost) any Control to show animations
Is your email address OK? You are signed up for our newsletters but your email address is either unconfirmed, or has not been reconfirmed in a long time. Please click here to have a confirmation email sent so we can confirm your email address and start sending you newsletters again. Alternatively, you can update your subscriptions.
Download demo - 673.91 KB
Download full code - 405.76 KB
Animations on a Controls (e.g. a DataListView)

Google Enviers' Anonymous

"I'd like to welcome you all to this weeks meeting of Google Enviers' Anonymous. Hi. My name is Phillip and I'm a Google envier. I've managed to control my condition for almost six days. But this morning, I fell off the wagon in a big way. I was working normally and then I saw it! You all know what happens next. My breathing was suddenly rapid and shallow. I reached for my paper bag to keep calm. But it was too late. Waves of jealousy swept over me. In desperation, I speed-dialed my Google Envier buddies, Steve and Bill, and they talked me through it. After a minute or so, the spasm passed and I returned to (more or less) normal, though the bitter taste of envy lingered for the rest of the day.

In my self defence, the source of my envy is nothing as crass as their billion dollar development budget, their wonderful working conditions, or their thousand plus dollar share price. All these things fall into insignificance in comparison with the true object of my obsession: their animations! The way they effortlessly add little spinning stars, glowing text or fading sparkles to their applications. My applications sit there fully functional and obedient -- but static and passive, lacking the moving eye candy that make Google apps cute and cool.

But no more! To you, fellow enviers, I present the Sparkle animation framework. With this framework, you too can put animations into your applications and free yourself from the shackles of Google envy."
Understanding Sparkle in 30 Seconds or Less

OK. A little more seriously this time. The Sparkle library's purpose is to allow (almost) any Control to show animations.

The design goals of the Sparkle library are:
Short-lived animations on any control. The Sparkle library is designed to draw short animations over the top of existing Controls.
Declarative. The Sparkle library is declarative. You say what you want the animation to do, and then you run the animation. The animation is completely defined before it begins.
Non-interactive. The Sparkle library does not do user interaction -- it does not listen to mouse moves, clicks or drags. It doesn't do collision detection or physics models. It just draws eye candy.

To use the library itself, you'll need to grasp its four major concepts:
Animations. An animation is the canvas upon which sprite are placed. It is the white board upon which things are drawn.
Sprites. Sprites are things that can be drawn. There are several flavours of sprites -- one for images, another for text, still another for shapes. It is normal to make your own types of sprites by subclassing Sprite (or implementing ISprite).
Effects. Effects are things that make changes to sprites over time. They are the "movers and shakers" in the library, who actually do things. Sprites sit there, completely passive, looking pretty, but the effects push them around, change their visibility, spin or size. Again, you can use existing Effects, or implement your own through the IEffect interface.
Locators. Locators are things that known how to calculate a point or a rectangle. Rather than saying "Put this sprite at (10, 20)," they allow you to say "Put this sprite at the bottom right corner of this other sprite." This idea can be tricky to get your mind around, but once you have grasped it, it is powerful.
How to Use It

Adding any sort of animation to an application is a multi-step process. With Sparkle, the workflow for creating an animation is:
Decide where the animation will appear. That is your Animation.
Think about what you want to show. They are your Sprites.
Think about what you want each Sprite to do. They are your Effects.
Whenever an Effect needs a "where", that's when you need Locators.
Simple Example

To get a feeling for how to use the library, there's no substitute for seeing code. So let's do a simple example of moving a word across a control.

According to our workflow (above), we first need to decide where we want our animation to appear. So let's make a new project, with a new form, and put on it a UserControl that's docked to fill the whole form. Put a button on the form called "Run". In the click handler for that button, we'll do the work of running an animation.

The first thing we need is an Animation on that UserControl.
 Collapse
AnimationAdapter adapter = new AnimationAdapter(this.userControl1); 
Animation animation = adapter.Animation;

AnimationAdapter is the class that links an Animation to an existing control. We've used a UserControl, but it could be any Control that supports the Paint event.

Once we have an Animation, the workflow says we need to decide what be seen: they are our Sprites. We want to show the word "Sparkle" so we make a TextSprite. If we had want to show an image, there is an ImageSprite, and to show shapes, there is a ShapeSprite. You can (of course) make your own sprites by implementing the ISprite interface or by subclassing Sprite:
 Collapse
TextSprite sparkle = new TextSprite("Sparkle!", new Font("Gill Sans", 48), Color.Blue);

OK. We have our sprite. What do we want it to do? We want to move it from the top left of animation to the bottom right. Moving (or any other sort of change over time) requires an Effect. In this case, we need a MoveEffect. You can create these directly – using new MoveEffect(...) – or you can use the Effects factory, which has lots methods to make Effect objects:
 Collapse
sparkle.Add(100, 1000, Effects.Move(Corner.TopLeft, Corner.BottomRight));

This says, “Beginning 100 milliseconds after the sprite starts, and lasting for 1000 milliseconds, move this sprite from the top right to the bottom left of the animation.”

That’s all we want the sprite to do at the moment, so now we add the sprite to the animation. Not all sprites are active at the beginning of the animation, so when we add the sprite the animation we also tell it when the sprite should begin. In this case, we do want the sprite to start when the animation starts, so we give 0 as the start time for the sprite:
 Collapse
animation.Add(0, sparkle);

And finally, we tell the animation to run:
 Collapse
animation.Start();

All being well, you should see something like this:

For those who noted that the above graphic lacks one of the fundamental requirements for an animation (namely animated-ness), CodeProject doesn't support animations within a page, so click here to see the actual animation.
A Little More Interesting

Under whelmed? Admittedly, it's not that impressive, but you did only write six lines of code! But if we add a few different effects, you can easily do something more impressive. For example, if we want the text to walk around the edge of the control, spinning and fading at the same time:
 Collapse
sparkle.Add(0, 5000, Effects.Rotate(0, 360 * 4));
sparkle.Add(0, 5000, Effects.Blink(5));
sparkle.Add(0, 5000, Effects.Walk(Locators.AnimationBounds(-100, -50),
 WalkDirection.Anticlockwise));

This gives the Sprite three effects that run simultaneously. The first two are fairly obvious, but the third is a little trickier. It uses the Effects factory to create an effect that will walk a sprite around a rectangle. The rectangle to be walked is a "where" so it uses a Locator. This particular locator returns the bounds of the Animation, inset by (100, 50).

Putting these together produces this:

Again, you have to look here to see the actual animation.

Admittedly, this is garish, but it does give an idea of what you can do with just a few more lines of code.
Animations

An animation has two distinct functions:
It implements a timer tick based animation system. At each tick of a clock, it advances the state of the animation: it decides which sprites should become active/inactive, gives effects the opportunity to do their magic. This portion does not perform any rendering -- it simply changes the state of parts of the animation. If anything needs to be rendered, the animation triggers a Redraw event.
It draws the sprites according to their current state. Normally, something would listen for the Redraw event on an Animation, and in response to that event, it would redraw the animation. To do that, it calls the Animation.Draw(Graphics g) method. This will render the animation, in its current state, onto the given Graphics object. This operation does not change the state of the Animation.

In addition to animating sprites and rendering them, an animation supports the basic set of commands to control its execution:
Start()
Pause()/Unpause()
Stop()
Repeat Behaviour

Animations have a Repeat property, which controls the animation's behaviour when it reaches the end of the animation.
Repeat.None - The animation simply quits. All sprites disappear. This is the default.
Repeat.Pause - The animation pauses. All sprites that were visible at the end of the animation remain visible and motionless.
Repeat.Loop - The animation begins again.
Sprites

Sprite are the actual eye candy -- the pretty do-nothing things that the user can see. They keep whatever state information they require -- location, size, color, transparency -- and then use that state information to draw themselves when asked. They don't change their own state -- that's the responsibility of Effects.

There are several flavours of sprites that come with the Sparkle library:
ImageSprite. This takes an Image and draws it according to the sprites state. If the given Image is a frame animation itself, the Sparkle framework will animate that image automatically. I think it is only animated GIFs that Microsoft supports as frame animations.
TextSprite. TextSprites draw text (no prizes). But they can do a bit more formatting than just that. The text can be colored (ForeColor property), they can be drawn with a background (BackColor property). They can draw a border around the text (BorderWidth and BorderColor properties). The border can be either a rectangle (set CornerRounding to 0) or a round cornered rectangle (set CornerRounding to greater than 0 -- 16 is normally nice).
ShapeSprites. These draw regular shapes (square, rectangles, round cornered rectangle, triangles, ellipses/circles). Like TextSprites, ShapeSprites can have a ForeColor (color of frame of the shape), BackColor (used for the filled part of the shape), and PenWidth (width of the frame).

Remember, all colors can have alpha values set for them, which will allow varying levels of transparency when drawing the sprites.
Custom Sprites

It is expected that application would implement new sprites to do whatever specialized drawing it requires. To do this, you would implement the ISprite interface or subclass Sprite directly.
 Collapse
public interface ISprite : IAnimateable
{
   /// <summary>
   /// Gets or sets where the sprite is located
   /// </summary>
   Point Location { get; set; }
  
   /// <summary>
   /// Gets or sets how transparent the sprite is.
   /// 0.0 is completely transparent, 1.0 is completely opaque.
   /// </summary>
   float Opacity { get; set; }
  
   /// <summary>
   /// Gets or sets the scaling that is applied to the extent of the sprite.
   /// The location of the sprite is not scaled.
   /// </summary>
   float Scale { get; set; }
  
   /// <summary>
   /// Gets or sets the size of the sprite
   /// </summary>
   Size Size { get; set; }
  
   /// <summary>
   /// Gets or sets the angle in degrees of the sprite.
   /// 0 means no angle, 90 means right edge lifted vertical.
   /// </summary>
   float Spin { get; set; }
  
   /// <summary>
   /// Gets or sets the bounds of the sprite. This is boundary within which
   /// the sprite will be drawn.
   /// </summary>
   Rectangle Bounds { get; set; }
  
   /// <summary>
   /// Gets the outer bounds of this sprite, which is normally the
   /// bounds of the control that is hosting the story board.
   /// Nothing outside of this rectangle will be drawn.
   /// </summary>
   Rectangle OuterBounds { get; }
  
   /// <summary>
   /// Gets or sets the reference rectangle in relation to which
   /// the sprite will be drawn. This is normal the ClientArea of
   /// the control that is hosting the story board, though it
   /// could be a subarea of that control (e.g. a particular
   /// cell within a ListView).
   /// </summary>
   /// <remarks>This value is controlled by ReferenceBoundsLocator property.</remarks>
   Rectangle ReferenceBounds { get; set; }
  
   /// <summary>
   /// Gets or sets the locator that will calculate the reference rectangle
   /// for the sprite.
   /// </summary>
   IRectangleLocator ReferenceBoundsLocator { get; set; }
  
   /// <summary>
   /// Gets or sets the point at which this sprite will always be placed.
   /// </summary>
   /// <remarks>
   /// Most sprites play with their location as part of their animation.
   /// But other just want to stay in the same place.
   /// Do not set this if you use Move or Goto effects on the sprite.
   /// </remarks>
   IPointLocator FixedLocation { get; set; }
  
   /// <summary>
   /// Gets or sets the bounds at which this sprite will always be placed.
   /// </summary>
   /// <remarks>See remarks on FixedLocation</remarks>
   IRectangleLocator FixedBounds { get; set; }
  
   /// <summary>
   /// Draw the sprite in its current state
   /// </summary>
   /// <param name="g"></param>
   void Draw(Graphics g);
  
   /// <summary>
   /// Add an Effect to this sprite. This effect will run at the beginning of
   /// the sprite and will have 0 duration.
   /// </summary>
   /// <param name="effect">The effect to be applied to the sprite</param>
   void Add(IEffect effect);
  
   /// <summary>
   /// Add an Effect to this sprite. This effect will commences startTicks
   /// after the sprite begins and will have 0 duration
   /// </summary>
   /// <param name="startTick">When will the effect begins?</param>
   /// <param name="effect">What effect will be applied?</param>
   void Add(long startTick, IEffect effect);
  
   /// <summary>
   /// The main entry point for adding effects to Sprites.
   /// </summary>
   /// <param name="startTick">When will the effect begin?</param>
   /// <param name="duration">For how long will it last?</param>
   /// <param name="effect">What effect will be applied?</param>
   void Add(long startTick, long duration, IEffect effect);
}

Look carefully at the existing sprites to see how they should be implemented. Pay special attention to the role of co-ordinate transformations to handle Location and Rotation properties.
Effects

Effects are the movers and shakers of the Sparkle library. They push Sprites around, moving them here or there, making them visible or invisible, spinning them around. Any time you want a Sprite to change, you need an Effect.

Effects are given to a Sprite, and told when they should start and how long they will run for:
 Collapse
this.imageSprite.Add(100, 250, new FadeEffect(0.0f, 0.8f));

This says, "100 milliseconds after imageSprite starts in the animation, this FadeEffect should, during 250 milliseconds, fade the sprite from hidden (0.0 opacity) to 80% visible (0.8 opacity)."

Many Effects work by "tweening" - they are given an initial value and a target value, and as the effect progresses, the effect gradually change a property on their Sprite from the initial value to the end value. In the above example, the FadeEffect's initial value is 0.0 and its end value is 0.8. As the animation progresses, the FadeEffect would gradually change the Opacity property of its Sprite from 0.0 to 0.8. So, 100 milliseconds after the sprite starts, the imageSprite will be hidden; after 225 milliseconds, it will be 40% visible; after 350 milliseconds, it will be 80% visible, and then the effect will stop.
Effects Factory

Effects factory contains static methods to create many commonly used effects.
 Collapse
Move(Corner to)

Move the sprite from it's current location to a corner of the animation.
 Collapse
Move(Corner from, Corner to)

Move the sprite from one corner of the animation to another. This has a zillion variations which allow different ways of saying where to start and where to end.
 Collapse
Goto(Corner to)

Go to (as in Monopoly) the given corner without any transition.
 Collapse
Fade(float from, float to)

Change the Opacity of the sprite from the start to the end value, effectively fading it in or out.
 Collapse
Rotate(float from, float to)

Change the Spin of the sprite from the start to the end value (both in degrees).
 Collapse
Scale(float from, float to)

Change the Scale of the sprite, effectively making it bigger or smaller.
 Collapse
Bounds(IRectangleLocator locator)

Change the Bounds of the sprite.
 Collapse
Walk(IRectangleLocator locator)

This is the first interesting effect. This changes the location of the sprite so that it "walks" around the perimeter of the given rectangle. This has several flavours saying which exact point of the sprite will be walked, which direction the walk should take, and where the walking should start.
 Collapse
Blink(int repetitions)

Another interesting effect. This changes the Opacity of the sprite so that it blinks a number of times. There are a couple of variations that allow the characteristics of the "blink" to be changed: how long it takes to fade in, stay visible, fade out, stay invisible.
 Collapse
Repeater(int repetitions, IEffect effect)

This applies the given Effect several times to the Sprite.
Custom Effects

Of course, it's again expected that applications would want to make their ways to change Sprites. You might want a move effect that bounces a sprite along an arc, or that does a checker board transition between two images. To do your own stuff, you need to implement the IEffect interface.
 Collapse
public interface IEffect
{
    /// <summary>
    /// Gets or set the sprite to which the effect will be applied
    /// </summary>
    ISprite Sprite { get; set; }

/// <summary>
    /// Signal that this effect is about to applied to its sprite for the first time
    /// </summary>
    void Start();

/// <summary>
    /// Apply this effect to the underlying sprite
    /// </summary>
    /// <param name="fractionDone">How far through the total effect are we?
    /// This will always in the range 0.0 .. 1.0.</param>
    void Apply(float fractionDone);

/// <summary>
    /// The effect has completed
    /// </summary>
    void Stop();

/// <summary>
    /// Reset the effect AND the sprite to its condition before the effect was applied.
    /// </summary>
    void Reset();
}

Effects need to know what Sprite they are changing, and to know when they start and stop. A sequence diagram would look something like this:
Start()
Apply() [called 0 or more times, with any value 0.0..1.0]
Stop()
Reset() [called 0 or once]

The only interesting bit is the Apply() method. This is where Effect do their actual work. Notice that the Effect is given a "fraction done" value, not a click count (or something similar). Effects cannot rely on Apply() being called in any particular order: first Apply() could have fractionDone=0.1, the next time it could be 0.9 and then 0.5.

Also note that Reset() must revert the state of the Effect and the Sprite to their original conditions before the Effect was Start()'ed. This means that in the Start() method, effects normally store any state they are going to change, and then in Reset() that state is put back.
Locators

In some ways, locators are the most difficult concept to grasp. If you can get this concept, everything else normally falls into place.

A Locator is a point or a rectangle that can calculate itself whenever needed. A plain Point is fixed, but a PointLocator can be different every time it is called. By using a Locator, "how" a point is calculated can be replaced at runtime to use any strategy it likes.

For example, the MoveEffect changes the Location of a Sprite. It could be coded to move a Sprite to the TopLeft of an Animation:
 Collapse
this.Sprite.Location = this.Animation.Bounds.Location;

This is nice and obvious solution, but not very flexible. If we then wanted to move the sprite to the centre of the Animation, we'd have to write a separate line of code, and then give some way to choose which line to execute. And another line of code for ever other possible location we could want.

But with Locators, the MoveEffect simply says:
 Collapse
this.Sprite.Location = this.Locator.GetPoint();

By using this extra layer of abstraction, the intelligence of calculating the "where" is placed into a separate object, and becomes reusable from there.
Standard Locators

Locators is a factory that has static methods to produce many common locators. You can of course create the locators directly -- these are just a convenience.
 Collapse
IPointLocator At(int, int)

Create a PointLocator for a fixed point.
 Collapse
IPointLocator SpriteAligned(Corner corner)

Create a PointLocator which is where a Sprite must be moved to so that the given Corner is located at the corresponding corner of the Animation. So, Locators.SpriteAligned(Corner.BottomRight) calculates where a sprite must be moved to so that its BottomRight corner is at the BottomRight corner of the Animation.
 Collapse
IPointLocator SpriteAligned(Corner corner, Point offset)

Same as above, but the point is offset by the given fixed amount.
 Collapse
IPointLocator SpriteAligned(Corner corner, float proportionX, float proportionY)

Create a PointLocator which is where a Sprite must be moved to so that the given Corner is located at a point proportional across and down the bounds the Animation. So, Locators.SpriteAligned(Corner.BottomRight, 0.6f, 07.7) calculates where a sprite must be moved to so that its BottomRight corner is 60% across the Animation and 70% down.
 Collapse
IPointLocator SpriteBoundsPoint(Corner corner)

Create a PointLocator which calculates the given corner of the sprite's bounds.
 Collapse
IPointLocator SpriteBoundsPoint(float proportionX, float proportionY)

Create a PointLocator which calculates a given proportion across and down the sprite's bounds.
 Collapse
IRectangleLocator At(int, int, int, int)

Create a RectangleLocator for a fixed rectangle.
 Collapse
IRectangleLocator AnimationBounds()

Create a RectangleLocator for the bounds of the animation.
 Collapse
IRectangleLocator AnimationBounds(int x, int y)

Create a RectangleLocator for the bounds of the animation inset by the given amount.
 Collapse
IRectangleLocator SpriteBounds()

Create a RectangleLocator for the bounds of the sprite.
 Collapse
IRectangleLocator SpriteBounds(int x, int y)

Create a RectangleLocator for the bounds of the sprite inset by the given amount.
AnimationAdaptor

The AnimationAdaptor mentioned above gives an example of linking the Animation.Redraw event to the Animation.Draw() method. When the Animation triggers a Redraw event, the AnimationAdaptor invalidates its Control. This causes the Control to repaint itself, and when the control triggers the Paint event, the AnimationAdaptor renders the animation through the Draw() method. Voilá! Any Control (with a Paint event) can show an animation.

An AnimationAdaptor can be used on Panels, Buttons, Labels, PictureBoxes, UserControls, numeric spin controls, and (oddly enough) DataGridView. It cannot be used on another control because they don't usefully support the Paint event. There is nothing that can be done about RichTextBox and the others, but if you want to put animations on a ListView or a TreeView, have a look at the ObjectListView project, which does support these animations.

One of the beautiful things about the design of Sparkle is that it can be trivially used within another framework. To use it within WPF, all that is needed is an equivalent of the AnimationAdaptor, which listens for redraw events on the Animation, and then do something to make the animation redraw itself.
Performance

The Sparkle library performs fairly well when used in accordance with its design goals. Animating dozens of sprites with dozens of effects has a minimal impact on performance. On my laptop, 20 or so sprites with a variety of effects uses only about 2-3% of the CPU. The limiting factor is not the animation but the redrawing of the underlying control. Currently, the whole control is redrawn every frame. For simple controls, like Buttons or UserControls, this is not a problem, but for complicated control, like DataGridView, this redrawing quickly becomes taxing.

In a later version, I'll optimize to invalidate only the smallest possible area of the control.

I haven't tried using Sparkle with thousands of sprites. That really wasn't its purpose.
Status and Stability

Sparkle is a new library. It has worked well for me, but I'm sure there are bugs in it. Please report them and I will fix them.

The interfaces and major classes are stable, but not yet fixed (unchangeable). It's possible that I will add a few more properties to the ISprite interface (I think it needs Skew).
Conclusion

Go ahead. Dazzle your users with the glittery, snazzy animations.

Now when I look at Google's apps, I no longer suffer from envy. I still don't have their work conditions or share price, but when a little star spins and fades, I think, "Hey, I can do that too!"
To Do
Handle updates more efficiently (calculate damaged region and only redraw that portion).
Add fancier effects, like glow and mirror.
Add composites (ways of putting effects onto multiple sprites at same time).
Allow different interpolation calculations. All interpolations are currently linear. We should allow for example, acceleration, so that falling shapes in the demo accelerate as they fall.
Allow animations to reverse.
Library License

This library is released under the LGPL v2.0.
History
v0.8 - 30 March 2010
Initial public release
License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)
About the Author
 Phillip Piper

Software Developer (Senior)

Australia

Member  Phillip has been playing with computers since the Apple II was the hottest home computer available. He learned the fine art of C programming and Guru meditation on the Amiga.

Python and Smalltalk are his languages of choice. C# is interesting. C++ is to programming what drills are to visits to the dentist.

He has worked for longer than he cares to remember as Lead Programmer and System Architect of the Objective document management system. (www.objective.com)

He has lived for 10 years in northern Mozambique, teaching in villages.

He is currently developing trading and financial software for a high volume trading house.

Article Top  Rate this article for us!    Poor       
 Excellent

原文:

http://www.codeproject.com/KB/GDI-plus/Sparkle.aspx

Animated Eye Candy for Programmers相关推荐

  1. ps眼睛糖果滤镜插件 - Alien Skin Eye Candy 7 for Mac

    Alien Skin Eye Candy 7 汉化版又名ps眼睛糖果滤镜插件,插件包含了30多种Photoshop滤镜集,主要应用对象包含多种设计任务,字体,标志,网页设计等,使用对自然现象的模拟提供 ...

  2. PS一键生成鎏金字特效插件(糖果滤镜Skin Eye Candy)

    给大家带来的这款非常好用的PS糖果滤镜插件Skin Eye Candy汉化版,不用3D软件.更不用C4D,在PS就能一键生成金属以及各种材质质感.无论是制作字体效果,还是图形质感,都是秒出效果,用一次 ...

  3. 【强大精美的PS特效滤镜合集】Alien Skin Eye Candy for Mac 7.2.2.20

    [简介] Alien Skin Eye Candy for Mac 7.2.2 版本,支持最新的PhotoShop CC 2019.2018等版本,这是一款强大酷炫的PS特效滤镜合集,具有32种滤镜和 ...

  4. ps眼睛糖果滤镜插件:eye candy 7 汉化版(支持ps2021)

    Alien Skin Eye Candy 7 Mac汉化版是运行在photoshop上的特效滤镜插件,eye candy 7中文版可以为你的图像创建火焰.金属质感.闪电.动物皮毛.阴影等真实的效果,使 ...

  5. 眼睛糖果插件 Alien Skin Eye Candy 7.2.3.37 for Mac汉化版(10.14.1)

    眼睛糖果插件 Alien Skin Eye Candy 7.2.2.20Mac中文汉化版(支持CC2019) 软件版本: AlienSkin EyeCandy 7.2.2.20 fo Mac汉化版 支 ...

  6. Alien Skin Eye Candy 7 for Mac(PS眼睛糖果滤镜) v7.2.3.189

    Alien Skin Eye Candy 7 for Mac是一款非常实用的Photoshop特效滤镜合集.同时也是ps外挂滤镜中最广为人所使用的其中一组,包括30多种Photoshop滤镜集.由于A ...

  7. Alien Skin Eye Candy v7.x(眼睛糖果7)最新通用汉化补丁32/64位

    Alien Skin Eye Candy v7.x(眼睛糖果7)主要应用对象包含各种设计任务,字体,标志,网页设计等,通过对自然现象的模拟提供各种现实的精致效果.眼睛糖果 的界面简单直观,轻松提高你使 ...

  8. [Mac滤镜插件] 眼睛糖果插件 Alien Skin Eye Candy 7.2.3.37 for Mac汉化版

    眼睛糖果插件 Alien Skin Eye Candy 7.2.3.37Mac中文汉化版(支持CC2019) 软件版本: AlienSkin EyeCandy 7.2.3.37 fo Mac汉化版 支 ...

  9. Alien Skin Eye Candy 7 for Mac(眼睛糖果滤镜PS插件)

    Alien Skin Eye Candy 7 for Mac(眼睛糖果滤镜)是一款Mac平台上十分优秀的的PS滤镜插件,功能十分强大,滤镜集数量众多,包含30多种PS滤镜集,提供各种现实的精致效果,渲 ...

最新文章

  1. Python3中collections.OrderedDict介绍
  2. JS高级群的日常!写一个从10到0的倒计时,用console.log打印,不可以用 setInterval!本来说好的研究avalonJS最后演变成了看着大神在那边互相比拼实力。。...
  3. 【学习笔记】python - pyecharts
  4. 图像分割综述【深度学习方法】
  5. delphi socket 流的使用_Socket
  6. C# this关键字的3种用法
  7. minheight能继承吗_民法典亮点盘点 | 侄子能继承叔叔的遗产吗?
  8. 如何调用npm已经安装在全局位置的模块
  9. Excel数据转化为sql脚本
  10. 飞信2016 5.6.8820.0超级精简版
  11. 土建中级工程师考试用书电子版_湖南土建中级职称教材1.pdf
  12. Python 矩形法求1/x的定积分(完美实现)
  13. 无法打开internet站点,ie无法打开站点的解决方法【图解】
  14. Access to XMLHttpRequest at ‘http://localhost:8081/api/account/doLogin‘ from origin ‘http://localhos
  15. 沐阳JP1081B USB转网口 内核选项
  16. 技术之路如何成长而不迷茫
  17. 基于插件式的开发框架
  18. python语法报错原因_python萌新最常见5大错误
  19. Sql中的并(UNION)、交(INTERSECT)、差(minus)、除去(EXCEPT)详解
  20. gitlab导入project

热门文章

  1. 算法--生成m个指定范围的不重复随机数的三种方法分析(Java实现)
  2. cookies共享 sso_cookie共享(单点登录)
  3. 数据结构与算法—一文多图搞懂双链表
  4. Android利用广播实现ViewPager中item之间的数据通信
  5. 在数据准备区中允许使用的数据结构有哪些, 各有什么优点?
  6. sql 外连接的写法。
  7. 【必看】如何在 Linux 上恢复误删除的文件或目录
  8. 利用 Arthas 解决启动 StandbyNameNode 加载 EditLog 慢的问题
  9. linux分区大容量加入lvm,linux 添加磁盘+lvm扩容
  10. linux pmap命令,Linux pmap 命令用法详解-Linux命令大全(手册)