原文链接:http://cocoadevcentral.com/articles/000088.php
官方文档:https://developer.apple.com/library/mac/documentation/UserExperience/Reference/ScreenSaver/Classes/ScreenSaverView_Class/index.html
written by Brian Christensen
Writing a screen saver module is surprisingly simple using Mac OS X's screen saver framework. The ScreenSaverView class provides us with an interface for animating the screen saver, drawing the preview view in the System Preferences pane, and displaying a configuration sheet.
I originally wrote this article in 2001 when it was still necessary to jump through a few configuration hoops just to create a new screen saver project. An entire section was dedicated to "Preparing the Project." Thankfully, these steps are no longer required. Ever since the advent of Xcode Apple has included a default screen saver project template to make our lives significantly easier.
Having said that, this is not just a mere recycling of the old article. There is a considerable amount of fresh material which I hope will improve upon the original article.
Part 1: basics on set up, simple bezier path drawing, and user preferences using a configure sheet
Part 2: advanced topics such as setting up and using OpenGL for drawing
First, we'll need to create a new project. Launch Xcode and choose File > New Project. The window depicted below will appear:
From the list of choices you are presented with at this point select Screen Saver located under theStandard Apple Plug-ins category. Proceed to name the project MyScreenSaver (or any other name you prefer) and save it in your desired location. Once you have completed these steps, the project window will open.
Xcode automatically creates two files for us: MyScreenSaverView.h and MyScreenSaverView.m. Take a few minutes to poke around MyScreenSaverView.m and take note of the various methods that are provided for our use.
I have summarized some of these methods below:
-initWithFrame: isPreview: |
initializes the view with the given frame rect |
-setAnimationTimeInterval: | sets the animation rate in seconds |
-startAnimation: | invoked by the screen saver engine when animation should begin |
-stopAnimation: | invoked by the screen saver engine when animation should stop |
-drawRect: | draws the view |
-animateOneFrame | advances the animation by one frame at the rate set by the preceding method (this can be used for drawing instead of drawRect:) |
-hasConfigureSheet | returns true if the module has a configure sheet |
-configureSheet | returns the module's associated configure sheet |
We want to draw a bunch of shapes of random type, size, color, and location. This drawing magic must occur either in the drawRect: or animateOneFrame method. Since animateOneFrame is slightly easier to use and better suits our purpose, this is the method we will be using.
Open the "MyScreenSaverView.m" file to edit it. Scroll to the animateOneFrame method and add the following code:
First of all, we want to obtain the screen's boundaries for later use. To do this, we use the boundsmethod. This returns an NSRect from which we will obtain the size property.
Since we want our shapes to have random sizes, we can use the specially suppliedSSRandomFloatBetween() function for this. For those who are wondering, it is automatically seeded by the screen saver framework, so there is no need to manually deal with that.
Now we want to calculate a random origin point for our shape. To do this, we use the handySSRandomPointForSizeWithinRect() function, which will do all the work for us.
In simple terms, an NSBezierPath object lets you draw paths consisting of straight and curved line segments. When put together these can form shapes such as rectangles, ovals, arcs, and glyphs. We will be using the first three in our code.
We want to randomly decide whether to create our NSBezierPath object as a rectangle, oval, or arc. In order to provide for greater flexibibility should you choose to invent additional shape types at a later time, we will utilize a switch statement.
The arc case is a bit more complicated, so we will go through it step-by-step. An arc consists of a center, a radius, a starting angle, an ending angle, and a direction. First, we will select random starting and ending angles between 0 and 360 degrees. (Naturally, as you can see in the code below, it wouldn't make sense for the ending angle to start before the starting angle. Hence, it will not necessarily fall between 0 and 360 degrees. It is actually chosen to be somewhere between the starting angle value and the starting angle value plus 360.)
Similarly, we now choose a random radius. Since we already did a calculation earlier to determine a random rectangle size, we will simply use either the width or the height of that size, whichever is the smallest. In addition, we also calculate a center point using previously generated origin and size values.
Finally, we are ready to construct our path. Unlike the above rectangle and oval cases, here we must first create an empty bezier path and then append the arc path to it.