ニュース専用RSSリーダー(音声再生機能付き)
以前作成した【TTS(Text To Speech) powered by Google Translate)】を応用。
(@see http://wonderfl.net/c/q6VD)
{朝日新聞、読売新聞、毎日新聞}からニュースのRSSを取得し、自動再生させました。
再生中には、画面下部のオーディオ操作ボタンを何度も押さないことをオススメします・・・
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.utils.Timer;
[SWF(width = "465", height = "465", frameRate = "30", backgroundColor = "0xFFFFFF")]
public class Main extends Sprite {
private static const INTERAL:int = 10000;
private var _newsButton:NewsButton;
private var _message:TextField;
private var _speakerButton:SpeakerButton;
private var _article:Article;
private var _audioButton:AudioButton;
private var _index:int;
private var _timer:Timer;
private var _tts:TTS;
public function Main():void {
_article = new Article("");
_article.x = stage.stageWidth / 2;
_article.y = stage.stageHeight / 2;
addChild(_article);
_message = new TextField();
_message.autoSize = TextFieldAutoSize.LEFT;
_message.type = TextFieldType.DYNAMIC;
_message.defaultTextFormat = new TextFormat("_ゴシック", 12, 0xFF9900, true, false);
_message.multiline = false;
_message.selectable = false;
_message.wordWrap = false;
_message.text = "Please Select !!!";
_message.x = _article.x - _article.width / 2;
_message.y = _article.y - _article.height / 2 - _message.textHeight - 10;
addChild(_message);
_speakerButton = new SpeakerButton();
_speakerButton.x = _article.x + _article.width / 2;
_speakerButton.y = _message.y;
addChild(_speakerButton);
_newsButton = new NewsButton();
_newsButton.x = (stage.stageWidth - _newsButton.width) / 2;
_newsButton.y = _message.y - _newsButton.height - 10;
_newsButton.addEventListener(Event.SELECT, _selected);
addChild(_newsButton);
var labelNewsButton:TextField = new TextField();
labelNewsButton.autoSize = TextFieldAutoSize.LEFT;
labelNewsButton.type = TextFieldType.DYNAMIC;
labelNewsButton.defaultTextFormat = new TextFormat("_ゴシック", 15, 0x000000, true, false);
labelNewsButton.multiline = false;
labelNewsButton.selectable = false;
labelNewsButton.wordWrap = false;
labelNewsButton.text = "以下のニュースサイトからRSSを取得するよ~";
labelNewsButton.x = _newsButton.x;
labelNewsButton.y = _newsButton.y - labelNewsButton.textHeight - 10;
addChild(labelNewsButton);
_audioButton = new AudioButton(this);
_audioButton.x = (stage.stageWidth - _audioButton.width) / 2;
_audioButton.y = _article.y + _article.height / 2 + 10;
addChild(_audioButton);
_timer = new Timer(INTERAL);
_timer.addEventListener(TimerEvent.TIMER, _autoPlay);
XmlLoader.instance.addEventListener(Event.COMPLETE, _completed);
}
private function _selected(e:Event = null):void {
_newsButton.enabled = false;
_timer.reset();
_message.text = "Now Loading ... ";
XmlLoader.instance.load(_newsButton.site);
}
private function _completed(e:Event = null):void {
_index = 0;
setArticle(0);
_newsButton.enabled = true;
_timer.start();
_message.text = "[自動生成]";
}
private function get isLoaded():Boolean {
if (XmlLoader.instance.entries.length > 0) {
return true;
}
_message.text = "Please Select !!!";
return false;
}
private function _autoPlay(e:TimerEvent = null):void {
setArticle(1);
}
public function set auto(flag:Boolean):void {
if (!isLoaded) {
return;
}
if (flag) {
_timer.start();
_message.text = "[自動生成]";
} else {
_timer.stop();
_message.text = "[手動生成]";
}
}
public function setArticle(offset:int):void {
if (isLoaded) {
_index += offset;
if (_index == -1) {
_index = XmlLoader.instance.entries.length - 1;
}
if (_index == XmlLoader.instance.entries.length) {
_index = 0;
}
if (_article) {
removeChild(_article);
}
var entry:Entry = XmlLoader.instance.entries[_index];
if (_speakerButton.on) {
_tts = new TTS();
_tts.play(entry.title);
}
_article = new Article(entry.title + " [" + entry.date + "]", entry.url);
_article.x = stage.stageWidth / 2;
_article.y = stage.stageHeight / 2;
addChild(_article);
}
}
}
}
import com.bit101.components.RadioButton;
import com.bit101.components.Style;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
class NewsButton extends Sprite {
private static const WIDTH:int = 120;
private static const HEIGHT:int = 30;
private static const PADDING:int = 10;
private static const SPACING:int = 5;
private static const FILTER:DropShadowFilter = new DropShadowFilter(4, 45, 0x0066FF, 0.3);
private var _asahi:RadioButton;
private var _yomiuri:RadioButton;
private var _mainichi:RadioButton;
private var _site:String = null;
public function NewsButton():void {
Style.fontSize = 12;
Style.BACKGROUND = 0xFEFEFE;
Style.BUTTON_FACE = 0x0099FF;
var pane:Sprite = new Sprite();
_asahi = new RadioButton(pane, 0, 0, "asahi.com", false, _selected);
_asahi.name = "asahi";
_asahi.filters = [FILTER];
_asahi.setSize(WIDTH, HEIGHT);
_asahi.x = PADDING;
_asahi.y = PADDING;
_yomiuri = new RadioButton(pane, 0, 0, "yomiuri online", false, _selected);
_yomiuri.name = "yomiuri";
_yomiuri.filters = [FILTER];
_yomiuri.setSize(WIDTH, HEIGHT);
_yomiuri.x = _asahi.x + WIDTH + SPACING;
_yomiuri.y = PADDING;
_mainichi = new RadioButton(pane, 0, 0, "mainichi.jp", false, _selected);
_mainichi.name = "mainichi";
_mainichi.filters = [FILTER];
_mainichi.setSize(WIDTH, HEIGHT);
_mainichi.x = _yomiuri.x + WIDTH + SPACING;
_mainichi.y = PADDING;
pane.graphics.lineStyle(1.0, 0x000000, 1.0);
pane.graphics.drawRoundRect(0, 0, PADDING * 2 + WIDTH * 3 + SPACING * 2, HEIGHT + PADDING, 10, 10);
addChild(pane);
}
private function _selected(e:MouseEvent):void {
var source:RadioButton = e.target as RadioButton;
if (_site != source.name) {
_site = source.name;
dispatchEvent(new Event(Event.SELECT));
}
}
public function get site():String {
return _site;
}
public function set enabled(flag:Boolean):void {
_asahi.enabled = flag;
_yomiuri.enabled = flag;
_mainichi.enabled = flag;
}
}
import flash.display.GraphicsPathCommand;
import flash.display.GraphicsPathWinding;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
class SpeakerButton extends Sprite {
private var _mask:Shape;
private var _on:Boolean;
public function SpeakerButton():void {
buttonMode = true;
mouseEnabled = true;
useHandCursor = true;
addChild(_createBase());
addChild((_mask = _createMask()));
_mask.alpha = 0.0;
_on = true;
addEventListener(MouseEvent.CLICK, _clicked);
}
private function _createBase():Shape {
var commands:Vector.<int> = new Vector.<int>();
commands.push(GraphicsPathCommand.MOVE_TO);
commands.push(GraphicsPathCommand.LINE_TO);
commands.push(GraphicsPathCommand.LINE_TO);
commands.push(GraphicsPathCommand.LINE_TO);
commands.push(GraphicsPathCommand.LINE_TO);
commands.push(GraphicsPathCommand.LINE_TO);
commands.push(GraphicsPathCommand.LINE_TO);
commands.push(GraphicsPathCommand.MOVE_TO);
commands.push(GraphicsPathCommand.CURVE_TO);
commands.push(GraphicsPathCommand.MOVE_TO);
commands.push(GraphicsPathCommand.CURVE_TO);
commands.push(GraphicsPathCommand.MOVE_TO);
commands.push(GraphicsPathCommand.CURVE_TO);
var data:Vector.<Number> = new Vector.<Number>();
data.push(0, 5);
data.push(5, 5);
data.push(10, 0);
data.push(10, 15);
data.push(5, 10);
data.push(0, 10);
data.push(0, 5);
data.push(12, 5);
data.push(13, 7);
data.push(12, 10);
data.push(14, 2);
data.push(16, 7);
data.push(14, 12);
data.push(16, 0);
data.push(19, 7);
data.push(16, 15);
var shape:Shape = new Shape();
shape.graphics.lineStyle(0.5, 0x000000, 1.0);
shape.graphics.beginFill(0xDEDEDE);
shape.graphics.drawPath(commands, data, GraphicsPathWinding.EVEN_ODD);
shape.graphics.endFill();
return shape;
}
private function _createMask():Shape {
var commands:Vector.<int> = new Vector.<int>();
commands.push(GraphicsPathCommand.MOVE_TO);
commands.push(GraphicsPathCommand.LINE_TO);
commands.push(GraphicsPathCommand.MOVE_TO);
commands.push(GraphicsPathCommand.LINE_TO);
var data:Vector.<Number> = new Vector.<Number>();
data.push(0, 0);
data.push(20, 15);
data.push(20, 0);
data.push(0, 15);
var shape:Shape = new Shape();
shape.graphics.lineStyle(2.0, 0xFF0000, 1.0);
shape.graphics.beginFill(0xDEDEDE);
shape.graphics.drawPath(commands, data, GraphicsPathWinding.EVEN_ODD);
shape.graphics.endFill();
shape.filters = [new DropShadowFilter(4, 90)];
return shape;
}
private function _clicked(e:MouseEvent):void {
if (_mask.alpha == 0.0) {
_mask.alpha = 1.0;
_on = false;
} else {
_mask.alpha = 0.0;
_on = true;
}
}
public function get on():Boolean {
return _on;
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.net.navigateToURL;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFieldType;
import flash.text.TextFormat;
class Article extends Sprite {
private static const WIDTH:int = 200;
private static const HEIGHT:int = 120;
private static const PADDING:int = 10;
private static const FORMAT:TextFormat = new TextFormat("_ゴシック", 16, 0x000000, true, false);
public function Article(text:String, url:String = null):void {
var tf:TextField = _createTextField(text);
var bd:BitmapData = new BitmapData(tf.width, tf.height, true, 0x0);
bd.draw(tf);
var bitmap:Bitmap = new Bitmap(bd, "auto", true);
bitmap.smoothing = true;
bitmap.x = bitmap.y = PADDING;
var frame:Sprite = new Sprite();
frame.graphics.lineStyle(2.0, 0x000000);
frame.graphics.beginFill(0xDEDEDE, 0.5);
frame.graphics.drawRoundRect(0, 0, WIDTH + PADDING * 2, HEIGHT + PADDING * 2, PADDING, PADDING);
frame.graphics.endFill();
frame.addChild(bitmap);
frame.x = -frame.width / 2;
frame.y = -frame.height / 2;
frame.doubleClickEnabled = true;
addChild(frame);
buttonMode = true;
mouseEnabled = true;
useHandCursor = true;
doubleClickEnabled = true;
addEventListener(MouseEvent.DOUBLE_CLICK, function(e:MouseEvent):void {
if (url) {
navigateToURL(new URLRequest(url), "_blank");
}
});
}
private function _createTextField(text:String):TextField {
var tf:TextField = new TextField();
tf.width = WIDTH;
tf.height = HEIGHT;
tf.autoSize = TextFieldAutoSize.LEFT;
tf.type = TextFieldType.DYNAMIC;
tf.defaultTextFormat = FORMAT;
tf.multiline = true;
tf.selectable = false;
tf.wordWrap = true;
tf.text = text;
return tf;
}
}
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
class AudioButton extends Sprite {
public function AudioButton(main:Main):void {
var play:Shape = new Shape();
play.graphics.lineStyle(1.0, 0x000000, 1.0);
play.graphics.beginFill(0xDEDEDE, 1.0);
play.graphics.drawCircle(40, 40, 40);
play.graphics.beginFill(0x000000, 1.0);
play.graphics.drawTriangles(Vector.<Number>([20, 20, 20, 60, 60, 40]));
play.graphics.endFill();
var playButton:Sprite = new Sprite();
playButton.addChild(play);
playButton.buttonMode = true;
playButton.mouseEnabled = true;
playButton.useHandCursor = true;
playButton.filters = [new DropShadowFilter()];
playButton.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void { main.auto = true; } );
addChild(playButton);
var stop:Shape = new Shape();
stop.graphics.lineStyle(1.0, 0x000000, 1.0);
stop.graphics.beginFill(0xDEDEDE, 1.0);
stop.graphics.drawCircle(30, 30, 30);
stop.graphics.beginFill(0x000000, 1.0);
stop.graphics.drawRect(20, 15, 5, 30);
stop.graphics.drawRect(35, 15, 5, 30);
stop.graphics.endFill();
var stopButton:Sprite = new Sprite();
stopButton.addChild(stop);
stopButton.buttonMode = true;
stopButton.mouseEnabled = true;
stopButton.useHandCursor = true;
stopButton.filters = [new DropShadowFilter()];
stopButton.x = 90;
stopButton.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void { main.auto = false; } );
addChild(stopButton);
var prev:Shape = new Shape();
prev.graphics.lineStyle(1.0, 0x000000, 1.0);
prev.graphics.beginFill(0xDEDEDE, 1.0);
prev.graphics.drawCircle(30, 30, 30);
prev.graphics.beginFill(0x000000, 1.0);
prev.graphics.drawTriangles(Vector.<Number>([45, 45, 45, 15, 15, 30]));
prev.graphics.drawRect(15, 15, 5, 30);
prev.graphics.endFill();
var prevButton:Sprite = new Sprite();
prevButton.addChild(prev);
prevButton.buttonMode = true;
prevButton.mouseEnabled = true;
prevButton.useHandCursor = true;
prevButton.filters = [new DropShadowFilter()];
prevButton.x = 160;
prevButton.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void { main.auto = false; main.setArticle( -1); } );
addChild(prevButton);
var next:Shape = new Shape();
next.graphics.lineStyle(1.0, 0x000000, 1.0);
next.graphics.beginFill(0xDEDEDE, 1.0);
next.graphics.drawCircle(30, 30, 30);
next.graphics.beginFill(0x000000, 1.0);
next.graphics.drawTriangles(Vector.<Number>([15, 15, 15, 45, 45, 30]));
next.graphics.drawRect(40, 15, 5, 30);
next.graphics.endFill();
var nextButton:Sprite = new Sprite();
nextButton.addChild(next);
nextButton.buttonMode = true;
nextButton.mouseEnabled = true;
nextButton.useHandCursor = true;
nextButton.filters = [new DropShadowFilter()];
nextButton.x = 230;
nextButton.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void { main.auto = false; main.setArticle(1); } );
addChild(nextButton);
}
}
class Entry {
private var _title:String;
private var _url:String;
private var _date:String;
public function Entry():void {
}
public function get title():String {
return this._title;
}
public function set title(title:String):void {
this._title = title;
}
public function get url():String {
return this._url;
}
public function set url(url:String):void {
this._url = url;
}
public function get date():String {
return this._date;
}
public function set date(date:String):void {
this._date = date;
}
public function toString():String {
return "[" + this._date + "] " + this._title + " (" + this._url + ")";
}
}
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.URLLoader;
import flash.net.URLRequest;
class XmlLoader extends EventDispatcher {
private static var _instance:XmlLoader = null;
public function XmlLoader():void {
}
public static function get instance():XmlLoader {
if (XmlLoader._instance == null) {
XmlLoader._instance = new XmlLoader();
}
return XmlLoader._instance;
}
private static const URL:String = "http://service-maker.appspot.com/rss/?site=";
private var _entries:Array = new Array();
public function load(site:String):void {
var _xmlloader:URLLoader = new URLLoader();
_xmlloader.addEventListener(Event.COMPLETE, onLoaded);
_xmlloader.load(new URLRequest(URL + site));
}
private function onLoaded(e:Event):void {
var xml:XML = new XML(e.target.data);
this._entries = new Array();
for each (var news:XML in xml.entries.entry) {
var entry:Entry = new Entry();
entry.title = news.title;
entry.url = news.link;
entry.date = news.date;
this._entries.push(entry);
}
dispatchEvent(new Event(Event.COMPLETE));
}
public function get entries():Array {
return this._entries;
}
}
import flash.events.Event;
import flash.media.Sound;
import flash.net.URLRequest;
class TTS {
private var _sound:Sound;
public function TTS():void {
_sound = new Sound();
_sound.addEventListener(Event.COMPLETE, _completed);
}
public function play(text:String):void {
_sound.load(new URLRequest("http://service-maker2.appspot.com/tts?text=" + encodeURI(text)));
}
private function _completed(e:Event):void {
Sound(e.target).play();
}
}