`
yangzhiyong77
  • 浏览: 965363 次
文章分类
社区版块
存档分类
最新评论

flex4 自定义控件系列 基于GraphicElement的动态背景

 
阅读更多

效果图:

点击按钮可重新生成新的背景

单击单个元素可改变单个元素的外观

效果图

单个背景图案

package components

{

import flash.display.DisplayObject;

import flash.display.Graphics;

import flash.display.GraphicsPathCommand;

import flash.display.GraphicsPathWinding;

import flash.display.Sprite;

import flash.events.Event;

import flash.events.MouseEvent;

import flash.geom.Point;

import flash.utils.getQualifiedClassName;

import mx.utils.ColorUtil;

import spark.core.IGraphicElement;

import spark.primitives.supportClasses.GraphicElement;

public class FlowerGraphicElement extends GraphicElement

{

/**

* 绘图commands

* */

private var _commands:Vector.<int> = new Vector.<int>;

/**

* 绘图datas

* */

private var _datas:Vector.<Number> = new Vector.<Number>;

/**

* commands索引

* */

private var _ci:int;

/**

* datas索引

* */

private var _di:int;

/**

* 分度数

* */

private var _numOfLeaves:int = 5;

/**

* 图案的旋转度数

* */

private var _flowerRotation:Number = 0;

/**

* 线高的比例 子分级与分级

* */

private var _innerToOuterRadiusRatio:Number = 0.382;

/**

* 笔画重度 考虑到使用StrokedElement

* */

private var _strokeWeight:int = 1;

/**

* 图案颜色 考虑到使用FilledElement

* */

private var _color:uint = 0x808080;

/**

* 当前填充颜色 考虑到使用FilledElement

* */

private var _fillColor:uint = 0x808080;

/**

* 为演示目的 强制对象分享

* */

private var _shouldShareDisplayObject:Boolean;

public function FlowerGraphicElement()

{

super();

}

/**

* 设置分度数

* */

public function set numberOfLeaves(value:int):void

{

if ( value != _numOfLeaves )

{

_numOfLeaves = Math.max(3, value);

invalidateDisplayList();

}

}

public function get numberOfLeaves():int{ return _numOfLeaves; }

/**

* Ratio inner/outer radius 线高的比例

*/

public function get innerToOuterRadiusRatio():Number{return _innerToOuterRadiusRatio;}

public function set innerToOuterRadiusRatio(value:Number):void

{

if (_innerToOuterRadiusRatio != value)

{

_innerToOuterRadiusRatio = Math.max(0.1, Math.min(1, value));

invalidateDisplayList();

}

}

/**

* 笔画重度

*/

public function get strokeWeight():int{ return _strokeWeight;}

public function set strokeWeight(value:int):void{ _strokeWeight = value; }

/**

* 图案颜色

*/

public function get color():uint{return _color; }

public function set color(value:uint):void

{

if(_color != value)

{

_color = _fillColor = value;

invalidateDisplayList();

}

}

/**

* 图案的旋转弧度

* 首先是设置设置这个角度

* 用这个,当旋转图案时旋转属性不必受到影响

* 并且必须绘出

*/

public function set flowerRotation(value:Number):void

{

if ( value != _flowerRotation )

{

_flowerRotation = value;

invalidateDisplayList();

}

}

public function get flowerRotation():Number{ return _flowerRotation; }

/**

* 设置是否强制对象分析

* */

public function set shouldShareDisplayObject(value:Boolean):void

{

_shouldShareDisplayObject = value;

//通知主机此元素已更改且需要更新其图层的实用程序方法

invalidateDisplayObjectSharing();

}

public function get shouldShareDisplayObject():Boolean{ return _shouldShareDisplayObject; }

/**

* 确定此元素是否可以将它自己绘制到该序列的sharedDisplayObject

* */

public override function setSharedDisplayObject(sharedDisplayObject:DisplayObject):Boolean

{

return super.setSharedDisplayObject(sharedDisplayObject);

}

/**

* 如果元素需要一个独占的displayObject则为true

* */

protected override function get needsDisplayObject():Boolean

{

return !_shouldShareDisplayObject;

}

/**

* Flex调用 为graphic element 创建显示对象

* */

public override function createDisplayObject():DisplayObject

{

//父类将会创建InvalidatingSprite(继承自Sprite)

var displaySpirteObject:DisplayObject = super.createDisplayObject();

//根据需要个性化

setupDisplayObject(displaySpirteObject);

return displaySpirteObject;

}

private function setupDisplayObject(value:DisplayObject):void

{

if ( value is Sprite )

{

var sprite:Sprite = Sprite(value);

sprite.mouseEnabled = true;

sprite.mouseChildren = true;

sprite.addEventListener(MouseEvent.CLICK, clickHandler);

sprite.addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);

sprite.addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);

sprite.addEventListener(Event.REMOVED_FROM_STAGE, removeHandler);

}

else

{

trace("不能设置显示对象:"+getQualifiedClassName(this));

}

}

/**

* 点击事件

* */

private function clickHandler(e:MouseEvent):void

{

//随机图案

innerToOuterRadiusRatio = Math.random();

numberOfLeaves = Math.random() * 10;

width = height = Math.random() * 150 + 50;

invalidateDisplayList();

}

/**

* 鼠标触摸事件

* */

private function rollOverHandler(e:MouseEvent):void

{

//将颜色向亮度亮的方向调整

_fillColor = ColorUtil.adjustBrightness(_color, 90);

invalidateDisplayList();

}

/**

* 鼠标移除事件

* */

private function rollOutHandler(e:MouseEvent):void

{

_fillColor = _color;

invalidateDisplayList();

}

/**

* 从场景中移除事件处理函数

* */

private function removeHandler(e:Event):void

{

var target:DisplayObject = DisplayObject(e.currentTarget);

target.removeEventListener(MouseEvent.CLICK, clickHandler);

target.removeEventListener(MouseEvent.ROLL_OUT, rollOutHandler);

target.removeEventListener(MouseEvent.ROLL_OVER, rollOverHandler);

target.removeEventListener(Event.REMOVED_FROM_STAGE, removeHandler);

}

/**

* 是否可以与下一个IGraphicElement元素共享显示对象

* 覆盖强制取消共享显示对象

* */

public override function canShareWithNext(element:IGraphicElement):Boolean

{

return _shouldShareDisplayObject;

}

/**

* 是否可以与上一个IGraphicElement元素共享显示对象

* */

public override function canShareWithPrevious(element:IGraphicElement):Boolean

{

return _shouldShareDisplayObject;

}

/**

* 绘制元素和/或调整其内容的大小并定位该内容

* */

protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void

{

super.updateDisplayList(unscaledWidth, unscaledHeight);

draw(unscaledWidth, unscaledHeight);

}

private function draw(w:Number, h:Number):void

{

//得到显示对象的画图工具

var graphic:Graphics = ( displayObject as Sprite ).graphics;

w = isNaN(w) ? this.width : w;

h = ( isNaN(h) ? this.height : h ) - 1;

/*

* 设置 graphic element 的根笛卡尔坐标 关联到绘图displayObject

* 用来绘图的关联到绘图displayObject的笛卡尔坐标可能不是从(0,0)而是从(drawX,drawY)开始

* graphical element 的笛卡尔坐标必须纳入计数器

* 因此displayObject显示对象必须是共享的

*/

var gx:Number = drawX + w/2;

var gy:Number = drawY + h/2;

//重设索引

_ci = 0;

_di = 0;

//为简单起见,1.65逼近,outerRadius关联cp,不会在外部边界,测量不准确

var outerRadius:Number = Math.min(w, h) / 1.65;

var innerRadius:Number = _innerToOuterRadiusRatio * outerRadius;

var cp:Point = new Point;

var ap:Point = new Point;

var r:Number = _flowerRotation;

var rMax:Number = r + 2 * Math.PI;

var angleStep:Number = Math.PI / _numOfLeaves;

//设置开始点

ap = Point.polar(innerRadius, r);

ap.offset(gx, gy);

_commands[_ci++] = GraphicsPathCommand.MOVE_TO;

_datas[_di++] = ap.x;

_datas[_di++] = ap.y;

while ( r < rMax )

{

//外部控制点

r += angleStep;

cp = Point.polar(outerRadius, r);

cp.offset(gx, gy);

//内部锚点

r += angleStep;

ap = Point.polar(innerRadius, r);

ap.offset(gx, gy);

//设置画曲线

_commands[_ci++] = GraphicsPathCommand.CURVE_TO;

_datas[_di++] = cp.x;

_datas[_di++] = cp.y;

_datas[_di++] = ap.x;

_datas[_di++] = ap.y;

}

//end point = start point

ap = Point.polar(innerRadius, r);

ap.offset(gx, gy);

_commands[_ci++] = GraphicsPathCommand.LINE_TO;

_datas[_di++] = ap.x;

_datas[_di++] = ap.y;

//重用前清除不必要的数据

//激活缓存工作 如果没有数据改变时data和command是不会被执行的

if ( _ci != _commands.length )

{

_commands.splice(_ci, _commands.length - _ci);

_datas.splice(_di, _datas.length - _di);

}

//考虑用到 FilledElement

graphic.beginFill(_fillColor, 1);

//绘制路径

graphic.drawPath(_commands, _datas, GraphicsPathWinding.NON_ZERO);

}

}

}

应用

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

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

xmlns:s="library://ns.adobe.com/flex/spark"

xmlns:mx="library://ns.adobe.com/flex/mx"

minWidth="955"

minHeight="600"

creationComplete="application1_creationCompleteHandler(event)"

xmlns:ah="com.hulstkamp.spark.components.*"

viewSourceURL="srcview/index.html">

<fx:Script>

<![CDATA[

import components.FlowerGraphicElement;

import mx.events.FlexEvent;

import mx.utils.ColorUtil;

//-------------------------------------------------------------------------

// Demo hacks

//-------------------------------------------------------------------------

protected function application1_creationCompleteHandler(event:FlexEvent):void

{

buildField();

}

private function buildField():void

{

var colors:Array = [0x989508, 0xFFA800, 0xfd808e, 0xec656c, 0xbc0f3d, 0x19c6a2];

// addFlower(Math.random() * 75 + 50, 0, 0, colors[0], Math.random() * 10, Math.random());

// addFlower(Math.random() * 75 + 50, flowersGroup.width, 0, colors[0], Math.random() * 10, Math.random());

// addFlower(Math.random() * 75 + 50, flowersGroup.width, flowersGroup.height, colors[0], Math.random() * 10, Math.random());

// addFlower(Math.random() * 75 + 50, 0, flowersGroup.height, colors[0], Math.random() * 10, Math.random());

//occupy corners

addFlower(Math.random() * 75 + 50, 0, 0, colors[(i % colors.length)], Math.random() * 10, Math.random());

addFlower(Math.random() * 75 + 50, flowersGroup.width, 0, colors[(i % colors.length)], Math.random() * 10, Math.random());

addFlower(Math.random() * 75 + 50, flowersGroup.width, flowersGroup.height, colors[(i % colors.length)], Math.random() * 10, Math.random());

addFlower(Math.random() * 75 + 50, 0, flowersGroup.height, colors[(i % colors.length)], Math.random() * 10, Math.random());

//flower field

for (var i:int = 0; i < 37; i++)

{

addFlower(Math.random() * 100 + 100, Math.random() * flowersGroup.width, Math.random() * flowersGroup.height, colors[(i % colors.length)], Math.random() * 10, Math.random());

}

}

private function addFlower(size:Number, x:Number, y:Number, color:uint, numOfLeaves:int, ratio:Number):void

{

var ge:FlowerGraphicElement = new FlowerGraphicElement();

ge.shouldShareDisplayObject = false;

ge.width = ge.height = size;

ge.horizontalCenter = x - flowersGroup.width/2;

ge.verticalCenter = y - flowersGroup.height / 2;

ge.numberOfLeaves = numOfLeaves;

ge.innerToOuterRadiusRatio = ratio;

ge.color = ColorUtil.adjustBrightness(color, Math.random() * 64 - 32);

ge.blendMode = BlendMode.MULTIPLY;

flowersGroup.addElement(ge);

}

protected function button1_clickHandler(event:MouseEvent):void

{

flowersGroup.removeAllElements();

buildField();

}

]]>

</fx:Script>

<s:Group id="flowersGroup" width="600" height="600" horizontalCenter="0" verticalCenter="0" >

<s:mask>

<s:Group width="600" height="600">

<s:Rect width="100%" height="100%" radiusX="5" radiusY="5">

<s:fill>

<s:SolidColor color="0xff0000" />

</s:fill>

</s:Rect>

</s:Group>

</s:mask>

</s:Group>

<s:VGroup gap="7" horizontalCenter="0" verticalCenter="0" horizontalAlign="center">

<s:Label fontSize="14" color="0xffffff" text="基于GraphicElement的背景" />

<s:Label fontSize="11" color="0xffffff" text="点击一个元素改变其外观或按一下按钮" />

<s:Button label="重新生成" click="button1_clickHandler(event)" fontSize="11" chromeColor="0x80a000" />

<s:filters>

<s:DropShadowFilter distance="1" blurX="0" blurY="0" quality="0" />

</s:filters>

</s:VGroup>

</s:Application>

分享到:
评论
Global site tag (gtag.js) - Google Analytics