注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

神魔破杜梓的叨叨堂

Programming every day!

 
 
 

日志

 
 
 
 

Degrafa简介——在Flex中轻松绘图  

2008-05-06 11:31:11|  分类: My Tech |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
原文来自insideria

One of the most important aspects of delivering a rich user experience is what a user sees and interacts with on the screen. Graphics, whether static or dynamic, comprise the face of an application. Static graphics can definitely suffice for creating the necessary visual parts of an application, but to change them you must replace them with other static graphics. Dynamic graphics, created with programmatic drawing are very powerful because it can be manipulated at run-time, but it can involve more advanced knowledge of the Drawing API. Degrafa is a declarative graphics framework that aims to offer the best of both worlds.

In this article you will be introduced to some of the theory behind Degrafa, the basics of composition, advanced implementations, and how the framework may fit into your Flex or AIR projects. There are many uses for Degrafa, all of which can’t be covered in this article, but the hope is that this information may reveal something useful for you.

Degrafa is an open-source project created by developers in the RIA community. One of the primary goals is to allow designers and developers to forego the complexities of ActionScript to create dynamic graphics in MXML markup. With Degrafa you can define fills, strokes, shapes, complex paths, and more in the same way you would define a Flex component in MXML. Degrafa can be used to create skins, data visualizations, maps, or meet any other graphics need.

Some of the features of Degrafa include:

? A library of pre-composed shapes for you to use as well as the ability to create your own.
? Use SVG path data to create complete reusable shapes.
? Flexible options for fills and strokes.
? Binding of properties for Fills, Strokes and Geometry.
? Advanced CSS support for layered backgrounds, complex border control and background image positioning based on CSS 3.
? Productive features like derivatives, composition reuse, shape libraries, repeaters, and other utilities that allow you to do more with less code.
? Light weight model-based architecture.
? Compatibility with Flex 2 and Flex 3.
? A "pay-as-you-go" implementation.
? Much, much more...


Terminology
In the following examples there will be terminology used that you may or may not be familiar with. Some terms revolve around graphics, Flex, or the tags used in Degrafa. Before you get started, here's some definitions of some of those terms you'll see used in the remainder of this article:

geometry - A general term referring to any shape, path or graphic.

graphics context - A drawing destination where vector drawing commands can occur and stores information on how commands get rendered like line styles or fill styles. Any objects derived from Shape, Sprite or Movie Clip have a graphics property. Anything visual is drawn to or stored within a graphics context.

graphicsTarget - A property available to Degrafa geometry, like Circle, RegularRectangle, Polygon, etc. It allows you to specify the target(s) as a destination for Degrafa to render to. Acceptable targets must have a graphics context.

Surface - A tag in Degrafa provided as a base UIComponent for composing Degrafa elements.

GeometryGroup - A tag is used within the Surface tag and allows you to group Degrafa objects together. GeometryGroup is based on Sprite, so you can take advantage of the properties and events supported by Sprite.

GeometryComposition - A Degrafa tag that works similarly to GeometryGroup, but it allows you to compose or group elements at any level within your MXML file, including the root. You can optionally render those graphics to any object containing a graphics property using the graphicsTarget property.

Fill - A fill is a graphics term for the treatment of the inner area of an object. Fills are applied to the shapes you create. Degrafa has a variety of fills you can take advantage of like Solid, Linear Gradient, Radial Gradient, Bitmap, Blend and Complex fills.

Stroke - A stroke is a graphics term for the treatment of the edge of an object, usually defined with a thickness. Degrafa provides Solid, Linear Gradient and Radial Gradients strokes.


Getting Started with Degrafa
To use Degrafa in your projects you have two options; you can either download the latest version of Degrafa as a compiled SWC, or tap in directly to the Degrafa SVN. Both of these options are hosted openly on Google Code. For the purposes of this article you can use the compiled Degrafa SWC by following these steps:


1. Go to Google Code where the Degrafa code is hosted and download the latest version of the Degrafa SWC for the version of Flex you’re running. There is a version for Flex 2 and Flex 3. After you’ve downloaded the Degrafa SWC, open up Flex Builder and create a new project called DegrafaExample.

2. Once you’ve created your new Flex project, you need to drop the Degrafa SWC you just downloaded into the libs folder.

