2017-02-02 5 views
2

コンテキスト:従来のFlex/Actionscript描画アプリケーションでは、単純なシンボルのスケーリングを追加する必要があります。アプリは描画にGraffitiライブラリを使用し、結果の形状データは、GraphicsPathCommandsとして格納され、保存と再読み込みのためにDegrafaライブラリを使用してXMLにシリアル化されます。私は、ユーザーがこれらのグラフィックスを拡大縮小して、シリアル化できる更新されたパスデータを取得できるようにする必要があります。シンボルはシンプルですがシンプルなジオメトリより複雑です。たとえば、次のようにGraphicsPathCommandデータのスケール方法

enter image description here

質問:は、私は、ActionScript GraphicsPathCommandsに、このシンボルのSVGデータを変換し、それを描画することができるよ、もちろん翻訳は簡単です - しかし、私はどのように私は希望を知りませんユーザーがアプリケーション内のマーキーの矩形をドラッグすることで定義されたバウンディングボックスが与えられた場合、それを拡大縮小します。

Actionscriptコマンドデータを変換する方法、またはSVGのActionScriptに移植できるスケーリング用のJavaScriptスクリプトスニペットを知っている人はいますか?

参考のために、星を描くためのアクションスクリプトGraphicsPathCommandsの例を以下に示します。


public function DrawPathExample() 
    { 
     var star_commands:Vector.<int> = new Vector.<int>(5, true); 

     star_commands[0] = GraphicsPathCommand.MOVE_TO; 
     star_commands[1] = GraphicsPathCommand.LINE_TO; 
     star_commands[2] = GraphicsPathCommand.LINE_TO; 
     star_commands[3] = GraphicsPathCommand.LINE_TO; 
     star_commands[4] = GraphicsPathCommand.LINE_TO; 

     var star_coord:Vector.<Number> = new Vector.<Number>(10, true); 
     star_coord[0] = 66; //x 
     star_coord[1] = 10; //y 
     star_coord[2] = 23; 
     star_coord[3] = 127; 
     star_coord[4] = 122; 
     star_coord[5] = 50; 
     star_coord[6] = 10; 
     star_coord[7] = 49; 
     star_coord[8] = 109; 
     star_coord[9] = 127; 

     graphics.beginFill(0x003366); 
     graphics.drawPath(star_commands, star_coord); 
    } 

ソリューション

対話的GraphicsPathCommandデータをスケーリングするための完全なソリューションは、以下の通りです。パスデータは、SVGParserを介して置かれたSVGから派生したものです。 graphics.lineTo(28.4,16.8);の形式でパス描画コマンドを生成します。 2つのユーティリティ関数は、データをコマンドから分離し、データをシリアル化できるようにVectorsに格納します。私は任意のSWGを使う必要はないので、データをハードコードしただけです。

enter image description here

