Macっぽい球体を描画するAquaSphere.as
Macっぽい球体を描画するAS2用クラスを作ってみました。
AquaSphere.as
サンプルは、にゃあプロジェクト様のところで、素敵なのを作っていただいちゃいましたので、そちらをご覧ください。
上記の他に、以下のライブラリが必要ですので、それぞれのサイトからDLしてください。
(昨日あたりから、なぜかGuy Watsonさんのサイトflashguru.co.ukにアクセスできない模様です。サイトが復旧するまで一時的に、僕がDLしたasファイルをこちらにUPさせていただきます。)
AquaSphereの使い方はこんな感じです。
var target:MovieClip = this //描画先 var hue:Number = 230; //色相(0〜360) var radius:Number = 100; //球の半径 var x:Number = 10; //x座標 var y:Number = 10; //y座標 var hasDropShadow:Boolean = true; //ドロップシャドウの有無 var sphere:AquaSphere = new AquaSphere(target, hue, radius, x, y, hasDropShadow);
パラメータの「色相(hue)って何じゃい?」という方は、Wikiのこのページ に詳しい解説がありますが、「そんなの読んでられねーだろ、ゴルァ」というやんちゃな方は、「色相とは色味(いろみ)のことで、0〜360度で表現されるもの」と考えてもらえばよろしいかと思います。ちなみにFlashのカラーウィンドウもデフォルトはRGBでの設定となっていますが、オプション(右上の三角)でHSBでの設定へ変更することができまするんですよぉ。
インスタンス化したAquaSphereオブジェクトのカラーを変更するには、colorize(hue)というメソッドをご利用ください。
sphere.colorize(110)
ところで、このクラスには、どうもイケてない点があります。それは、例えばこのオブジェクトの透明度を変えたいとか、マウスイベントを設定したいという場合、ムービークリップと同様に
sphere._alpha = 80; sphere.onRollOver = function() { trace("onRollOver"); }
みたいなスクリプトが書けるようにしたいのです。ですが、「それじゃあ、MovieClipクラスを継承させればokじゃん」と、そのようにしてみたところ、どうも上手くいきませんでした。この件については、後日エントリーするつもりですが、現在はMovieClipクラスを継承しないで、上記のようなケースの対応は、
var wrapper:MovieClip = sphere.getWrapper(); wrapper._alpha = 80; wrapper.onRollOver = function():Void { trace ("onRollOVer"); }
のように、AquaSphereクラス内で生成している全ての描画オブジェクトを内包しているMovieClipへの参照を返すgetWrapper()というメソッドを利用し、このオブジェクトのプロパティやメソッドを操作する、という苦肉の策を採っています。
んー、我ながらイケてない…。
最後に一応、スクリプトを晒しておきます。「ここ変だよ」とかいう部分がありましたら、本人が凹まない程度にご指摘いただけましたら幸いでございます。
import ColorConversion; import flash.filters.BlurFilter; import flash.filters.DropShadowFilter; import flash.filters.GlowFilter; import flash.geom.ColorTransform; import flash.geom.Matrix; import flash.geom.Transform; import org.casaframework.math.geom.Ellipse; import org.casaframework.util.DrawUtil; class AquaSphere { private static var DROP_SHADOW_DEPTH:Number = 0; private static var BASE_CIRCLE_DEPTH:Number = 1; private static var HIGHLIGHT_DEPTH:Number = 2; private static var INNER_GLOW_DEPTH:Number = 3; private static var BASE_SATURATION:Number = 75; private static var BASE_BRIGHTNESS:Number = 78; private var holderClip:MovieClip; private var baseClip:MovieClip; private var innerGlowClip:MovieClip; private var dropShadowClip:MovieClip; private var baseEllipse:Ellipse; private var highlightClip:MovieClip; private var radius:Number; private var baseHue:Number; private var hasDropShadow:Boolean = false; /* * AquaSphereコンストラクタ * @param target:MovieClip AquaSphereオブジェクトの生成先 * @param hue:Number 球体のベースカラーの色相(0〜360) * @param r:Number 半径 * @param x:x座標 * @param y:y座標 * @param bDropShadow:Boolean */ public function AquaSphere(target:MovieClip, hue:Number, r:Number, x:Number, y:Number, bDropShadow:Boolean) { holderClip = target.createEmptyMovieClip("holderClip", target.getNextHighestDepth()); radius = r; hasDropShadow = bDropShadow; holderClip._x = x; holderClip._y = y; buildClips(); colorize(hue); } /* * 球のカラーを変更 * @param hue:色相(0〜360) */ public function colorize(hue:Number):Void { setBaseHue(hue); colorBaseClip(); colorInnerGlowClip(); } /* * ドロップシャドウの表示/非表示の切替え */ public function toggleDropShadow():Void { if (hasDropShadow) { removeMovieClip(dropShadowClip); } else { buildDropShadowClip(); } hasDropShadow = !hasDropShadow; } /* * ラッパーMovieClipを参照 */ public function getWrapper():MovieClip { return holderClip; } /* * 色相の設定 */ private function setBaseHue(hue:Number):Void { hue %= 360; if (hue < 0) hue += 360; baseHue = Math.floor(hue); } /* * 必要なMovieClipを生成 */ private function buildClips():Void { buildBaseClip(); buildHighlightClip(); buildInnerGlowClip(); if (hasDropShadow != false) buildDropShadowClip(); } /* * ベースとなるMovieClipを生成 */ private function buildBaseClip():Void { var diameter:Number = radius * 2; baseClip = holderClip.createEmptyMovieClip("baseClip", BASE_CIRCLE_DEPTH); baseEllipse = new Ellipse(0, 0, diameter, diameter); } /* * 球体上部の光の反射を表現するMovieClipを生成 */ private function buildHighlightClip():Void { highlightClip = holderClip.createEmptyMovieClip("innerGlow", HIGHLIGHT_DEPTH); var diameter:Number = radius * 2 * 0.9; var x:Number = -(diameter / 2); var y:Number = 0; var highlightEllipse:Ellipse = new Ellipse(x, y, diameter, diameter); highlightClip._x = radius; highlightClip._y = radius * .05; var fillType:String = "linear" var colors:Array = [0xffffff, 0xffffff]; var alphas:Array = [100, 0]; var ratios:Array = [0, 255 * .75]; var matrix:Matrix = new Matrix(); var offsetX:Number = -(diameter / 2); var offsetY:Number = 0; matrix.createGradientBox(diameter, diameter, 90 * Math.PI / 180, offsetX, offsetY); highlightClip.beginGradientFill(fillType, colors, alphas, ratios, matrix); DrawUtil.drawEllipse(highlightClip, highlightEllipse); highlightClip.endFill(); highlightClip._xscale = 80; highlightClip._yscale = 75; highlightClip._alpha = 70; } /* * 球体の内側の光彩を表現するMovieClipを生成 */ private function buildInnerGlowClip():Void { innerGlowClip = highlightClip.duplicateMovieClip("innerGlow", INNER_GLOW_DEPTH); innerGlowClip._rotation += 180; innerGlowClip._y = (radius * 2) - (radius * .1); } /* * ドロップシャドウ用のMovieClipを生成し、DropShadowエフェクトを適用 */ private function buildDropShadowClip():Void { dropShadowClip = holderClip.createEmptyMovieClip("dropShadowClip", DROP_SHADOW_DEPTH); var diameterX:Number = radius * 1.5; var diameterY:Number = radius * .45; var ellipse:Ellipse = new Ellipse(0, 0, diameterX, diameterY); dropShadowClip.beginFill(0x000000); DrawUtil.drawEllipse(dropShadowClip, ellipse); dropShadowClip.endFill(); dropShadowClip._x = (radius * 2 - diameterX) / 2; dropShadowClip._y = (radius * 2 - diameterY) / 2; var distance:Number = radius; var angleInDegrees:Number = 90; var color:Number = 0x000000; var alpha:Number = .5; var blurX:Number = diameterX / 10; var blurY:Number = blurX; var strength:Number = 1; var quality:Number = 3; var inner:Boolean = false; var knockout:Boolean = false; var hideObject:Boolean = true; var dropShadow:DropShadowFilter = new DropShadowFilter(distance, angleInDegrees, color, alpha, blurX, blurY, strength, quality, inner, knockout, hideObject); var filterList:Array = [dropShadow]; dropShadowClip.filters = filterList; } /* * ベースのカラー設定 */ private function colorBaseClip():Void { var baseRgbHex:Number = ColorConversion.hsbtohex24(baseHue, BASE_SATURATION, BASE_BRIGHTNESS); baseClip.beginFill(baseRgbHex); DrawUtil.drawEllipse(baseClip, baseEllipse); baseClip.endFill(); var hue:Number = (baseHue + 6) % 360; var saturation:Number = BASE_SATURATION - 25; var brightness:Number = BASE_BRIGHTNESS - 25; var shadowRGB:Object = ColorConversion.hsbtorgb(hue, saturation, brightness); var shadowRgbHex:Number = ColorConversion.rgbtohex24(shadowRGB.red, shadowRGB.green, shadowRGB.blue); var alpha:Number = 1; var blurX:Number = radius / 2; var blurY:Number = blurX; var strength:Number = 2; var quality:Number = 3; var inner:Boolean = true; var knockout:Boolean = false; var innderShadow:GlowFilter = new GlowFilter(shadowRgbHex, alpha, blurX, blurY, strength, quality, inner, knockout); var filterList:Array = [innderShadow]; baseClip.filters = filterList; } /* * 内側の光彩のカラー設定 */ private function colorInnerGlowClip():Void { var colorTrans:ColorTransform = new ColorTransform(); var trans:Transform = new Transform(innerGlowClip); var hue:Number = (baseHue - 30) % 360; if (hue < 0) hue += 360; var saturation:Number = 100; var brightness:Number = 100; var glowRbg:Object = ColorConversion.hsbtorgb(hue, saturation, brightness) var glowRgbHex:Number = ColorConversion.rgbtohex24(glowRbg.red, glowRbg.green, glowRbg.blue); colorTrans.rgb = glowRgbHex; trans.colorTransform = colorTrans; var blurLen:Number = radius * .15; var blurQuality:Number = 3; var blur:BlurFilter = new BlurFilter(blurLen, blurLen, blurQuality); var filterList:Array = [blur]; innerGlowClip.filters = filterList; innerGlowClip.blendMode = "multiple"; } }