HandwrittenAnimation forked from: 手描きアニメ風?線文字 Ver.1
forked from 手描きアニメ風?線文字 (diff: 415)
秒数とfps指定してプレレンダリングしたものを再生できるSprite拡張クラス https://github.com/nowri/HandwrittenAnimation
♥0 |
Line 364 |
Modified 2012-05-24 14:48:39 |
MIT License
archived:2017-03-20 16:46:54
| (replaced)
Related images
ActionScript3 source code
/**
* Copyright n0wri ( http://wonderfl.net/user/n0wri )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/bNmX
*/
//秒数とfps指定してプレレンダリングしたものを再生できるSprite拡張クラス
// forked from lagash's 手描きアニメ風?線文字 Ver.1
package
{
import flash.events.MouseEvent;
import com.bit101.components.PushButton;
import jp.progression.commands.Func;
import jp.progression.commands.lists.SerialList;
import jp.progression.commands.net.LoadBitmapData;
import jp.progression.data.getResourceById;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.system.Security;
public class Main extends Sprite
{
private static const txt1:String = "http://assets.wonderfl.net/images/related_images/b/b4/b432/b432f6677ba28577859160bdbbb785a36bab6843";
private static const txt2:String = "http://assets.wonderfl.net/images/related_images/f/f1/f167/f167ab4399596b17b2d45d321b7f3b768449f26c";
private static const txt3:String = "http://test.nowri.in/wonderfl/handwrittenanimation/t3.png";
private var animeVec:Vector.<HandwrittenAnimation>=Vector.<HandwrittenAnimation>([]);
public function Main()
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event):void
{
Security.loadPolicyFile( "http://test.nowri.in/crossdomain.xml" );
stage.addChild(this);
var sh:Shape=new Shape();
var g:Graphics = sh.graphics;
stage.addChildAt(sh, 0);
g.beginFill(0x000000,1);
g.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
var lst:SerialList = new SerialList();
var initObj:Object = {context:new LoaderContext(true, ApplicationDomain.currentDomain)};
lst.addCommand
(
[
new LoadBitmapData(new URLRequest(txt1), initObj),
new LoadBitmapData(new URLRequest(txt2), initObj),
new LoadBitmapData(new URLRequest(txt3), initObj)
],
new Func(imgLoaded)
);
lst.execute();
new PushButton(stage,0,0,"start",start);
new PushButton(stage,0,30,"pause",pause);
}
private function start(e:MouseEvent):void
{
if(animeVec.length)
{
for (var i : int = 0; i < animeVec.length; i++) {
animeVec[i].play();
}
}
}
private function pause(e:MouseEvent):void
{
if(animeVec.length)
{
for (var i : int = 0; i < animeVec.length; i++) {
animeVec[i].pause();
}
}
}
private function imgLoaded():void
{
createAnime(txt2);
createAnime(txt1);
}
private function createAnime(url:String):void
{
var bmd:BitmapData = getResourceById(url).toBitmapData();
var vo:HandwrittenAnimationVO = new HandwrittenAnimationVO
(
);
var anime:HandwrittenAnimation = new HandwrittenAnimation(bmd, vo);
anime.addEventListener(HandwrittenAnimationEvent.CREATE_COMPLETE, createAnimeComplete);
}
private function createAnimeComplete(e:HandwrittenAnimationEvent):void
{
var anime:HandwrittenAnimation = e.target as HandwrittenAnimation;
anime.x = stage.stageWidth/2 - anime.width/2;
anime.y = stage.stageHeight/2 - anime.height/2;
addChild(anime);
anime.play();
animeVec.push(anime);
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.utils.Timer;
[Event(name="CREATE_COMPLETE", type="HandwrittenAnimationEvent")]
class HandwrittenAnimation extends Sprite
{
//---------------------------------------------------------------------------------------------------------------------------------------------
// Public Properties
//---------------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------------------
// Internal Properties
//---------------------------------------------------------------------------------------------------------------------------------------------
private var timer:Timer;
private var vo:HandwrittenAnimationVO;
private var src:BitmapData;
private var color:uint;
private var bmp:Bitmap;
private var bmdVec:Vector.<BitmapData>;
private var cloneBmd:BitmapData;
private var current:int=0;
//---------------------------------------------------------------------------------------------------------------------------------------------
// Public Methods
//---------------------------------------------------------------------------------------------------------------------------------------------
public function HandwrittenAnimation(bmd:BitmapData, vo:HandwrittenAnimationVO)
{
this.vo = vo;
this.src = bmd;
init();
}
public function play():void
{
pause();
timer = new Timer(int(1000/vo.fps),0);
timer.addEventListener(TimerEvent.TIMER, update);
timer.start();
}
public function pause():void
{
if(timer)
{
timer.stop();
if(timer.hasEventListener(TimerEvent.TIMER))timer.removeEventListener(TimerEvent.TIMER, update);
}
}
// getter setter
//---------------------------------------------------------------------------------------------------------------------------------------------
// Internal Methods
//---------------------------------------------------------------------------------------------------------------------------------------------
private function init():void
{
if(!vo.isSync)
{
var t:Timer = new Timer(1,1);
t.addEventListener(TimerEvent.TIMER, _init);
t.start();
return;
}
_init();
}
private function _init(e:TimerEvent=null):void
{
var vec:Vector.<uint>=src.getVector(new Rectangle(0,0,src.width,src.height));
var w:int=src.width;
var h:int=src.height;
var pos:uint=0;
var add:int = int(10*(1-vo.lineDensitydensity));
var srcPos:Vector.<Vector.<uint>>;
var minX:int, minY:int, maxX:int, maxY:int = int.MIN_VALUE;
srcPos=Vector.<Vector.<uint>>([]);
for(var y:int=0; y<h; y++)
{
for(var x:int=0; x<w; x+=add)
{
pos=w*y+x;
if(vec[pos])
{
if(minX != int.MIN_VALUE)
{
minX = (x>=minX)? minX:x;
}
else
{
minX = x;
}
if(minY != int.MIN_VALUE)
{
minY = (y>=minY)? minY:y;
}
else
{
minY = y;
}
if(maxX != int.MIN_VALUE)
{
maxX = (x<=maxX)? maxX:x;
}
else
{
maxX = minX+1;
}
if(maxY != int.MIN_VALUE)
{
maxY = (y<=maxY)? maxY:y;
}
else
{
maxY = minY+1;
}
srcPos.push(Vector.<uint>([x,y]));
}
}
}
var bmdW:int = maxX - minX;
var bmdH:int = maxY - minY;
cloneBmd = new BitmapData(bmdW+add*2, bmdH+add*2,true,0x00);
color = (vo.color!=-1)? vo.color:src.getPixel32(srcPos[0][0], srcPos[0][1]);
createBmdVec(srcPos,add);
bmp = new Bitmap(bmdVec[0]);
bmp.x = minX-add;
bmp.y = minY-add;
addChild(bmp);
if(!vo.isSync)
{
dispatchEvent(new HandwrittenAnimationEvent(HandwrittenAnimationEvent.CREATE_COMPLETE));
}
}
private function createBmdVec(pos:Vector.<Vector.<uint>>, radius:int):void
{
bmdVec = Vector.<BitmapData>([]);
var len:int = vo.time*vo.fps;
for (var i:int=0; i<len; i++)
{
bmdVec.push(createBmd(pos, radius));
}
}
private function createBmd(pos:Vector.<Vector.<uint>>, radius:int):BitmapData
{
var sh:Shape = new Shape();
var len:int = pos.length;
var mat:Matrix = new Matrix(1,0,0,1,radius,radius);
var col:ColorTransform = new ColorTransform();
var rect:Rectangle = new Rectangle(0,0,cloneBmd.width,cloneBmd.height);
for(var i:int = 0; i<len; i++)
{
var x:int = pos[i][0];
var y:int = pos[i][1];
drawSpline(createRandomCircleVector(x, y, (vo.radius!=-1)? vo.radius:radius), sh);
}
var bmd:BitmapData = cloneBmd.clone();
bmd.draw(sh, mat, col, null, rect);
return bmd;
}
private function createRandomCircleVector(x:int, y:int, max_radius:int):Vector.<Vector.<Number>>
{
var vec:Vector.<Vector.<Number>> = Vector.<Vector.<Number>>([]);
var len:int = vo.lineDensitydensity*4+4;
for (var i : int = 0; i<len; i++)
{
vec.push(randomCirclePos(x,y,max_radius));
}
return vec;
}
private function randomCirclePos(_x:Number, _y:Number, max_radius:int):Vector.<Number>
{
var radius:Number = Math.sqrt(Math.random())*max_radius;
var angle:Number = Math.random()*(Math.PI*2);
return Vector.<Number>([
_x+Math.cos(angle)*radius,
_y+Math.sin(angle)*radius
]);
}
private function update(e:TimerEvent=null):void
{
current++;
if(bmdVec.length==current)
{
current=0;
}
bmp.bitmapData=bmdVec[current];
}
private function drawSpline(v:Vector.<Vector.<Number>>, sh:Shape):void
{
if(v.length<2)
{
return;
}
// v.splice(0,0,v[0]);
// v.push(v[v.length-1]);
var numSegments:uint = 5;//曲線分割数(補完する数)
for(var i:uint=0; i<v.length-3; i++){
var p0:Vector.<Number> = v[i];
var p1:Vector.<Number> = v[i+1];
var p2:Vector.<Number> = v[i+2];
var p3:Vector.<Number> = v[i+3];
splineTo(p0, p1, p2, p3, numSegments,sh);
}
}
private function splineTo(p0:Vector.<Number>, p1:Vector.<Number>, p2:Vector.<Number>, p3:Vector.<Number>, numSegments:uint, sh:Shape):void {
sh.graphics.lineStyle(vo.lineWeight, color, 1);
sh.graphics.moveTo(p1[0], p1[1]);
for(var i:uint=0; i<numSegments; i++){
var t:Number = (i+1)/numSegments;
sh.graphics.lineTo(
catmullRom(p0[0], p1[0], p2[0], p3[0], t),catmullRom(p0[1], p1[1], p2[1], p3[1], t)
);
}
}
private function catmullRom(p0:Number,p1:Number,p2:Number,p3:Number,t:Number):Number{
var v0:Number = (p2 - p0) * 0.5;
var v1:Number = (p3 - p1) * 0.5;
return (2*p1 - 2*p2 + v0 + v1)*t*t*t +
(-3*p1 + 3*p2 - 2*v0 - v1)*t*t + v0*t + p1;
}
}
class HandwrittenAnimationVO
{
private var _time:Number;
private var _fps:int;
private var _lineWeight:int;
private var _lineDensitydensity:Number;
private var _isSync:Boolean;
private var _color:int;
private var _radius:int;
public function HandwrittenAnimationVO(time:Number=1, fps:int=20, radius:int=5, line_weight:Number=0.5, line_densitydensity:Number=0.3, color:int=-1, is_sync:Boolean=false)
{
this._time=time;
this._fps=fps;
this._lineWeight=line_weight;
this._lineDensitydensity=line_densitydensity;
this._isSync=is_sync;
this._color = color;
this._radius = radius;
}
public function get time():Number
{
return _time;
}
public function get fps():int
{
return _fps;
}
public function get lineWeight():int
{
return _lineWeight;
}
public function get lineDensitydensity():Number
{
return _lineDensitydensity;
}
public function get isSync():Boolean
{
return _isSync;
}
public function get color():int
{
return _color;
}
public function get radius():int
{
return _radius;
}
}
class HandwrittenAnimationEvent extends Event
{
public static const CREATE_COMPLETE : String = "CREATE_COMPLETE";
public function HandwrittenAnimationEvent(type:String)
{
super(type);
}
public override function clone() : Event
{
return new HandwrittenAnimationEvent(type);
}
}