package classes 
{ 
    import flash.display.GraphicsPathCommand; 
    import flash.display.Shape; 
    import flash.display.Sprite; 
    import flash.events.Event; 
    import flash.events.MouseEvent; 
    import flash.geom.Point; 
    import flash.geom.Rectangle; 

    public class DrawSVG extends Sprite 
    { 
     private var startPt:Point = new Point(); 
     private var selectRect:Rectangle = new Rectangle(); 
     private var viewBox:Rectangle = new Rectangle(); 

     protected var commands:Vector.<int> = new Vector.<int>(); 
     protected var drawingData:Vector.<Number> = new Vector.<Number>(); 
     protected var sourceDrawingData:Vector.<Number> = new Vector.<Number>(); 

     public function DrawSVG() 
     { 
      super(); 
      this.addEventListener(Event.ADDED_TO_STAGE, setup); 
      setupWomanData(); 
     } 

     private function setup(event:Event):void 
     { 
      stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); 
     } 

     private function onMouseDown(event:MouseEvent):void 
     { 
      stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); 
      stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); 

      this.graphics.clear(); 

      // offset so graphic draws centered on click point 
      startPt = new Point(event.stageX - (viewBox.width /2), event.stageY - (viewBox.height /2)); 
      selectRect = new Rectangle(startPt.x, startPt.y, viewBox.width, viewBox.height); 

      var kx:Number = selectRect.width/(viewBox.width); 
      var ky:Number = selectRect.height/(viewBox.height); 
      var scaleFactor:Number = kx < ky ? kx : ky; 

      drawSymbol(scaleFactor); 

      this.graphics.lineStyle(1, 0x000000); 
      this.graphics.drawRect(selectRect.x, selectRect.y, selectRect.width, selectRect.height); 
     } 

     private function onMouseMove(event:MouseEvent):void 
     { 
      selectRect.width = Math.max(viewBox.width, Math.abs(event.stageX - startPt.x)); 
      selectRect.height = Math.max(viewBox.height, Math.abs(event.stageY - startPt.y)); 

      var kx:Number = selectRect.width/(viewBox.width); 
      var ky:Number = selectRect.height/(viewBox.height); 
      var scaleFactor:Number = kx < ky ? kx : ky; 

      this.graphics.clear(); 

      drawSymbol(scaleFactor); 

      this.graphics.lineStyle(1, 0x000000); 
      this.graphics.drawRect(selectRect.x, selectRect.y, viewBox.width * scaleFactor, viewBox.height * scaleFactor); 
     } 

     private function onMouseUp(event:MouseEvent):void 
     { 
      stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); 
      stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); 
      this.graphics.clear(); 
      createSprite(commands, drawingData); 
     } 

     private function drawSymbol(toScale:Number):void 
     { 
      drawingData.length = 0; 
      for (var i:int = 0; i < sourceDrawingData.length; i++) { 
       drawingData[i] = Math.max(sourceDrawingData[i], sourceDrawingData[i] * toScale); 
       drawingData[i] += i % 2 == 0 ? startPt.x : startPt.y ; 
      } 
      this.graphics.clear(); 
      this.graphics.lineStyle(); 
      this.graphics.beginFill(0xff0000); 
      this.graphics.drawPath(commands, drawingData); 
      this.graphics.endFill(); 
     } 

     private function createSprite(command:Vector.<int>, coord:Vector.<Number>):Shape{ 
      var s:Shape = new Shape(); 
      addChild(s); 
      s.graphics.beginFill(0xff); 
      s.graphics.drawPath(command, coord); 
      s.graphics.endFill(); 
      return s; 
     } 

     private function setupWomanData():void 
     { 
      commands = new Vector.<int>(); 
      drawingData = new Vector.<Number>(); 
      viewBox= new Rectangle(0, 0, 24.629, 52.336); 

      addMoveToCmd(12.31,10.3); 
      addCurveToCmd(13.37,10.3,14.3,9.89); 
      addCurveToCmd(15.24,9.48,15.94,8.78); 
      addCurveToCmd(16.64,8.08,17.05,7.14); 
      addCurveToCmd(17.46,6.2,17.46,5.15); 
      addCurveToCmd(17.46,4.1,17.05,3.16); 
      addCurveToCmd(16.64,2.23,15.94,1.52); 
      addCurveToCmd(15.24,0.82,14.3,0.41); 
      addCurveToCmd(13.37,0,12.31,0); 
      addCurveToCmd(11.26,0,10.33,0.41); 
      addCurveToCmd(9.39,0.82,8.69,1.52); 
      addCurveToCmd(7.98,2.23,7.57,3.16); 
      addCurveToCmd(7.16,4.1,7.16,5.15); 
      addCurveToCmd(7.16,6.2,7.57,7.14); 
      addCurveToCmd(7.98,8.08,8.69,8.78); 
      addCurveToCmd(9.39,9.48,10.33,9.89); 
      addCurveToCmd(11.26,10.3,12.31,10.3); 
      addLineToCmd(12.314,10.304); 

      addMoveToCmd(24.6,26.36); 
      addLineToCmd(20.7,12.77); 
      addCurveToCmd(20.62,12.3,20.39,11.91); 
      addCurveToCmd(20.15,11.51,19.81,11.23); 
      addCurveToCmd(19.47,10.94,19.04,10.78); 
      addCurveToCmd(18.61,10.62,18.14,10.62); 
      addLineToCmd(6.49,10.62); 
      addCurveToCmd(6.02,10.62,5.59,10.78); 
      addCurveToCmd(5.16,10.94,4.82,11.23); 
      addCurveToCmd(4.48,11.51,4.24,11.91); 
      addCurveToCmd(4.01,12.3,3.93,12.77); 
      addLineToCmd(0.03,26.36); 
      addCurveToCmd(0.01,26.4,0.01,26.45); 
      addCurveToCmd(-0.01,26.5,-0.01,26.55); 
      addCurveToCmd(0.01,26.6,0.01,26.65); 
      addCurveToCmd(0.02,26.69,0.03,26.74); 
      addCurveToCmd(-0.15,27.95,0.55,28.69); 
      addCurveToCmd(1.25,29.44,2.2,29.6); 
      addCurveToCmd(3.15,29.77,4.05,29.3); 
      addCurveToCmd(4.95,28.84,5.17,27.63); 
      addLineToCmd(6.85,21.37); 
      addLineToCmd(4.07,34.88); 
      addCurveToCmd(3.81,35.51,3.91,36.15); 
      addCurveToCmd(4,36.78,4.35,37.3); 
      addCurveToCmd(4.7,37.81,5.26,38.13); 
      addCurveToCmd(5.81,38.45,6.49,38.45); 
      addLineToCmd(6.78,38.45); 
      addLineToCmd(6.78,49.72); 
      addCurveToCmd(6.78,50.99,7.59,51.62); 
      addCurveToCmd(8.41,52.25,9.39,52.25); 
      addCurveToCmd(10.37,52.25,11.19,51.62); 
      addCurveToCmd(12,50.99,12,49.72); 
      addLineToCmd(12,38.45); 
      addLineToCmd(12.63,38.45); 
      addLineToCmd(12.63,49.72); 
      addCurveToCmd(12.63,50.99,13.44,51.62); 
      addCurveToCmd(14.26,52.25,15.24,52.25); 
      addCurveToCmd(16.22,52.25,17.04,51.62); 
      addCurveToCmd(17.85,50.99,17.85,49.72); 
      addLineToCmd(17.85,38.45); 
      addLineToCmd(18.14,38.45); 
      addCurveToCmd(18.82,38.45,19.38,38.13); 
      addCurveToCmd(19.93,37.81,20.28,37.3); 
      addCurveToCmd(20.63,36.78,20.72,36.14); 
      addCurveToCmd(20.81,35.51,20.56,34.87); 
      addLineToCmd(17.78,21.37); 
      addLineToCmd(19.45,27.58); 
      addCurveToCmd(19.67,28.79,20.57,29.27); 
      addCurveToCmd(21.47,29.75,22.43,29.6); 
      addCurveToCmd(23.38,29.45,24.08,28.7); 
      addCurveToCmd(24.78,27.96,24.6,26.74); 
      addCurveToCmd(24.61,26.69,24.62,26.65); 
      addCurveToCmd(24.63,26.6,24.63,26.55); 
      addCurveToCmd(24.63,26.5,24.62,26.45); 
      addCurveToCmd(24.62,26.4,24.6,26.36); 
      addLineToCmd(24.601,26.356); 
     } 


     protected function addCurveToCmd(p1:Number, p2:Number, p3:Number, p4:Number):void 
     { 
      commands.push(GraphicsPathCommand.CURVE_TO); 
      sourceDrawingData.push(p1); 
      sourceDrawingData.push(p2); 
      sourceDrawingData.push(p3); 
      sourceDrawingData.push(p4); 
     } 

     protected function addMoveToCmd(p1:Number, p2:Number):void 
     { 
      commands.push(GraphicsPathCommand.MOVE_TO); 
      sourceDrawingData.push(p1); 
      sourceDrawingData.push(p2); 
     } 

     protected function addLineToCmd(p1:Number, p2:Number):void 
     { 
      commands.push(GraphicsPathCommand.LINE_TO); 
      sourceDrawingData.push(p1); 
      sourceDrawingData.push(p2); 
     } 
    } 
} 