3. For the sake of keeping things clean in your MXML you can add a Degrafa XML namespace in the root MXML tag where you’ll be using Degrafa. For example, adding the Degrafa namespace in the Application tag of DegrafaExample.mxml could look like this:


<?xml version="1.0" encoding="utf-8"?> 
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:Degrafa="http://www.degrafa.com/2007"
layout="absolute">
</mx:Application>

The Basics of Composition By following those steps you can now access any of the Degrafa MXML tags for creating your graphics. Before you do though, there are a few fundamentals you’ll want to keep in mind when composing graphics. The following steps expose some of these fundamentals and walks through the basics of creating graphics with Degrafa resulting in a final composition of a single white Circle shown in Figure 1 and viewable here.

deg1.png
Figure 1 - Basic Circle

1. Graphic objects defined with Degrafa are drawn by a series of commands that require an object to be rendered upon. To define this you can either use a Degrafa GeometryGroup tag within a Surface tag, like this:

<Degrafa:Surface>     
<Degrafa:GeometryGroup>
<!-- Add Degrafa Shapes Here -->
</Degrafa:GeometryGroup>
</Degrafa:Surface>
The Degrafa Surface tag is a UIComponent, which means you can set properties like verticalCenter, horizontalCenter, etc. and the GeometryGroup tag is a Sprite, which has fewer properties than UIComponent.

2. The other option you have for specifying an area to draw Degrafa graphics to is to use the graphicsTarget property with a GeometryComposition or other geometry tag like Circle, RegularRectangle, etc. This will allow you to define graphic objects outside of the component and target any graphics context, i.e., any component that accepts graphics, like a Canvas, Button, Image, etc. This will be the method used in this basic example.

3. Add a Canvas in the application MXML and give it an id of myCanvas. Also, add a GeometryComposition and specify myCanvas in the graphicsTarget property like this:

<Degrafa:GeometryComposition     
graphicsTarget="{[ myCanvas ]}">
<!-- Add Degrafa Shapes Here -->
</Degrafa:GeometryComposition>
<mx:Canvas
id="myCanvas"/>
4. Once you’ve specified the graphics context you want to draw to you can start drawing Degrafa geometry. There are a number of pre-created Degrafa geometry objects that you can use to create your compositions, like Circle, RegularRectangle, Path, LineRepeater, and more. These objects can be drawn within a GeometryGroup, GeometryComposition, or by themselves using the graphicsTarget property. For this example, add a Circle within the GeometryComposition:

<Degrafa:GeometryComposition     
graphicsTarget="{[ myCanvas ]}">
<Degrafa:Circle
radius="100"
centerX="120"
centerY="120"/>
</Degrafa:GeometryComposition>
<mx:Canvas
id="myCanvas"/>
5. That last bit of MXML draws a Circle, but you can’t see it because it needs to have a fill or stroke applied to it. Degrafa comes with a number of fill and stroke capabilities that are sure to meet the majority of your needs. There are Solid, Linear Gradient, Radial Gradient, Blend, and Complex Fills. Stroke types include Solid, Linear Gradient, and Radial Gradient options. To get the Circle in this example to show up you can apply a SolidFill within the Circle like this:

<Degrafa:GeometryComposition     
graphicsTarget="{[ myCanvas ]}">
<Degrafa:Circle
radius="100"
centerX="120"
centerY="120" >
<Degrafa:fill>
<Degrafa:SolidFill
color="#FFF"/>
</Degrafa:fill>
</Degrafa:Circle>
</Degrafa:GeometryComposition>
<mx:Canvas
id="myCanvas"/>
Note: With the binding features of Degrafa you can also specify Fills and Strokes outside of geometry and assign the fill or stroke by referencing its id. This is a great way to repurpose fills and strokes across geometry objects. The following MXML snippet shows the same fill used above, but pulled outside of the Circle tag and assigned using the fill’s id of myFill:

<Degrafa:fills>     
<Degrafa:SolidFill
id="myFill"
color="#FFF"/>
</Degrafa:fill>

<Degrafa:Circle
radius="100"
centerX="120"
centerY="120"
fill="{myFill}"/>
View the final product or view the source.

Thoughts on Binding
One of the features I use the most in Degrafa is binding. Binding means creating a relationship between two properties such that when one updates the other is dynamically updated. This can be a very powerful feature when you think about binding properties like width, height, radius, fill, stroke, etc. between geometry objects to create some very dynamic relationships for a variety of purposes.

