BitmapDataを操作およびアニメーション化して、以下のリンクにあるような渦巻き効果を作成したいと思います。
http://www.flash-filter.net/swirl-effect.phtml
どのようなテクニックを適用できますか?
ところで:はい、私は効果が醜いことを知っています。
BitmapDataを操作およびアニメーション化して、以下のリンクにあるような渦巻き効果を作成したいと思います。
http://www.flash-filter.net/swirl-effect.phtml
どのようなテクニックを適用できますか?
ところで:はい、私は効果が醜いことを知っています。
スワール効果がどのように達成されるか、つまりアルゴリズムを探している場合。これは、画像がどのように変換されるかを段階的に説明したものです。画像のツイストとスワールのアルゴリズム
このためのピクセルベンダーフィルターがあります。このリンクをチェックしてください:
http://www.adobe.com/cfusion/exchange/index.cfm?event=extensionDetail&extid=1536021
これがTweeningPixelBenderフィルターのチュートリアルです
http://plasticsturgeon.com/2011/03/pixel-transition-tweening-a-pixel-bender-filter-in-as3/
AS3ImageProcessingライブラリを確認することもできます
http://blog.joa-ebert.com/imageprocessing-library/
これはあなたに良い出発点を与えるはずです
Pixel Bender ist krieg!
私は以前の回答に同意しますが、この種の効果は、何年も前から存在しているビットマップフィルター、つまりDisplacementMapFilterのみを使用することで実行できることを指摘しておきます。ピクセルを円方向に移動するディスプレースメントマップを作成し、このマップを画像に複数回適用します。これにより、渦巻く変化が得られます。
これが私の簡単な実装です。
使い方はとても簡単です(クラスの後を見てください)。
package org.noregret.images
{
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.BlendMode;
import flash.display.DisplayObject;
import flash.display.GradientType;
import flash.display.InterpolationMethod;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.filters.DisplacementMapFilter;
import flash.filters.DisplacementMapFilterMode;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
/**
* @author Nox Noctis (http://noregret.org)
*/
public class Swirl
{
public var target : DisplayObject;
public var allowCache : Boolean = false;
public var levels : uint;
public var isDestroyed : Boolean;
protected var bitmapMargin : Point;
protected var filter : DisplacementMapFilter;
protected var radius : int;
protected var cache : Object;
protected var map : BitmapData;
protected var targetRect : Rectangle;
protected var mapOffset : Point;
protected var maxLevel : Number = 1;
public function Swirl(_target : DisplayObject, _filterLevels : uint = 10, _allowCache : Boolean = true)
{
target = _target;
allowCache = _allowCache;
levels = _filterLevels;
cache = {};
filter = new DisplacementMapFilter();
filter.componentX = BitmapDataChannel.RED;
filter.componentY = BitmapDataChannel.GREEN;
filter.scaleX = -20;
filter.scaleY = -20;
filter.mapPoint = new Point();
filter.mode = DisplacementMapFilterMode.IGNORE;
}
private function createDisplacementMap() : void
{
targetRect = target.getRect(target);
radius = Math.max(Math.max(targetRect.width, targetRect.height), 100) / 2;
radius = Math.sqrt(2) * radius;
mapOffset = new Point(radius - targetRect.width / 2, radius - targetRect.height / 2);
var mapSprite : Sprite = new Sprite();
var redLayer : Sprite = new Sprite();
var greenLayer : Sprite = new Sprite();
var grayLayer : Sprite = new Sprite();
mapSprite.addChild(redLayer);
mapSprite.addChild(greenLayer);
mapSprite.addChild(grayLayer);
var gradientMatrix : Matrix;
gradientMatrix = new Matrix();
gradientMatrix.createGradientBox(radius * 2, radius * 2, Math.PI / 2, -radius, -radius);
redLayer.graphics.lineStyle(0, 0, 0);
redLayer.graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0], [100, 100], [0, 255], gradientMatrix, SpreadMethod.PAD, InterpolationMethod.RGB);
redLayer.graphics.drawCircle(0, 0, radius);
redLayer.graphics.endFill();
greenLayer.graphics.lineStyle(0, 0, 0);
gradientMatrix.createGradientBox(radius * 2, radius * 2, 0, -radius, -radius);
greenLayer.graphics.beginGradientFill(GradientType.LINEAR, [0x00FF00, 0x00FF00], [0, 100], [10, 245], gradientMatrix, SpreadMethod.PAD, InterpolationMethod.RGB);
greenLayer.graphics.drawCircle(0, 0, radius);
greenLayer.graphics.endFill();
greenLayer.blendMode = BlendMode.ADD;
gradientMatrix = new Matrix();
gradientMatrix.createGradientBox(radius * 2, radius * 2, 0, -radius, -radius);
grayLayer.graphics.lineStyle(0, 0, 0);
grayLayer.graphics.beginGradientFill(GradientType.RADIAL, [0x808080, 0x808080], [0, 100], [0, 0xFF], gradientMatrix, SpreadMethod.PAD, InterpolationMethod.RGB);
grayLayer.graphics.drawCircle(0, 0, radius);
grayLayer.graphics.endFill();
var rect : Rectangle = mapSprite.getRect(mapSprite);
var matrix : Matrix = new Matrix();
matrix.translate(-rect.x, -rect.y);
if (map) {
map.dispose();
}
map = new BitmapData(rect.width, rect.height, false, 0xFF808080);
map.draw(mapSprite, matrix);
filter.mapBitmap = map;
}
public function swirlTo(ratio : Number) : BitmapData
{
if (isDestroyed) {
trace("Swirl: error! Tried to swirl on disposed item.");
return null;
}
if (ratio < 0) {
ratio = 0;
}
var level : uint = Math.round(levels * ratio);
var cacheName : String = getCacheName(level);
if (cache[cacheName]) {
return (cache[cacheName] as BitmapData).clone();
}
var rect : Rectangle = target.getRect(target);
if (!map || rect.width != targetRect.width || rect.height != targetRect.height) {
createDisplacementMap();
flushCache();
}
var point : Point = new Point(-targetRect.x, -targetRect.y);
bitmapMargin = new Point(point.x + mapOffset.x, point.y + mapOffset.y);
var bmp : BitmapData;
if (cache["l" + maxLevel]) {
bmp = cache["l" + maxLevel] as BitmapData;
} else {
bmp = new BitmapData(map.width, map.height, true, 0);
var matrix : Matrix = new Matrix();
matrix.translate(bitmapMargin.x, bitmapMargin.y);
bmp.draw(target, matrix, null, null, null, true);
}
if (level == 0) {
cache[cacheName] = bmp.clone();
return bmp;
}
var destPoint : Point = new Point();
for (var i : Number = maxLevel;i <= level; i++) {
bmp.applyFilter(bmp, bmp.rect, destPoint, filter);
if (allowCache) {
cache["l" + i] = bmp.clone();
}
}
maxLevel = Math.max(maxLevel, level);
return bmp;
}
private function getCacheName(level : uint) : String
{
return "l" + level;
}
public function flushCache() : void
{
for each (var bmp:BitmapData in cache) {
bmp.dispose();
}
cache = {};
}
public function destroy() : void
{
flushCache();
target = null;
map.dispose();
map = null;
isDestroyed = true;
}
}
}
使用例:
package
{
import flash.display.Sprite;
import flash.display.Loader;
import flash.events.Event;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.display.Bitmap;
import org.noregret.images.Swirl;
[SWF(width="800",height="600",backgroundColor="#FFFFFF",fps="30")]
public class TestSwirl extends Sprite
{
private const loader:Loader = new Loader();
private const swirlBitmap:Bitmap = new Bitmap();
private var swirl:Swirl;
private var time:Number = 0;
public function TestSwirl()
{
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
var request:URLRequest = new URLRequest("http://i.stack.imgur.com/Vtsvm.gif");
loader.load(request, new LoaderContext(true));
}
protected function onLoadComplete(event:Event):void
{
var original:Bitmap = loader.content as Bitmap;
addChild(original);
swirlBitmap.bitmapData = original.bitmapData.clone();
swirlBitmap.x = original.x + original.width + 10;
addChild(swirlBitmap);
swirl = new Swirl(original,80);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
protected function onEnterFrame(event:Event):void
{
var ratio:Number = Math.abs(Math.sin(time));
// ***
swirlBitmap.bitmapData = swirl.swirlTo(ratio);
// ***
time += .02;
}
}
}
PixelBenderを使用して独自のビットマップフィルターを作成することをお勧めします。