答えて

1

これを行うには非常に簡単な方法があるように思えます。スケールする唯一のものは座標そのものなので、スケールファクタを適用することができます。
例:

public function ASEntryPoint() { 
     var star_commands:Vector.<int> = new Vector.<int>(5, true); 

     star_commands[0] = GraphicsPathCommand.MOVE_TO; 
     star_commands[1] = GraphicsPathCommand.LINE_TO; 
     star_commands[2] = GraphicsPathCommand.LINE_TO; 
     star_commands[3] = GraphicsPathCommand.LINE_TO; 
     star_commands[4] = GraphicsPathCommand.LINE_TO; 

     var star_coord:Vector.<Number> = new Vector.<Number>(10, true); 
     star_coord[0] = 66; //x 
     star_coord[1] = 10; //y 
     star_coord[2] = 23; 
     star_coord[3] = 127; 
     star_coord[4] = 122; 
     star_coord[5] = 50; 
     star_coord[6] = 10; 
     star_coord[7] = 49; 
     star_coord[8] = 109; 
     star_coord[9] = 127; 

     //reference shape to detect initial size 
     var s:Shape = shapeInRect(star_commands, star_coord); 
     var bounds:Rectangle = s.getBounds(s); 
     s.graphics.lineStyle(1); 
     s.graphics.drawRect(bounds.x, bounds.y, bounds.width, bounds.height); 
     addChild(s); 

     //fit to target 
     var targetSize:Rectangle = new Rectangle(150, 100, 75, 60); 
     //detect lesser factor - assuming you need to preserve proportions 
     var kx:Number = targetSize.width/(bounds.width); 
     var ky:Number = targetSize.height/(bounds.height); 
     var toUse:Number = kx < ky ? kx : ky; 

     //apply to coords 
     for (var i:int = 0; i < star_coord.length; i++) { 
      //size 
      star_coord[i] *= toUse; 
      //fix initial offset 
      star_coord[i] -= i % 2 == 0 ? bounds.x * toUse : bounds.y * toUse; 
     } 
     //draw 
     addChild(shapeInRect(star_commands, star_coord, targetSize)); 
    } 

    private function shapeInRect(command:Vector.<int>, coord:Vector.<Number>, rect:Rectangle = null):Shape{ 
     var s:Shape = new Shape(); 
     addChild(s); 
     s.graphics.beginFill(0x003366); 
     s.graphics.drawPath(command, coord); 
     s.graphics.endFill(); 
     if (rect){ 
      s.graphics.lineStyle(1); 
      s.graphics.drawRect(0, 0, rect.width, rect.height); 
      s.x = rect.x; 
      s.y = rect.y; 
     } 
     return s; 
    } 
+0

ありがとうナッジ!それは働いた。 –

関連する問題