A simple example would be binding the angle of a LinearGradientFill to a HorizontalSlider so that the angle of the gradient would change dynamically based on the updated value of the slider (don’t forget to set live dragging on the slider). A more complex example would be a list of items whose backgrounds change based on dynamic data.

When you start to think of all the data you could use to influence graphics drawn with Degrafa it seems the possibilities are endless; interfaces that change based on cursor coordinates, buttons that change at different stages in a process, icons that change based on time of day, and charts that change shape based on new data. All it takes is a little experimentation with your own data sets, various public APIs, and user input. With binding in Degrafa you’ll start to see opportunities to create dynamic graphics in Flex.

A More Advanced Implementation

Now that we’ve covered some of the capabilities of Degrafa and the basics of composing graphics, let’s take a look at more involved example. The following steps will walk through creating a Flex Clock (Figure 2) to illustrate some of the features of Degrafa mentioned throughout this article and create a more advanced graphics composition. You can see the final product here.

deg2.png
Figure 1 - Flex Clock

1. To get started, create a new Flex application within your DegrafaExample folder and name it FlexClock.mxml. For convenience, add the same XML namespace mentioned in the previous example to your Application tag:

xmlns:Degrafa="http://www.degrafa.com/2007"

2. For this example, you’ll be composing the different parts of the Flex Clock as GeometryGroups to take advantage of some of the properties of Sprite, like rotation for the clock hands.

The first thing you need to do is set up the Surface tag so you can start adding the parts of the clock as GeometryGroups. Set the x and y of the Surface to 100 to position the clock within your application.

3. Add a GeometryGroup tag within the Surface tag and give it an id of clockFace. Within this GeometryGroup you’ll create the face of the clock, which is made up of the dark gradient background and letters “Fx”.

To create the dark grey face of the clock you can use a RegularRectangle object inside the clockFace GeometryGroup. Set the height and width of the RegularRectangle to 360. You also need to create that dark grey radial gradient fill for the RegularRectangle, but at this point the clockFace MXML should look like this:

<Degrafa:GeometryGroup     
id="clockFace">
<Degrafa:RegularRectangle
width="300"
height="300"/>
</Degrafa:GeometryGroup>

4. Outside the clockFace GeometryGroup, create a new fills tag. Within that fills tag, add a RadialGradientFill tag and set the cx property to 40, cy to 20, radius to 440 and give it an id of greyRadFill. The last thing you need to do to finish this fill is assign gradient stops within the fill.

Gradient stops are the attributes that make up a gradient and have their own set of properties, including color, alpha, and ratio. In Degrafa, you use a GradientStop tag to create a gradient stop within a radial or linear gradient fill. You can set as many gradient stops as you need to get the desired effect you’re looking for. For the purposes of this example, just create two gradient stops. Give the first gradient stop a color of #444 and the second a color of #000.

