wonderfl build Flash online
// forked from kacchan6's forked from: シェイプトゥイーンの実験
// forked from kacchan6's シェイプトゥイーンの実験
package
{
import flash.geom.ColorTransform;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.filters.GlowFilter;
[SWF(width=465, height=465, backgroundColor=0x000000, frameRate=30)]
public class ShapeTween extends Sprite
{
public function ShapeTween()
{
//アイコンデータは以下から参照 http://raphaeljs.com/icons/
var path1:CompoundPath = new CompoundPath();
//wonderfl
SVGPathParser.draw(path1, "M132.897,254.69c-0.14,0.49-0.49,0.771-1.12,0.771h-4.13c-0.56,0-0.91-0.28-1.12-0.771l-9.941-32.204c-3.431,10.851-6.931,21.422-10.361,32.134c-0.14,0.56-0.56,0.84-1.26,0.84h-3.851c-0.63,0-1.05-0.07-1.26-0.84l-11.691-36.054c-0.21-0.49,0.14-0.98,0.7-0.98h3.22c0.561,0,0.98,0.35,1.26,0.98l9.941,31.923c3.431-10.711,6.721-20.862,10.151-31.574c0.21-0.91,0.77-1.33,1.61-1.33h3.29c0.91,0,1.47,0.42,1.68,1.33l9.731,31.574c3.57-10.991,6.721-20.933,10.291-31.923c0.21-0.561,0.7-0.98,1.26-0.98h2.8c0.56,0,0.91,0.49,0.7,0.98L132.897,254.69zM185.536,236.559c0,5.531-1.75,10.291-4.34,13.861c-3.291,3.92-7.771,6.16-13.582,6.16s-10.361-2.24-13.651-6.16c-2.59-3.57-4.271-8.33-4.271-13.861c0-5.67,1.4-10.291,4.271-13.861c3.291-4.061,7.841-6.091,13.651-6.091c5.881,0,10.291,1.96,13.582,6.091C184.066,226.408,185.536,231.028,185.536,236.559z M180.355,236.559c0-4.411-1.26-8.261-3.29-11.271c-2.45-3.011-5.601-4.48-9.451-4.48c-3.92,0-7,1.61-9.451,4.48c-2.17,3.01-3.36,6.86-3.36,11.271c0,4.48,1.19,8.4,3.36,11.271c2.451,3.01,5.601,4.551,9.451,4.551c3.92,0,7.001-1.681,9.451-4.551C179.096,244.959,180.355,241.039,180.355,236.559zM225.015,254.48c0,0.63-0.35,0.98-0.98,0.98h-2.8c-0.63,0-0.98-0.351-0.98-0.98v-22.052c0-8.611-3.22-11.832-8.821-11.832c-7.561,0-11.622,4.411-11.622,11.971v21.913c0,0.63-0.35,0.98-0.98,0.98h-2.8c-0.63,0-0.98-0.351-0.98-0.98v-28.003c0-3.991,0-5.881-0.21-7.911c-0.07-0.63,0.42-0.98,0.98-0.98h2.52c0.63,0,0.98,0.35,0.98,0.98v3.85c2.59-3.99,5.88-5.811,12.321-5.811c8.891,0,13.371,5.391,13.371,14.702V254.48zM267.784,254.48c0,0.63-0.35,0.98-0.979,0.98h-2.73c-0.631,0-0.98-0.351-0.98-0.98v-5.25c-2.521,4.76-6.581,7.141-12.182,7.141c-4.97,0-8.891-1.891-11.69-5.741c-2.591-3.57-3.851-8.261-3.851-14.142c0-13.091,5.181-19.672,15.541-19.672c5.601,0,10.222,2.45,12.182,6.021v-22.052c0-0.63,0.35-0.98,0.98-0.98h2.73c0.63,0,0.979,0.35,0.979,0.98V254.48z M240.552,236.488c0,4.41,0.7,7.98,2.17,10.711c2.03,3.361,4.9,5.182,9.031,5.182c7.561,0,11.341-8.611,11.341-15.893c0-8.96-3.92-15.681-11.341-15.681c-3.991,0-7.001,1.68-9.031,5.11C241.252,228.648,240.552,232.288,240.552,236.488zM282.271,237.889c-0.21,9.24,4.971,14.492,12.602,14.492c3.71,0,7.001-0.631,9.801-2.24c0.63-0.281,0.91-0.141,0.91,0.489v3.15c0,0.42-0.28,0.771-0.77,0.979c-3.081,1.191-6.371,1.82-10.291,1.82c-11.481,0-17.433-6.65-17.433-20.092c0-5.95,1.471-10.711,4.411-14.351c3.08-3.71,7.001-5.531,11.691-5.531c5.25,0,8.961,1.89,11.69,5.601c2.381,3.291,3.57,7.771,3.57,13.301c0,2.451,0.07,2.381-2.52,2.381H282.271z M303.273,233.898c0-3.851-0.7-6.721-2.311-9.171c-1.75-2.73-4.2-4.13-7.491-4.13c-3.36,0-6.091,1.4-8.19,4.201c-1.681,2.52-2.94,6.021-3.011,9.101H303.273zM335.822,221.857c-0.841-0.28-1.961-0.42-3.36-0.42c-3.431,0-6.021,1.68-7.701,5.11c-1.33,2.66-1.96,6.091-1.96,10.221v17.712c0,0.63-0.351,0.98-0.98,0.98h-2.73c-0.63,0-0.979-0.351-0.979-0.98v-28.423c0-3.36-0.07-5.041-0.141-7.491c0-0.63,0.351-0.98,0.98-0.98h2.59c0.63,0,0.98,0.35,0.98,0.98v6.86c2.311-5.88,5.671-8.821,10.081-8.821c1.05,0,2.17,0.14,3.221,0.42c0.56,0.21,1.05,0.56,1.05,1.33v2.94C336.872,221.857,336.312,222.067,335.822,221.857zM359.341,199.175c0.63,0.21,0.91,0.7,0.841,1.47l-0.141,2.03c-0.07,0.56-0.49,0.7-0.979,0.49c-1.051-0.35-1.751-0.49-2.871-0.49c-2.729,0-4.55,1.4-5.32,4.13c-0.35,1.12-0.49,3.571-0.49,7.421v3.36h7.701c0.63,0,0.98,0.35,0.98,0.98v2.1c0,0.63-0.351,0.98-0.98,0.98h-7.701v32.833c0,0.63-0.35,0.98-0.979,0.98h-2.73c-0.63,0-0.98-0.351-0.98-0.98v-32.833h-6.79c-0.631,0-0.98-0.35-0.98-0.98v-2.1c0-0.63,0.35-0.98,0.98-0.98h6.79v-2.87c0-5.11,0.49-8.751,1.4-10.991c1.47-3.36,4.341-5.041,8.681-5.041C357.101,198.685,358.291,198.825,359.341,199.175zM371.869,255.461h-3.08c-0.631,0-0.98-0.351-0.98-0.98v-53.696c0-0.63,0.35-0.98,0.98-0.98h3.08c0.63,0,0.979,0.35,0.979,0.98v53.696C372.849,255.11,372.499,255.461,371.869,255.461z");
//build
var path2:CompoundPath = new CompoundPath();
SVGPathParser.draw(path2, "M158.023,200.505c0-0.63,0.35-0.98,0.98-0.98h2.73c0.63,0,0.98,0.35,0.98,0.98v22.332c2.31-3.85,6.86-6.3,12.181-6.3c10.431,0,15.612,6.581,15.612,19.742c0.21,10.431-4.761,19.882-15.612,19.882c-5.601,0-9.661-2.38-12.181-7.141v5.461c0,0.631-0.35,0.98-0.98,0.98h-2.73c-0.63,0-0.98-0.35-0.98-0.98V200.505z M185.466,236.278c0.21-7.771-2.871-15.751-11.412-15.751c-7.63,0-11.341,7.071-11.341,15.751c0,8.472,4.9,15.892,11.341,15.892C182.595,252.17,185.676,244.189,185.466,236.278zM230.965,254.48c0,0.631-0.35,0.98-0.98,0.98h-2.521c-0.63,0-0.98-0.35-0.98-0.98v-5.811c-2.45,5.6-6.371,7.91-12.531,7.91c-8.751,0-13.091-4.9-13.091-14.631v-23.382c0-0.63,0.35-0.98,0.98-0.98h2.8c0.63,0,0.98,0.35,0.98,0.98v22.123c0,7.91,3.01,11.9,9.101,11.9c7.071,0,11.551-6.65,11.341-14.561v-19.462c0-0.63,0.35-0.98,0.98-0.98h2.8c0.63,0,0.98,0.35,0.98,0.98v28.142C230.825,249.79,230.895,252.03,230.965,254.48zM242.301,204.355c0-1.89,1.471-3.43,3.361-3.43c1.89,0,3.43,1.54,3.43,3.43c0,1.891-1.54,3.36-3.43,3.36C243.771,207.715,242.301,206.246,242.301,204.355z M247.271,255.461h-3.08c-0.631,0-0.98-0.35-0.98-0.98v-35.914c0-0.63,0.35-0.98,0.98-0.98h3.08c0.631,0,0.98,0.35,0.98,0.98v35.914C248.252,255.111,247.902,255.461,247.271,255.461zM264.281,255.461h-3.08c-0.631,0-0.98-0.35-0.98-0.98v-53.696c0-0.63,0.35-0.98,0.98-0.98h3.08c0.629,0,0.979,0.35,0.979,0.98v53.696C265.26,255.111,264.91,255.461,264.281,255.461zM307.473,254.48c0,0.631-0.35,0.98-0.98,0.98h-2.73c-0.629,0-0.979-0.35-0.979-0.98v-5.25c-2.521,4.76-6.582,7.141-12.182,7.141c-4.971,0-8.891-1.891-11.691-5.741c-2.59-3.57-3.852-8.261-3.852-14.142c0-13.091,5.182-19.672,15.543-19.672c5.6,0,10.221,2.45,12.182,6.021v-22.052c0-0.63,0.35-0.98,0.979-0.98h2.73c0.631,0,0.98,0.35,0.98,0.98V254.48z M280.24,236.488c0,4.41,0.699,7.98,2.17,10.711c2.029,3.361,4.9,5.182,9.031,5.182c7.561,0,11.342-8.611,11.342-15.893c0-8.96-3.922-15.681-11.342-15.681c-3.99,0-7.002,1.68-9.031,5.11C280.939,228.648,280.24,232.288,280.24,236.488z");
//Flash
var path3:CompoundPath = new CompoundPath();
SVGPathParser.draw(path3, "M162.853,254.48c0,0.63-0.35,0.98-0.98,0.98h-3.221c-0.63,0-0.98-0.351-0.98-0.98v-48.795c0-2.03,0-2.03,2.03-2.03h23.382c0.63,0,0.98,0.35,0.98,0.98v2.38c0,0.63-0.35,0.98-0.98,0.98h-20.232v18.552h19.252c0.63,0,0.98,0.35,0.98,0.98v2.521c0,0.63-0.35,0.98-0.98,0.98h-19.252V254.48zM197.082,255.461h-3.081c-0.63,0-0.98-0.351-0.98-0.98v-53.696c0-0.63,0.35-0.98,0.98-0.98h3.081c0.63,0,0.98,0.35,0.98,0.98v53.696C198.062,255.11,197.712,255.461,197.082,255.461zM211.57,223.467c-0.49,0.28-0.98,0.14-0.98-0.35v-2.66c0-0.63,0.35-1.12,0.98-1.47c3.291-1.75,6.861-2.38,11.271-2.38c9.311,0,13.441,4.411,13.441,13.371v17.572c0,2.8,0.07,4.9,0.279,6.931c0,0.63-0.35,0.98-0.979,0.98h-2.521c-0.63,0-0.98-0.351-0.98-0.98v-5.391c-1.96,4.761-7.071,7.491-12.461,7.491c-4.691,0-8.191-1.4-10.361-4.131c-1.47-1.891-2.24-4.48-2.24-6.931c0-5.671,2.59-9.941,8.121-11.972c3.36-1.189,8.541-1.819,15.471-1.819h0.91v-2.101c0-5.881-2.45-9.031-8.681-9.031C218.641,220.597,214.931,221.437,211.57,223.467z M231.522,235.719h-1.33c-5.25-0.21-9.311,0.49-12.041,1.54c-3.92,1.4-5.881,4.2-5.881,8.051c0,2.311,0.7,4.48,2.311,5.601c1.4,1.12,3.29,1.68,5.601,1.68c6.511,0,11.341-5.25,11.341-14.491V235.719zM246.221,250.84c2.869,1.19,5.811,1.75,8.82,1.75c5.04,0,8.681-2.66,8.681-6.86c0-2.45-2.1-4.9-4.69-6.371c-2.87-1.609-6.021-2.939-8.82-4.55c-3.361-1.891-4.9-4.761-4.9-7.771c0-7.001,5.6-10.431,12.32-10.431c3.571,0,5.951,0.35,8.541,1.12c0.561,0.21,1.051,0.56,0.98,1.19l-0.21,2.101c-0.07,0.77-0.63,0.91-1.12,0.7c-2.311-0.84-4.41-1.12-7.701-1.12c-5.391,0-8.121,2.17-8.121,6.441c0,1.89,1.33,3.5,4.761,5.18c3.011,1.471,5.741,2.66,9.102,4.551c2.87,1.61,5.04,5.11,5.04,8.961c0,7.421-6.511,10.852-13.512,10.852c-4.061,0-6.301-0.28-9.66-1.19c-0.631-0.21-0.98-0.63-0.91-1.26l0.279-2.591C245.17,250.77,245.59,250.56,246.221,250.84zM307.753,254.48c0,0.63-0.35,0.98-0.979,0.98h-2.801c-0.63,0-0.98-0.351-0.98-0.98v-21.563c0-9.031-3.29-12.181-8.61-12.181c-7.631,0-11.831,3.851-11.831,10.292v23.452c0,0.63-0.351,0.98-0.98,0.98h-2.8c-0.631,0-0.98-0.351-0.98-0.98v-53.766c0-0.63,0.35-0.98,0.98-0.98h2.8c0.63,0,0.98,0.35,0.98,0.98v20.302c2.59-3.01,6.301-4.271,12.111-4.271c9.03,0,13.091,5.25,13.091,16.101V254.48z");
//online
var path4:CompoundPath = new CompoundPath();
SVGPathParser.draw(path4, "M172.271,236.559c0,5.53-1.75,10.291-4.34,13.861c-3.291,3.921-7.771,6.161-13.582,6.161s-10.361-2.24-13.651-6.161c-2.59-3.57-4.271-8.331-4.271-13.861c0-5.671,1.4-10.291,4.271-13.861c3.291-4.061,7.841-6.091,13.651-6.091c5.881,0,10.291,1.96,13.582,6.091C170.801,226.407,172.271,231.028,172.271,236.559z M167.09,236.559c0-4.411-1.26-8.261-3.29-11.271c-2.45-3.01-5.601-4.48-9.451-4.48c-3.92,0-7,1.61-9.451,4.48c-2.17,3.011-3.36,6.861-3.36,11.271c0,4.48,1.19,8.4,3.36,11.271c2.45,3.01,5.601,4.55,9.451,4.55c3.92,0,7.001-1.68,9.451-4.55C165.831,244.959,167.09,241.039,167.09,236.559zM211.75,254.48c0,0.63-0.35,0.98-0.98,0.98h-2.8c-0.63,0-0.98-0.351-0.98-0.98v-22.052c0-8.611-3.22-11.832-8.821-11.832c-7.561,0-11.622,4.411-11.622,11.972v21.912c0,0.63-0.35,0.98-0.98,0.98h-2.8c-0.63,0-0.98-0.351-0.98-0.98v-28.003c0-3.99,0-5.881-0.21-7.911c-0.07-0.63,0.42-0.98,0.98-0.98h2.521c0.63,0,0.98,0.35,0.98,0.98v3.851c2.59-3.99,5.88-5.811,12.321-5.811c8.891,0,13.371,5.391,13.371,14.702V254.48zM228.267,255.461h-3.081c-0.63,0-0.98-0.351-0.98-0.98v-53.696c0-0.63,0.35-0.98,0.98-0.98h3.081c0.63,0,0.98,0.35,0.98,0.98v53.696C229.247,255.11,228.896,255.461,228.267,255.461zM240.165,204.355c0-1.89,1.471-3.43,3.36-3.43c1.891,0,3.431,1.54,3.431,3.43s-1.54,3.36-3.431,3.36C241.636,207.715,240.165,206.245,240.165,204.355z M245.136,255.461h-3.08c-0.63,0-0.98-0.351-0.98-0.98v-35.914c0-0.63,0.351-0.98,0.98-0.98h3.08c0.63,0,0.98,0.35,0.98,0.98v35.914C246.116,255.11,245.766,255.461,245.136,255.461zM288.047,254.48c0,0.63-0.35,0.98-0.979,0.98h-2.801c-0.63,0-0.98-0.351-0.98-0.98v-22.052c0-8.611-3.22-11.832-8.82-11.832c-7.561,0-11.621,4.411-11.621,11.972v21.912c0,0.63-0.351,0.98-0.98,0.98h-2.8c-0.631,0-0.98-0.351-0.98-0.98v-28.003c0-3.99,0-5.881-0.21-7.911c-0.07-0.63,0.42-0.98,0.98-0.98h2.52c0.63,0,0.98,0.35,0.98,0.98v3.851c2.59-3.99,5.881-5.811,12.321-5.811c8.891,0,13.371,5.391,13.371,14.702V254.48zM302.884,237.889c-0.21,9.241,4.971,14.491,12.602,14.491c3.711,0,7.001-0.63,9.801-2.24c0.631-0.28,0.91-0.14,0.91,0.49v3.15c0,0.42-0.279,0.771-0.77,0.98c-3.081,1.189-6.371,1.82-10.291,1.82c-11.481,0-17.433-6.651-17.433-20.093c0-5.95,1.471-10.711,4.411-14.351c3.08-3.71,7-5.531,11.691-5.531c5.25,0,8.961,1.89,11.69,5.601c2.381,3.291,3.57,7.771,3.57,13.301c0,2.451,0.07,2.381-2.52,2.381H302.884z M323.887,233.898c0-3.851-0.7-6.721-2.311-9.171c-1.75-2.73-4.2-4.131-7.491-4.131c-3.36,0-6.09,1.4-8.19,4.201c-1.681,2.52-2.94,6.021-3.011,9.101H323.887z");
var morphs:Array = [];
morphs.push(CompoundPath.createMorphingPath(path1, path2));
morphs.push(CompoundPath.createMorphingPath(path2, path3));
morphs.push(CompoundPath.createMorphingPath(path3, path4));
morphs.push(CompoundPath.createMorphingPath(path4, path1));
var shape:Shape = new Shape();
var data:BitmapData = new BitmapData(465, 465, true, 0);
var bitmap:Bitmap = new Bitmap(data);
var m:Matrix = new Matrix();
//m.scale(10, 10);
//m.translate(50, 50);
addChild(bitmap);
var g:Graphics = graphics;
g.beginFill(0x000000);
g.drawRect(0, 0, 465, 465);
g.endFill();
var t:uint = 0;
addEventListener(Event.ENTER_FRAME, function(e:Event):void
{
if (t >= 400)
{
t = 0;
}
var index:int = int(t / 100);
var t0:Number = (t - index * 100) / 100;
t0 *= t0;
var morph:MorphingPath = morphs[index];
morph.interpolate(t0);
var g:Graphics = shape.graphics;
g.clear();
g.beginFill(0xffffff);
g.drawPath(morph.commands, morph.data);
g.endFill();
data.colorTransform(data.rect, new ColorTransform(0.9, 0.3, 0.5, 0.95));
data.draw(shape, m);
t += 4;
});
}
}
}
import flash.display.GraphicsPathCommand;
class SVGPathParser
{
private static var _svgPathCommands:Object = {a: 7, A: 7, q: 4, Q: 4,
t: 2, T: 2, s: 4, S: 4,
c: 6, C: 6, v: 1, V: 1,
h: 1, H: 1, l: 2, L: 2,
z: 0, Z: 0, m: 2, M: 2};
private static var _svgPathPattern:RegExp = /^\s*(([-+]?(([0-9]*\.?[0-9]+)|([0-9]+\.?[0-9]*)))|[aAqQtTsScCvVhHlLzZmM,])\s*/;
public static function draw(path:CompoundPath, pathString:String):void
{
if (pathString === null || pathString === "")
{
return;
}
var tokens:Array;
var lastCommand:String;
var moved:Boolean = false;
var args:Vector.<Number> = new Vector.<Number>();
var commaAccept:Boolean;
var commandAccept:Boolean;
var point:ControlPoint = new ControlPoint();
while (tokens = pathString.match(_svgPathPattern))
{
var token:String = tokens[1];
pathString = pathString.substring(tokens[0].length);
if (!moved && token !== "m" && token !== "M")
{
return;
}
else if (!moved)
{
moved = true;
lastCommand = token;
continue;
}
if (token in _svgPathCommands)
{
if (commandAccept)
{
return;
}
if (executeCommand(path, point, lastCommand, args))
{
lastCommand = token;
}
else
{
return;
}
lastCommand = token;
commaAccept = false;
commandAccept = false;
}
else
{
if (token !== ",")
{
commandAccept = false;
args.push(parseFloat(token));
}
else
{
commandAccept = true;
if (commaAccept)
{
continue;
}
else
{
return;
}
}
commaAccept = true;
}
}
if (lastCommand)
{
executeCommand(path, point, lastCommand, args)
}
}
private static function executeCommand(path:CompoundPath, point:ControlPoint, command:String, args:Vector.<Number>):Boolean
{
var argLength:uint = _svgPathCommands[command];
var command0:String = command.toLocaleLowerCase();
var relative:Number = command0 === command ? 1 : 0;
var x:Number, y:Number, x1:Number, y1:Number;
args.reverse();
while (true)
{
if (args.length < argLength)
{
return false;
}
switch (command0)
{
case "a":
//unsupported
break;
case "q":
point.qx = args.pop() + relative * path.x;
point.qy = args.pop() + relative * path.y;
//passthrough
case "t":
x = args.pop() + relative * path.x;
y = args.pop() + relative * path.y;
if (isNaN(point.qx))
{
point.qx = path.x;
}
if (isNaN(point.qy))
{
point.qy = path.y;
}
path.curveTo(point.qx, point.qy, x, y);
point.cx = point.cy = NaN;
point.qx = x * 2 - point.qx;
point.qy = y * 2 - point.qy;
break;
case "c":
point.cx = args.pop() + relative * path.x;
point.cy = args.pop() + relative * path.y;
//passthrough
case "s":
x = args.pop() + relative * path.x;
y = args.pop() + relative * path.y;
x1 = relative * path.x + args.pop();
y1 = relative * path.y + args.pop();
if (isNaN(point.cx))
{
point.cx = path.x;
}
if (isNaN(point.cy))
{
point.cy = path.y;
}
path.cubicCurveTo(point.cx, point.cy, x, y, x1, y1);
point.qx = point.qy = NaN;
point.cx = x1 * 2 - x;
point.cy = y1 * 2 - y;
break;
case "v":
path.lineTo(path.x, relative * path.y + args.pop());
point.cx = point.qx = point.cy = point.qy = NaN;
break;
case "h":
path.lineTo(relative * path.x + args.pop(), path.y);
point.cx = point.qx = point.cy = point.qy = NaN;
break;
case "l":
path.lineTo(relative * path.x + args.pop(), relative * path.y + args.pop());
point.cx = point.qx = point.cy = point.qy = NaN;
break;
case "z":
path.close();
point.cx = point.qx = point.cy = point.qy = NaN;
break;
case "m":
path.moveTo(relative * path.x + args.pop(), relative * path.y + args.pop());
point.cx = point.qx = point.cy = point.qy = NaN;
break;
default:
return false;
}
if (args.length === 0)
{
break;
}
}
return true;
}
private static function radiusToDegress(angle:Number):Number
{
return angle * (180 / Math.PI);
}
}
class CompoundPath
{
private static var _cbt:Vector.<Number> = Vector.<Number>([0, 0, 0, 1,
0.001953125, 0.041015625, 0.287109375, 0.669921875,
0.015625, 0.140625, 0.421875, 0.421875,
0.052734375, 0.263671875, 0.439453125, 0.244140625,
0.125, 0.375, 0.375, 0.125,
0.244140625, 0.439453125, 0.263671875, 0.052734375,
0.421875, 0.421875, 0.140625, 0.015625,
0.669921875, 0.287109375, 0.041015625, 0.001953125,
1, 0, 0, 0]);
public static function createMorphingPath(start:CompoundPath, end:CompoundPath):MorphingPath
{
start.close();
end.close();
var paths:uint = Math.max(start._paths.length, end._paths.length);
var startData:Vector.<Number> = new Vector.<Number>();
var endData:Vector.<Number> = new Vector.<Number>();
var commands:Vector.<int> = new Vector.<int>();
for (var i:uint = 0; i < paths; i++)
{
var startPath:Path = start._paths[i];
var endPath:Path = end._paths[i];
var count:uint;
if (startPath === null)
{
count = endPath.writeCoordCenter(endData, startData);
}
else if (endPath === null)
{
count = startPath.writeCoordCenter(startData, endData);
}
else if (startPath.coordsList.length !== endPath.coordsList.length)
{
count = startPath.writeCoordInterpolate(endPath, startData);
endPath.writeCoordInterpolate(startPath, endData);
}
else
{
count = startPath.coordsList.length;
startData.push(startPath.x, startPath.y);
endData.push(endPath.x, endPath.y);
for (var j:uint = 0, len:uint = startPath.coordsList.length; j < len; j++)
{
var startCoords:Coords = startPath.coordsList[j];
var endCoords:Coords = endPath.coordsList[j];
startData.push(startCoords.cx, startCoords.cy, startCoords.ax, startCoords.ay);
endData.push(endCoords.cx, endCoords.cy, endCoords.ax, endCoords.ay);
}
}
var commandIndex:uint = commands.length;
commands[commandIndex++] = GraphicsPathCommand.MOVE_TO;
for (var k:uint = 0; k < count; k++)
{
commands[commandIndex++] = GraphicsPathCommand.CURVE_TO;
}
}
return new MorphingPath(commands, startData, endData);
}
private var _coordsList:Array;
private var _lastMoveX:Number;
private var _lastMoveY:Number;
private var _paths:Array;
private var _x:Number;
private var _y:Number;
public function CompoundPath()
{
_paths = [];
_coordsList = [];
_x = 0;
_y = 0;
_lastMoveX = 0;
_lastMoveY = 0;
}
public function close():void
{
if (_coordsList.length > 0)
{
if (_x !== _lastMoveX || _y !== _lastMoveY)
{
lineTo(_lastMoveX, _lastMoveY);
_x = _lastMoveX;
_y = _lastMoveY;
}
_paths.push(new Path(_lastMoveX, _lastMoveY, _coordsList.splice(0)));
}
}
public function cubicCurveTo(cx1:Number, cy1:Number, cx2:Number, cy2:Number, ax:Number, ay:Number):void
{
var t:Vector.<Number> = _cbt, x0:Number, x1:Number, x2:Number, y0:Number, y1:Number, y2:Number, i:int;
for (i = 24; i >= 0; i -= 8)
{
x0 = t[i] * _x + t[i + 1] * cx1 + t[i + 2] * cx2 + t[i + 3] * ax;
y0 = t[i] * _y + t[i + 1] * cy1 + t[i + 2] * cy2 + t[i + 3] * ay;
x1 = t[i + 4] * _x + t[i + 5] * cx1 + t[i + 6] * cx2 + t[i + 7] * ax;
y1 = t[i + 4] * _y + t[i + 5] * cy1 + t[i + 6] * cy2 + t[i + 7] * ay;
x2 = t[i + 8] * _x + t[i + 9] * cx1 + t[i + 10] * cx2 + t[i + 11] * ax;
y2 = t[i + 8] * _y + t[i + 9] * cy1 + t[i + 10] * cy2 + t[i + 11] * ay;
var coords:Coords = new Coords(_x, _y, x1 * 2 - (x0 + x2) * 0.5, y1 * 2 - (y0 + y2) * 0.5, x0, y0);
if (coords.length > 0)
{
_coordsList.push(coords);
}
_x = x0;
_y = y0;
}
_x = ax;
_y = ay;
}
public function curveTo(cx:Number, cy:Number, ax:Number, ay:Number):void
{
var coords:Coords = new Coords(_x, _y, cx, cy, ax, ay);
if (coords.length > 0)
{
_coordsList.push(coords);
}
_x = ax;
_y = ay;
}
public function lineTo(x:Number, y:Number):void
{
var coords:Coords = new Coords(_x, _y, x + (_x - x) * 0.5, y + (_y - y) * 0.5, x, y);
if (coords.length > 0)
{
_coordsList.push(coords);
}
_x = x;
_y = y;
}
public function moveTo(x:Number, y:Number):void
{
if (_coordsList.length > 0)
{
_paths.push(new Path(_lastMoveX, _lastMoveY, _coordsList.splice(0)));
}
_x = x;
_y = y;
_lastMoveX = x;
_lastMoveY = y;
}
public function get x():Number
{
return _x;
}
public function get y():Number
{
return _y;
}
}
class ControlPoint
{
public var cx:Number;
public var cy:Number;
public var qx:Number;
public var qy:Number;
}
class Path
{
public var coordsList:Array;
public var x:Number;
public var y:Number;
public function Path(x:Number, y:Number, coordsList:Array):void
{
var total:Number = 0;
var coords:Coords;
var current:Number = 0;
for each (coords in coordsList)
{
total += coords.length;
}
for each (coords in coordsList)
{
coords.pos = current / total;
current += coords.length;
}
this.x = x;
this.y = y;
this.coordsList = coordsList;
}
private function getNumCoords(from:Number, to:Number):uint
{
var count:uint = 0;
for each (var coords:Coords in coordsList)
{
if (from <= coords.pos && coords.pos < to)
{
count++;
}
else if (to <= coords.pos)
{
break;
}
}
return count;
}
public function writeCoordCenter(selfData:Vector.<Number>, centerData:Vector.<Number>):uint
{
var pointsX:Array = [];
var pointsY:Array = [];
var x:Number = this.x, y:Number = this.y;
var len:uint = 0, index:uint = selfData.length;
selfData.push(x, y);
for each (var coords:Coords in coordsList)
{
selfData.push(coords.cx, coords.cy, coords.ax, coords.ay);
getBounds1(coords.sy, coords.sx, coords.cx, coords.cy, coords.ax, coords.ay, pointsX, pointsY);
len++;
}
x = Math.min.apply(null, pointsX);
y = Math.min.apply(null, pointsY);
x += (Math.max.apply(null, pointsX) - x) / 2;
y += (Math.max.apply(null, pointsY) - y) / 2;
centerData.push(x, y);
for (var i:uint = 0; i < len; i++)
{
centerData.push(x, y, x, y);
}
return len;
}
public function writeCoordInterpolate(compare:Path, data:Vector.<Number>):uint
{
var self:Path = clone(), coords:Coords;
var segments:uint = 4, i:uint, diff:int;
var posFrom:Number, posTo:Number;
for (i = 0; i < segments; i++)
{
posFrom = i / segments;
posTo = (i + 1) / segments;
diff = compare.getNumCoords(posFrom, posTo) - self.getNumCoords(posFrom, posTo);
if (diff <= 0)
{
continue;
}
for each (coords in compare.coordsList)
{
if (posFrom <= coords.pos && coords.pos < posTo)
{
if (self.split(coords.pos))
{
diff--;
if (diff === 0)
{
break;
}
}
}
else if (posTo <= coords.pos)
{
break;
}
}
}
data.push(x, y);
for each (coords in self.coordsList)
{
data.push(coords.cx, coords.cy, coords.ax, coords.ay);
}
return self.coordsList.length;
}
private function clone():Path
{
var coordsList:Array = new Array(this.coordsList.length);
for (var i:uint = 0, len:uint = coordsList.length; i < len; i++)
{
coordsList[i] = this.coordsList[i].clone();
}
return new Path(x, y, coordsList);
}
private function getBounds1(x1:Number, y1:Number, x2:Number, y2:Number, x3:Number, y3:Number, pointsX:Array, pointsY:Array):void
{
var left:Number = Math.min(x1, x3);
var right:Number = Math.max(x1, x3);
var top:Number = Math.min(y1, y3);
var bottom:Number = Math.max(y1, y3);
var t:Number, tp:Number, p:Number;
t = (x1 - x2) / (x3 - 2 * x2 + x1);
if (0 <= t && t <= 1)
{
tp = 1 - t;
p = tp * tp * x1 + 2 * tp * t * x2 + t * t * x3;
if (p < left)
{
left = p;
}
else if (right < p)
{
right = p;
}
}
t = (y1 - y2) / (y3 - 2 * y2 + y1);
if (0 <= t && t <= 1)
{
tp = 1 - t;
p = tp * tp * y1 + 2 * tp * t * y2 + t * t * y3;
if (p < top)
{
top = p;
}
else if (bottom < p)
{
bottom = p;
}
}
pointsX.push(left, right);
pointsY.push(bottom, top);
}
private function split(pos:Number):Boolean
{
if (pos === 0)
{
return false;
}
var coords0:Coords;
var coords1:Coords;
var index:uint = 0;
var pos0:Number;
var pos1:Number;
for (var i:int = 0, len:uint = coordsList.length; i < len; i++)
{
coords0 = coordsList[i];
coords1 = coordsList[i + 1];
if (coords0.pos === pos)
{
return false;
}
pos0 = coords0.pos;
pos1 = coords1 === null ? 1 : coords1.pos;
if (pos0 < pos && pos < pos1)
{
index = i;
break;
}
}
var t:Number = 1 - (pos1 - pos) / (pos1 - pos0);
var tp:Number = 1 - t;
var dx:Number = tp * coords0.sx + t * coords0.cx;
var dy:Number = tp * coords0.sy + t * coords0.cy;
var ex:Number = tp * coords0.cx + t * coords0.ax;
var ey:Number = tp * coords0.cy + t * coords0.ay;
var fx:Number = tp * tp * coords0.sx + 2 * tp * t * coords0.cx + t * t * coords0.ax;
var fy:Number = tp * tp * coords0.sy + 2 * tp * t * coords0.cy + t * t * coords0.ay;
var coords2:Coords = new Coords(fx, fy, ex, ey, coords0.ax, coords0.ay);
coords2.pos = pos;
coords0.cx = dx;
coords0.cy = dy;
coords0.ax = fx;
coords0.ay = fy;
coordsList.splice(index + 1, 0, coords2);
return true;
}
}
class Coords
{
public var ax:Number;
public var ay:Number;
public var cx:Number;
public var cy:Number;
public var length:Number;
public var pos:Number;
public var sx:Number;
public var sy:Number;
public function Coords(sx:Number, sy:Number, cx:Number, cy:Number, ax:Number, ay:Number)
{
this.sx = sx;
this.sy = sy;
this.cx = cx;
this.cy = cy;
this.ax = ax;
this.ay = ay;
length = computeLength();
}
public function clone():Coords
{
var coords:Coords = new Coords(sx, sy, cx, cy, ax, ay);
coords.pos = pos;
coords.length = length;
return coords;
}
private function computeLength():Number
{
var xa:Number = 2 * (sx - 2 * cx + ax);
var xb:Number = -2 * sx + 2 * cx;
var ya:Number = 2 * (sy - 2 * cy + ay);
var yb:Number = -2 * sy + 2 * cy;
var a:Number = xa * xa + ya * ya;
var b:Number = 2 * (xa * xb + ya * yb);
var c:Number = xb * xb + yb * yb;
if (b * b !== 4 * a * c)
{
return (2 * ((2 * a + b) * Math.sqrt(a * (a + b + c)) - b * Math.sqrt(a * c)) + (b * b - 4 * a * c) * Math.log((2 * Math.sqrt(a * c) + b) / (2 * (Math.sqrt(a * (a + b + c)) + a) + b))) / (8 *
a * Math.sqrt(a));
}
else if (a !== 0)
{
if (1 !== -b / (2 * a))
{
return (2 * ((2 * a + b) * Math.sqrt(a * (a + b + c)) - b * Math.sqrt(a * c))) / (8 * a * Math.sqrt(a));
}
return -b * Math.sqrt(c) / (4 * a);
}
return Math.sqrt(c);
}
}
class MorphingPath
{
private var _commands:Vector.<int>;
private var _data:Vector.<Number>;
private var _endData:Vector.<Number>;
private var _startData:Vector.<Number>;
public function MorphingPath(commands:Vector.<int>, startData:Vector.<Number>, endData:Vector.<Number>)
{
_startData = startData;
_endData = endData;
_commands = commands;
_data = new Vector.<Number>(_startData.length, true);
interpolate(0);
}
public function get commands():Vector.<int>
{
return _commands;
}
public function get data():Vector.<Number>
{
return _data;
}
public function interpolate(t:Number):void
{
var i:int, len:uint, start:Number;
for (i = 0, len = _startData.length; i < len; i++)
{
start = _startData[i];
_data[i] = start + (_endData[i] - start) * t;
}
}
}