3_04
http://beautifl.net/book/
/**
* Copyright amashio ( http://wonderfl.net/user/amashio )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/wFrs
*/
package{
import com.bit101.components.PushButton;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
import flash.geom.Point;
import flash.net.FileReference;
import flash.net.URLRequest;
import flash.system.LoaderContext;
public class Main extends Sprite{
private static const UPPER_IMAGE_URL:String = "http://assets.wonderfl.net/images/related_images/2/20/203a/203a24ce61d8d1aafaec34f81e4877082a333140";
private static const LOWER_IMAGE_URL:String = "http://assets.wonderfl.net/images/related_images/c/c0/c00c/c00c78ed8353dfc87c586a0ffd95950be66a6302";
private var _upperImage:Loader;
private var _lowerImage:Loader;
private var _edge:Shape;
private var _mask:Shape;
private var _shadow:Shape;
public function Main(){
init();
loadImages();
}
//初期配置
private function init():void{
stage.frameRate = 60;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP;
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
_upperImage = new Loader();
_lowerImage = new Loader();
_edge = new Shape();
_mask = new Shape();
_shadow = new Shape();
//cacheAsBitmap で 内部Bitmapをつくる/ピクセルへの吸着を自動的に実行/処理が遅くなる可能性がある/filterをかけるときには しないといけない(?)
_edge.cacheAsBitmap = true;
_mask.cacheAsBitmap = true;
_shadow.cacheAsBitmap = true;
_shadow.filters = [new DropShadowFilter(0, 0, 0, 1.0, 8, 8, 1.2, 3, true, false, true)];
_lowerImage.mask = _mask;
addChild(_upperImage);
addChild(_edge);
addChild(_lowerImage);
addChild(_shadow);
addChild(_mask);
new PushButton(this, 0, 0, "upper layer", onButtonPush);
new PushButton(this, 100, 0, "lower layer", onButtonPush);
this.buttonMode = true;
}
private function loadImages():void{
_upperImage.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoadComplete);
_lowerImage.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoadComplete);
_upperImage.load(new URLRequest(UPPER_IMAGE_URL), new LoaderContext(true));
_lowerImage.load(new URLRequest(LOWER_IMAGE_URL), new LoaderContext(true));
}
private var _loadcount:uint = 0;
private function onImageLoadComplete(event:Event):void{
_loadcount++;
//読み込みが2つ完了したら
if(_loadcount == 2){
_upperImage.contentLoaderInfo.removeEventListener(Event.COMPLETE, onImageLoadComplete);
_lowerImage.contentLoaderInfo.removeEventListener(Event.COMPLETE, onImageLoadComplete);
start();
}
}
private function start():void{
addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
addEventListener(MouseEvent.ROLL_OUT, onMouseOut);
}
//
private var _isPressed:Boolean = false;//マウスのプレス状態
private var _prevX:Number;//前回のマウスポイントX座標
private var _prevY:Number;//前回のマウスポイントY座標
private var _prevMaskVertex1:Point;//前回描画したマスク領域の頂点1
private var _prevMaskVertex2:Point;//頂点2
private var _prevEdgeVertex1:Point;//描画した白い部分の頂点1
private var _prevEdgeVertex2:Point;//頂点2
private function onMouseDown(event:MouseEvent):void{
_isPressed = true;
_prevX = event.localX;
_prevY = event.localY;
_prevMaskVertex1 = new Point(_prevX, _prevY);
_prevMaskVertex2 = new Point(_prevX, _prevY);
_prevEdgeVertex1 = new Point(_prevX, _prevY);
_prevEdgeVertex2 = new Point(_prevX, _prevY);
}
private function onMouseMove(event:MouseEvent):void{
if(_isPressed){
var currX:Number = event.localX;
var currY:Number = event.localY;
//
var dx:Number = currX - _prevX;
var dy:Number = currY - _prevY;
var d:Number = Math.sqrt(dx * dx + dy * dy);
if(d < 5){
return;
}
//
var t:Number = Math.atan(dy / dx);
//移動量から描画領域の幅と頂点をもとめる
var w:Number = d + Math.random() * 10;
var currMaskVertex1:Point = new Point(
w * Math.cos(Math.PI / 2 + t) + currX,
w * Math.sin(Math.PI / 2 + t) + currY);
var currMaskVertex2:Point = new Point(
w * Math.cos(3 * Math.PI / 2 + t) + currX,
w * Math.sin(3 * Math.PI / 2 + t) + currY);
//白い部分のエリアの幅と頂点を計算
var ww:Number = w * 1.15 + 1;
var currEdgeVertex1:Point = new Point(
ww * Math.cos(Math.PI / 2 + t) + currX,
ww * Math.sin(Math.PI / 2 + t) + currY);
var currEdgeVertex2:Point = new Point(
ww * Math.cos(3 * Math.PI / 2 + t) + currX,
ww * Math.sin(3 * Math.PI / 2 + t) + currY);
if(dx < 0){
var tmp:Point = currMaskVertex1;
currMaskVertex1 = currMaskVertex2;
currMaskVertex2 = tmp;
tmp = currEdgeVertex1;
currEdgeVertex1 = currEdgeVertex2;
currEdgeVertex2 = tmp;
}
//頂点の作成 計算させる
var points1:Vector.<Point> = createPointData(_prevMaskVertex1, currMaskVertex1, Math.floor(d), t);
var points2:Vector.<Point> = createPointData(_prevMaskVertex2, currMaskVertex2, Math.floor(d), t);
var points3:Vector.<Point> = createPointData(_prevEdgeVertex1, currEdgeVertex1, Math.floor(d), t);
var points4:Vector.<Point> = createPointData(_prevEdgeVertex2, currEdgeVertex2, Math.floor(d), t);
//最後のポイントは今のところ
var endPoint:Point = new Point(currX + dx, currY + dy);
//各配列に最後のポイントに追加していく
points1.push(endPoint);
points2.push(endPoint);
points3.push(endPoint);
points4.push(endPoint);
//
draw(_mask, points1, points2);
draw(_shadow, points1, points2);
draw(_edge, points3, points4);
//
_prevX = currX;
_prevY = currY;
_prevMaskVertex1 = currMaskVertex1;
_prevMaskVertex2 = currMaskVertex2;
_prevEdgeVertex1 = currEdgeVertex1;
_prevEdgeVertex2 = currEdgeVertex2;
}
}
//ポイントの計算
private function createPointData(start:Point, end:Point, d:int, t:Number):Vector.<Point> {
var points:Vector.<Point> = new Vector.<Point>();
var cosT:Number = Math.cos(t);
var sinT:Number = Math.sin(t);
//
var a:Number = (start.y - end.y) / (start.x - end.x);
var b:Number = start.y - a * start.x;
points.push(new Point(start.x, start.y));
for(var i:uint = 1; i < d; i++){
var xx:Number = start.x + i / d * (end.x - start.x);
var yy:Number = a * xx + b;
xx += Math.random() * 3 * sinT;
yy += Math.random() * 3 * cosT;
points.push(new Point(xx, yy));
}
points.push(new Point(end.x, end.y));
return points;
}
private function draw(target:Shape, points1:Vector.<Point>, points2:Vector.<Point>, color:uint = 0xFFFFFF):void{
var j:int;
var k:int;
with(target.graphics){
beginFill(color);
moveTo(points1[0].x, points1[0].y);
for(j = 1; j < points1.length; j++){
lineTo(points1[j].x, points1[j].y);
}
for(k=points2.length - 1; k >= 0; k--){
lineTo(points2[k].x, points2[k].y);
}
moveTo(points2[0].x, points2[0].y);
endFill();
}
}
//
private function onMouseUp(event:MouseEvent):void{
_isPressed = false;
}
//
private function onMouseOut(event:MouseEvent):void{
onMouseUp(event);//
}
//消す
private function onKeyDown(event:KeyboardEvent):void{
_edge.graphics.clear();
_mask.graphics.clear();
_shadow.graphics.clear();
}
//イメージが再設定されたときに読み込み//これは共通化されている
//
private var fileRef1:FileReference;
private var fileRef2:FileReference;
private function onButtonPush(event:Event):void{
if(PushButton(event.target).label == "upper layer"){
fileRef1 = new FileReference();
fileRef1.browse();
fileRef1.addEventListener(Event.SELECT, onSelect);
}else{
fileRef2 = new FileReference();
fileRef2.browse();
fileRef2.addEventListener(Event.SELECT, onSelect);
}
}
private function onSelect(event:Event):void{
FileReference(event.target).addEventListener(Event.COMPLETE, onComplete);
FileReference(event.target).load();
}
//
private function onComplete(event:Event):void{
if(event.target == fileRef1){
_upperImage.loadBytes(fileRef1.data); //Loader.loadBytes(FileReference.data);
}else{
_lowerImage.loadBytes(fileRef2.data);
}
}
}
}