Note: You may have noticed that the colors for the gradient stops were defined using three digits rather than the six that Flex normally requires. This is similar to what is doable in HTML and another feature of Degrafa. In fact, you have several options for specifying colors within the color property. You can specify a color with a HEX value (#666), RGB value (60,60,60), color key (grey), or CMYK (0,0,0,60).

5. Now that you’ve created the dark grey fill, it must be applied to the RegularRectangle you created earlier. As mentioned previously in this article, you can apply a fill to an object using the fill property. The MXML for the RegularRectangle and RadialGradientFill should look like this:

<Degrafa:fills>     
<Degrafa:RadialGradientFill
id="greyRadFill"
cx="40"
cy="20"
radius="340">
<Degrafa:GradientStop
color="#444"/>
<Degrafa:GradientStop
color="#000"/>
</Degrafa:RadialGradientFill>
</Degrafa:fills>
<Degrafa:GeometryGroup
id="clockFace">
<Degrafa:RegularRectangle
width="300"
height="300"
fill="{ greyRadFill }"/>
</Degrafa:GeometryGroup>
6. If you run your application you should see the RegularRectangle you created filled with a dark grey radial gradient. There’s the base for the clock face.

Now you can create the remainder of the fills and strokes up front for the other elements of the clock and apply them as you go. You need to create a solid white fill for the “Fx” letters, a 10 pixel solid red stroke for the hour and minute hands, and a 2 pixel light grey stroke for the second hand. The fills tag has already been specified, but you need to add a strokes tag as well. Adding these new fills and strokes to the greyGradFill you already created should look like this in your MXML:

<Degrafa:fills>     
<Degrafa:RadialGradientFill
id="greyRadFill"
cx="40"
cy="20"
radius="340">
<Degrafa:GradientStop
color="#444"/>
<Degrafa:GradientStop
color="#000"/>
</Degrafa:RadialGradientFill>
<Degrafa:SolidFill
id="whiteFill"
color="#FFF"/>
</Degrafa:fills>
<Degrafa:strokes>
<Degrafa:SolidStroke
id="redStroke"
color="#C50"
weight="10"
caps="none"/>
<Degrafa:SolidStroke
id="greyStroke"
color="#666"
weight="2"
caps="none"/>
</Degrafa:strokes>

Note: You could expose Fill and Stroke properties to a designer to allow for customization without having them get involved with code.

7. With all the fills and strokes you’ll need for this example created, let’s add the remaining parts of the clock. You already have the dark grey background created, so now you need to finish the clock face and add the “Fx” letters. For these letters you will use a Polygon tag within the clockFace GeometryGroup.

For the “F” create a Polygon tag within the clockFace and assign whiteFill to the fill property. A Polygon takes shape by specifying a series of points, so rather than completely ending the Polygon tag, close it and set a points tag within. To specify the individual points, use a GraphicPoint tag for each point and specify the x and y values for each point. Instead of making you figure out the points to define the “F” I’ve defined them in the MXML block below along with the MXML for the “x”:

 
<!-- The White "F" Polygon -->
<Degrafa:Polygon
x="74"
y="90"
fill="{ whiteFill }">
<Degrafa:points>
<Degrafa:GraphicPoint
x="1.716"
y=".868"/>
<Degrafa:GraphicPoint
x="91.638"
y=".868"/>
<Degrafa:GraphicPoint
x="92.329"
y="21.965"/>
<Degrafa:GraphicPoint
x="30.768"
y="21.965"/>
<Degrafa:GraphicPoint
x="30.768"
y="71.768"/>
<Degrafa:GraphicPoint
x="85.758"
y="71.768"/>
<Degrafa:GraphicPoint
x="85.758"
y="95.632"/>
<Degrafa:GraphicPoint
x="30.768"
y="95.632"/>
<Degrafa:GraphicPoint
x="30.768"
y="164.11"/>
<Degrafa:GraphicPoint
x="1.37"
y="164.11"/>
</Degrafa:points>
</Degrafa:Polygon>
<!-- The White "x" Polygon -->
<Degrafa:Polygon
x="178"
y="140"
fill="{ whiteFill }">
<Degrafa:points>
<Degrafa:GraphicPoint
x="1.107"
y=".147"/>
<Degrafa:GraphicPoint
x="32.926"
y=".147"/>
<Degrafa:GraphicPoint
x="54.022"
y="39.574"/>
<Degrafa:GraphicPoint
x="76.503"
y=".147"/>
<Degrafa:GraphicPoint
x="105.209"
y=".147"/>
<Degrafa:GraphicPoint
x="72.354"
y="54.446"/>
<Degrafa:GraphicPoint
x="108.322"
y="113.932"/>
<Degrafa:GraphicPoint
x="73.736"
y="113.932"/>
<Degrafa:GraphicPoint
x="52.256"
y="73.43"/>
<Degrafa:GraphicPoint
x="32.505"
y="113.241"/>
<Degrafa:GraphicPoint
x=".07"
y="113.241"/>
<Degrafa:GraphicPoint
x="34.31"
y="58.596"/>
</Degrafa:points>
</Degrafa:Polygon>

Note: So, how did I get those points? I actually traced the “Fx” in Adobe Illustrator, saved that as an SVG, opened that SVG in TextEdit, and within the definition of the SVG there is a tag that had all the points I’m looking for. I just separated those points into the GraphicPoint tags for the Degrafa Polygon.

Note: For more information and clarification on how you can use SVG data in Degrafa, you can view this screencast.

8. The only objects you have left to create are the clock hands for the hours, minutes and seconds. Each of these hands will be a HorizontalLine within their own GeometryGroup, so they can be rotated. Start with the second hand and apply the greyStroke:

<!-- The Second Hand --> 
<Degrafa:GeometryGroup
id="secondHand"
x="180"
y="180">
<Degrafa:HorizontalLine
x="0"
x1="160"
y="0"
stroke="{ greyStroke }"/>
</Degrafa:GeometryGroup>

9. Below the second hand, create the minute and hour hands the same way the second hand was created, but change the stroke to redStroke as well as the y1 values to make the hands shorter heights:

<!-- The Minute Hand --> 
<Degrafa:GeometryGroup
id="minuteHand"
x="180"
y="180">
<Degrafa:HorizontalLine
x="0"
x1="150"
y="0"
stroke="{ redStroke }"/>
</Degrafa:GeometryGroup>
<!-- The Hour Hand -->
<Degrafa:GeometryGroup
id="hourHand"
x="180"
y="180">
<Degrafa:HorizontalLine
x="0"
x1="100"
y="0"
stroke="{ redStroke }"/>
</Degrafa:GeometryGroup>

10. If you now compile your application you should see the second, minute and hour hands in a horizontal orientation overlapping each other. You now have all the parts of your Flex Clock created, so now you can get it wired up and working.

To save time I’ve put together the necessary code to get the clock ticking. You can use the following Script block and place it right below the Application tag:

<mx:Script>     
<![CDATA[
private var clocktick:Timer= new Timer(1000);
public function initTime():void
{
setTime(new Date());
clocktick.addEventListener(TimerEvent.TIMER, initDraw);
clocktick.start();
}
private function initDraw(event:TimerEvent):void
{
setTime(new Date());
}
public function setTime(currtime:Date):void
{
var currseconds:uint = currtime.getSeconds();
var currminutes:uint = currtime.getMinutes();
var currhours:uint = currtime.getHours();
secondHand.rotation = 268 + (currseconds * 6);
minuteHand.rotation = 268 + (currminutes * 6);
hourHand.rotation = 268 + (currhours * 30) + (currminutes * 0.5);
}
]]>
</mx:Script>

11. With that added, the final thing you need to do to set the Flex Clock in motion is fire off the initTime() function on your Application’s creationComplete event:

creationComplete="initTime()"
Compile your app and check what time it is! You should see the time reflected by the rotation of the clock hands. The best thing is that the graphics are all done through MXML markup. You could easily go in and change the colors or type of strokes and fills, add some easing, bitmap filters. Leveraging the flexibility of working with Degrafa you could change the fill colors of the clock face based on time of day, or create an animation that shakes the clock like an alarm. There are a ton of possibilities and it’s easy!

View the final product or view the source.

Degrafa vs. ActionScript
As a developer you may be asking, why wouldn't I just do all my drawing in ActionScript rather than Degrafa MXML? Well, there's nothing that Degrafa does that you couldn't do in ActionScript. The amount of code needed to do something like a simple Circle in ActionScript is no more involved than using Degrafa MXML, however, in more complex scenarios you may find executing using ActionScript to be overwhelming.

Another reason is that the nature of the code is related to graphics and layout. You'll find it to be a more intuitive way to compose graphics through MXML markup rather than programmatically. With Degrafa, there is a more apparent visual structure to follow for laying out your geometry elements and their relationships via the nesting that occurs in MXML, while ActionScript is a lot more abstract and harder to follow, especially when using procedural methods to draw your objects.

There are a lot of things that are done for you in Degrafa so that you don't need to worry about advanced math or coordinates. It's really about being more productive and being able to leverage the power of programmatic drawing to create flexible and dynamic visuals without making your brain hurt.

Final Thoughts
These two examples just scratch the surface of what is possible with Degrafa. There are a number of things that couldn’t be covered in this article given the length, but I encourage you to check out some of the provided resources at the end of this article to learn about more of the features of Degrafa.

The features that Degrafa has like binding, advanced CSS, the ability to use SVG path data, utilities, focus on code reuse and more, enables you to quickly iterate on real applications at a pace that is more in line with client demands. As always, not every solution is the right one for everybody, but this framework was built by developers and designers to be one that they would use on a day to day basis to meet some of the most stringent needs. You can learn more about Degrafa at the following links:


Website and Blog: http://www.degrafa.com
Documentation: http://docs.degrafa.com
Samples: http://samples.degrafa.com
Code Source and Repository: http://code.degrafa.com
Discussion: http://group.degrafa.com
Community Showcase: http://showcase.degrafa.com
  评论这张
 
阅读(688)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017