На этом этапе мы портируем svg_displayinflash.as, который представляет собой код инициализации приложения.
Код состоит из двух функциональных частей: загрузка данных в SVG формате и отрисовка полученного пути. Загрузка данных - дело известное, начнем с этого. Добавим в класс SVGDisplayInFlash методы инициализации загрузки и обработчик полученных данных:
Код AS3:
private function getSVGData(url:String):void {
const loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onSVGLoaded);
loader.load(new URLRequest(url));
}
private function onSVGLoaded(event:Event):void {
const loader:URLLoader = event.target as URLLoader;
const data:String = loader.data as String;
const svg:XML = new XML(data);
trace(svg.toXMLString());
}
Обратите внимание на то, что мы можем немедленно протестировать загрузку данных, что и сделаем, добавив в initInstance вызов метода getSVGData, передав ему в качестве параметра url файла данных:
getSVGData(SVG_DATA_URL);
Если в результате компиляции не возникло проблем, то можем переходить к следующему шагу: портированию метода getShapes и процедуре его вызова.
Копируем и вставляем этот метод в класс SVGDisplayInFlash и видим, что FDT подсвечивает множество ошибок. Как это ни странно, но это очень хороший признак, что основная масса ошибок пришлась на последний этап портирования и говорит о правильно избранной стратегии действий. Сейчас у нас развязаны руки и мы можем вносить правки в код, не волнуясь о том, что это может чем-то навредить остальной части проекта. Однако мы не забываем, что на этом этапе наша задача - сделать код работоспособным с минимальными изменениями.
Копируем и вставляем объявления переменных, делаем их приватными. Если мы внимательны, то увидим, что переменная x будет конфликтовать со свойством мувиклипа, в котором мы ее объявили. Если мы невнимательны, то компилятор Flash об этом нам напомнит при первом же тесте.
Переименуем ее в svg:
Код AS3:
private var svg:XMLDocument = new XMLDocument();
private var conv:PathToArray;
private var paths:Array;
private var nPathNodes:Number;
Затем заменяем создание мувиклипа на добавление спрайта и получаем ссылку на объект graphics:
Код AS3:
// holder.createEmptyMovieClip("p"+iPath, iPath+1);
const drawLayer:Sprite = new Sprite();
holderMc.addChild(drawLayer);
const drawTarget:Graphics = drawLayer.graphics;
После этого заменяем все обращения holder["p"+iPath] на drawTarget.
Приступаем к портированию обработки загруженных данных. Пока мы можем пропустить обработку ошибок, поэтому просто переносим строки инициализации из оригинального метода xmlLoaded в метод onSVGLoaded:
Код AS3:
msg.text = "";
paths = x.firstChild.firstChild.childNodes;
nPathNodes = paths.length;
getShapes(0);
Заменяем msg на messageTxt и x на svg.
Добавляем парсинг полученных данных перед первым обращением к объекту svg:
Код AS3:
svg.ignoreWhite = true;
svg.parseXML(data);
Вот то, что в итоге должно было быть добавлено в класс:
Код AS3:
private var svg:XMLDocument = new XMLDocument();
svg.ignoreWhite = true;
private var conv:PathToArray;
private var paths:Array;
private var nPathNodes:Number;
private function onSVGLoaded(event:Event):void {
const loader:URLLoader = event.target as URLLoader;
const data:String = loader.data as String;
messageTxt.text = "";
svg.parseXML(data);
paths = svg.firstChild.firstChild.childNodes;
nPathNodes = paths.length;
getShapes(0);
}
private function getShapes(iPath:Number):void {
var dCmds:Array = new Array();
var d:Array;
var dp:Array;
conv = new PathToArray(paths[iPath], dCmds);
// draw the shapes in clips in holder movieclip
// holder.createEmptyMovieClip("p"+iPath, iPath+1);
const drawLayer:Sprite = new Sprite();
holderMc.addChild(drawLayer);
const drawTarget:Graphics = drawLayer.graphics;
for (var i:Number=0; i<dCmds.length; i++) {
d = dCmds[i];
dp = d[1];
switch (d[0]) {
case "F" :
drawTarget.beginFill(dp[0], dp[1]);
break;
case "S" :
drawTarget.lineStyle(dp[0], dp[1], dp[2]);
break;
case "M" :
drawTarget.moveTo(dp[0], dp[1]);
break;
case "L" :
drawTarget.lineTo(dp[0], dp[1]);
break;
case "C" :
drawTarget.curveTo(dp[0], dp[1], dp[2], dp[3]);
break;
}
}
// repeat til all paths have been read
if (++iPath < nPathNodes) getShapes(iPath);
}
Тестируем изменения. Если видим на экране попугая, то всё хорошо. Если нет, а вполне возможно что в ходе объяснений я что-то пропустил или был неточен, то для такого случая я приаттачу необходимые файлы.
Что же нам позволило даже не вникая в суть кода добиться успеха? Методология. Мы следовали простым принципам и в каждый момент делали только то, что соответствовало нашей стратегии:
- мы портировали код в строгом порядке: вначале портировались классы не использовавшие других пользовательских классов, только затем классы, использовавшие уже портированные классы, до тех пор, пока таким образом не закончили последний.
- мы не изменяли код без крайней на то необходимости и оставили это на самый последний момент.
- мы тестировали код при первой возможности.
Чего мы избегали:
- мы не пытались улучшить код, добавить недостающую типизацию, или изменить логику кода.
Мы оставили это для следующих этапов: рефакторинга и оптимизации.