ブラウザでダウンロード めくりながら、一文字づつ表示されて行きます。 作った本人が言うのもなんですが、風情がありますね・・・・ テキストはページ毎にサーバに用意します。 ページ数や、表示速度やフォントサイズの変更はビルドする必要があります。 もうちょっと頑張れば汎用的になると思います。 ( 誰かやって・・ ) ↓実行リンク ソースコード先にページをめくっても、ページを書き終わってからめくらないと前へすすみません。 左右のページが開いている場合は、右から左へイベントが進みます。 メインのパラメータは以下ですが、実際はソースコードの 微調整が必要になって来るでしょう。 private var charTime:int = 100; 1文字1文字の描画のタイマー間隔です private var size:int = 14; 文字のフォントサイズ ( あまり大きいと美しく無いです ) ソースは凝った事をせずに、ベタな書き方をしていますが、 このほうが誰でもコードを追えるはずです。 というか、Flex で凝った事すると、絶対痛い目にあいます。 それでなくとも、非同期です。 タイマーが描画遅れに追いついて文字が消えた時は目が点になりました・・・ <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:rs="com.rubenswieringa.book.*" initialize="initData();" layout="absolute" > <mx:Style> Application { backgroundGradientColors: 9737053,0 } </mx:Style> <mx:Script> <![CDATA[ import com.rubenswieringa.book.*; import mx.controls.*; import mx.events.*; import mx.rpc.events.*; import mx.formatters.*; import flash.external.*; // ページ数 private var numPage:int = 6; // [Bindable] private var canvasWidth:int = 400; [Bindable] private var canvasHeight:int = 530; // タイマー // あまり速くするとタイマーが追いついて文字が飛んでしまいます private var myTimer:Timer = new Timer(1000); // この時間はダミー private var charTime:int = 100; // 文字描画間隔 private var endTimer:Timer = new Timer(1000); // Label用ワーク変数 private var ch:Label = null; // フォントサイズ private var size:int = 14; private var fk:Number = 1.0; // 横のマス数 private var a:int = 0; // 縦のマス数 private var b:int = 0; // カウンタ private var i:int = 0; private var seq:int = 0; // 文字マスとしての座標 private var xm:int = 0; private var ym:int = 0; // 実際の座標 private var xl:int = 0; private var yl:int = 0; private var bmp:BitmapData = null; // 書き込み済みのページ番号 private var writingPage:int = 0; private var cvsWork:Canvas; private var str:String; // ********************************************************* // アプリケーションの初期化 // ********************************************************* public function initData():void { fk = Math.round( size / 14 ); // 横のマス数 a = ( canvasWidth - 10 ) / ( size + 2 ); // 縦のマス数 b = ( canvasHeight - 10 ) / ( size + 2 ) - 1; // カウンタ初期化 i = 1; seq = 0; // 効果 myFade1.play(); myTimer.addEventListener("timer", drawChar); endTimer.addEventListener("timer", endAction); } // ***************************************************** // ページをめくると文章が書かれます // ***************************************************** private function drawAction(eventPage:BookEvent):void { var pageId:String = eventPage.page.id; switch( pageId ) { case "pg0": if ( writingPage == 0 ) { writingPage = 1; cvsWork = cvs1; bmp = new BitmapData(canvasWidth, canvasHeight,true,0); myTimer.delay = 400; // 文字描画開始までの待ち時間 sendAction(); } break; case "pg2": if ( writingPage == 2 && i == 1 ) { writingPage = 3; cvsWork = cvs3; bmp = new BitmapData(canvasWidth, canvasHeight,true,0); myTimer.delay = 400; // 文字描画開始までの待ち時間 sendAction(); } break; case "pg4": if ( writingPage == 4 && i == 1 ) { writingPage = 5; cvsWork = cvs5; bmp = new BitmapData(canvasWidth, canvasHeight,true,0); myTimer.delay = 400; // 文字描画開始までの待ち時間 sendAction(); } break; } } // ***************************************************** // 最後の処理 // ***************************************************** private function endAction(event:TimerEvent):void { endTimer.stop(); } // ***************************************************** // 1文字づつの書き込み // ***************************************************** private function drawChar(event:TimerEvent):void { if ( i > str.length ) { drawCanvas( cvsWork ); myTimer.stop(); // 最後の処理 if ( writingPage == 5 ) { endTimer.start(); } i = 1; seq = 0; switch( writingPage ) { case 1: writingPage = 2; cvsWork = cvs2; bmp = new BitmapData(canvasWidth, canvasHeight,true,0); sendAction(); break; case 3: writingPage = 4; cvsWork = cvs4; bmp = new BitmapData(canvasWidth, canvasHeight,true,0); sendAction(); break; } return; } // 30 回に一回背景に書き込んで、Label を削除する if ( i % 30 == 0 ) { drawCanvas( cvsWork ); } // 以下、1文字づつの書き込み seq++; if ( i == 1 ) { myTimer.delay = charTime; seq++; } if ( str.charAt( i-1 ) == "\n" ) { seq += b-((seq-1)%b); } xm = a - Math.floor( (seq-1) / b ) - 1; ym = (seq-1) % b; xl = xm * (size + 2); yl = ym * (size + 2)+4; var tc:String = str.charAt( i-1 ); var fs:String = size.toString(); switch( tc ) { case 'ー': case '−': case '-': tc = "|"; fs = (size - 1).toString(); xl += Math.round(fk * 1); break; case "。": xl += Math.round(fk * 5); yl -= Math.round(fk * 8); break; case "、": xl += Math.round(fk * 7); yl -= Math.round(fk * 8); break; case 'ぁ': case 'ぅ': case 'ぇ': case 'ぉ': case 'ゃ': case 'ゅ': case 'ょ': case 'っ': case 'ァ': case 'ゥ': case 'ェ': case 'ォ': case 'ャ': case 'ュ': case 'ョ': case 'ッ': xl += Math.round(fk * 3); yl -= Math.round(fk * 2); break; case "「": xl -= Math.round(fk * 9); yl += Math.round(fk * 6); break; case "」": xl += Math.round(fk * 8); yl -= Math.round(fk * 5); break; } ch = new Label(); ch.text = tc; ch.x = xl; ch.y = yl; ch.setStyle("textAlign", "center"); ch.setStyle("fontSize", fs); cvsWork.addChild( ch ); i++; } // ***************************************************** // 10文字毎の、背景への転送 // ***************************************************** private function drawCanvas(target:Canvas):void { // 自分自身の背景に(Labelを含めた)全体を上書きする bmp.draw(target,null,null,"normal"); target.graphics.clear(); target.graphics.beginBitmapFill(bmp); target.graphics.drawRect(0, 0, canvasWidth, canvasHeight); target.graphics.endFill(); target.removeAllChildren(); } // ***************************************************** // ページの本文取得 // ***************************************************** private function sendAction():void { httpService.url = "response" + writingPage + ".txt"; httpService.send(); } // ***************************************************** // タイマー書き込み開始 // ***************************************************** private function actResult(event:ResultEvent):void{ str = event.result.toString(); myTimer.start(); } private function actFault(event:FaultEvent):void{ Alert.show(event.message.toString()); } ]]> </mx:Script> <mx:HTTPService id="httpService" method="GET" result="actResult(event)" fault="actFault(event)" resultFormat="text" /> <rs:Book id="myBook" x="{Math.round(Application.application.width/2-400)}" y="30" width="800" height="530" openAt="5" autoFlipDuration="600" easing="0.7" regionSize="150" sideFlip="true" hardCover="true" hover="true" snap="false" flipOnClick="true" pageTurned="drawAction(event)" > <rs:Page backgroundColor="0xFFFFFF" backgroundAlpha="1" id="pg5"> <mx:Image source="@Embed('p5.jpg')" alpha="0.4" /> <mx:Canvas id="cvs5" width="{canvasWidth}" height="{canvasHeight}" textAlign="left" > </mx:Canvas> </rs:Page> <rs:Page backgroundColor="0xD9D6B6" backgroundAlpha="0.93" id="pg4"> <mx:Canvas id="cvs4" width="{canvasWidth}" height="{canvasHeight}" textAlign="left" > </mx:Canvas> </rs:Page> <rs:Page backgroundColor="0xD9D6B6" backgroundAlpha="0.93" id="pg3"> <mx:Canvas id="cvs3" width="{canvasWidth}" height="{canvasHeight}" textAlign="left" > </mx:Canvas> </rs:Page> <rs:Page backgroundColor="0xD9D6B6" backgroundAlpha="0.93" id="pg2"> <mx:Canvas id="cvs2" width="{canvasWidth}" height="{canvasHeight}" textAlign="left" > </mx:Canvas> </rs:Page> <rs:Page backgroundColor="0xD9D6B6" backgroundAlpha="0.93" id="pg1"> <mx:Canvas id="cvs1" width="{canvasWidth}" height="{canvasHeight}" textAlign="left" > </mx:Canvas> </rs:Page> <rs:Page backgroundColor="0xFFFFFF" backgroundAlpha="1" id="pg0"> <mx:Image id="p0" source="@Embed('p0.jpg')" alpha="0.4" /> <mx:Image id="title" x="{Math.round((400-title.width)/2)}" y="{Math.round((530-title.height)/2)}" source="@Embed('title.png')" /> </rs:Page> </rs:Book> <mx:Fade id="myFade1" target="{title}" duration="3000" alphaFrom="0" alphaTo="1" /> </mx:Application> 先頭ページのデータ
今は昔、竹取の翁といふ者ありけり。 野山にまじりて竹を取りつつ、よろづのことに 使ひけり。 名をば、さぬきの造となむいひける。 その竹の中に、もと光る竹なむ一筋ありける。 怪しがりて、寄りて見るに、筒の中光りたり。 それを見れば、三寸ばかりなる人、いとうつくしうてゐたり。 翁、言ふやう、 「我、朝ごと夕ごとに見る竹の中におはするにて、知りぬ」 「子となり給ふべき人なめり」 とて、手にうち入れて、家へ持ちて来ぬ。 妻の嫗に預けて養はす。 うつくしきこと限りなし。 いと幼ければ籠に入れて養ふ。 「 とか 」は、既存の文字使っているので、向きが逆です。 実際は画像を作って使う必要があります。 文字によっては、中央がズレるのがあるので微調整するべきですが・・・ デザインは専門では無いので、あんまり手をつけなかったのですが、 画像や Flash のテクニックはなんでもありのはずですね。 ( タイトルだけフェードインしましたけど ) |