キャラクターが声で天気予報を教えてくれるアプリを作る
Bing Maps上に今日の天気予報を表示する処理
新しいTextBlockのインスタンス、myDateTextBlockとmyTenkiTextBlockオブジェクトを作成します。また、新しいImageのインスタンスmyImageオブジェクトを作成します。
加えて、新しいTextBlockのインスタンス、maxTextBlockとminTextBlockオブジェクトを作成します。
メンバー変数myInfoCountに
新しいStackPanelのインスタンス、myTenkiStackPanelオブジェクトを作成します。
Marginに「5」を指定して余白を設けます。背景色に「Navy」を指定します。
myDataTextBlockの文字色は「Gold」、文字サイズは24、パディングは5と指定し、Textプロパティに、1ずつ増減するメンバー変数noに位置する
myImageオブジェクトのSourceプロパティに1ずつ増減するメンバー変数noに位置する
myTenkiTexBlockの文字色を「Red」とします。文字サイズには「22」を指定し、パディングに「5」、Widthに「300」と指定します。
Textプロパティには、1ずつ増減するメンバー変数noに位置する
myTenkStackPanelにAddメソッドで、myDateTextBlock、myTenkiTextBlock、myImageオブジェクトを追加します。
maxTextBlockオブジェクトの文字色を「Beige」、文字サイズを「22」、パディングを「5」、Widthを「300」と指定し、Textプロパティに、1ずつ増減するメンバー変数noに位置する
要素の全ての子孫要素である
minTextBlockの文字色を「Beige」とします。文字サイズを「22」、パディングを「5」、Widthに「300」と指定し、TextプロパティにtempResultの取得したノードのインデックスが0の値を指定します。変数lowTempにtempResult.Nodes(0).ToStringを格納しておきます。
キャラクターに喋らせる内容をreadingTenkiに指定します。
新しいButtonのインスタンスnextButtonオブジェクトを作成します。Contentプロパティに「次」と指定します。
メンバー変数noの値がmyInfoCount-1と等しいか大きかった場合は、nextButtonの使用を不可とします。それ以外は、使用を可とします。
新しいButtonのインスタンスprevButtonオブジェクトを作成します。Contentプロパティに「前」と指定します。
もしメンバー変数noの値が0ならprevButtonの使用を不可とします。それ以外は使用可とします。
新しいStackPanelのインスタンスButtonStackPanelオブジェクトを作成します。Orientationに「Horizontal」と指定します。ButtonStackPanelオブジェクトにAddメソッドでnextButtonとprevButtonオブジェクトを追加します。
新しいStackPanelのインスタンスsyokoStackPanelオブジェクトを作成します。Orientationには「Horizontal」と指定します。
新しいImageのインスタンスsyokoImageオブジェクトを作成します。Widthに「141」、Heightに「274」と指定し、Sourceプロパティにソリューション・アクスプロ—ラー内のImageフォルダにある「syoko1.png」を指定します。
syokoStackPanelにAddメソッドでsyokoImageオブジェクトを追加します。
AddHandlerステートメントで、syokoImageがタップされた時のイベントハンドラを追加します。
イベントハンドラ内では、syokoVoiceタスクを実行します。
myTenkiStackPanelオブジェクトにAddメソッドでmaxTextBlock、minTextBlock、ButtonStackPanelオブジェクトを追加します。
新しいStackPanelのインスタンス、resultStackPanelオブジェクトを作成します。Orientationには「Horizontal」を指定します。
resultStackPanelオブジェクトにAddメソッドで、myTenkiStackPanel、syokoStackPanelを追加します。
MapLayer.SetPositionで、指定した緯度と経度の位置にresultStackPanelオブジェクトをセットします。
myMapにAddメソッドでresultStackPanelオブジェクトを追加します。
これで、天気予報が表示された横にキャラクターの画像が表示されます。
AddHandlerステートメントでnextButtonがクリックされた時に、nextButton_Clickイベントハンドラを実行します。
AddHandlerステートメントでprevButtonがクリックされた時に、prevButton_Clickイベントハンドラを実行します。
天気予報をキャラクターが喋るsyokoVoiceタスクを実行します。
非同期処理で行われるため、メソッドの先頭にAsyncを追加します。
Private Async Function DataShow() As Task myDateTextBlock = New TextBlock myTenkiTextBlock = New TextBlock myImage = New Image maxTextBlock = New TextBlock minTextBlock = New TextBlock myInfoCount = query.Descendants("info").Count myTenkiStackPanel = New StackPanel myTenkiStackPanel.Children.Clear() myTenkiStackPanel.Margin = New Thickness(5) myTenkiStackPanel.Background = New SolidColorBrush(Colors.Navy) With myDateTextBlock .Foreground = New SolidColorBrush(Colors.Gold) .FontSize = 24 .Padding = New Thickness(5) .Text = query.Descendants("info")(no).Attribute("date").Value End With myImage.Stretch = Stretch.None myImage.Source = New BitmapImage(New Uri(query.Descendants("info")(no).Element("img").Value, UriKind.Absolute)) myTenkiTextBlock.Foreground = New SolidColorBrush(Colors.Red) myTenkiTextBlock.FontSize = 22 myTenkiTextBlock.Padding = New Thickness(5) myTenkiTextBlock.Width = 300 myTenkiTextBlock.TextWrapping = TextWrapping.Wrap myTenkiTextBlock.Text = "【天気】=" & query.Descendants("info")(no).Element("weather").Value myTenkiStackPanel.Children.Add(myDateTextBlock) myTenkiStackPanel.Children.Add(myTenkiTextBlock) myTenkiStackPanel.Children.Add(myImage) maxTextBlock.Foreground = New SolidColorBrush(Colors.Beige) maxTextBlock.FontSize = 22 maxTextBlock.Padding = New Thickness(5) maxTextBlock.Width = 300 maxTextBlock.TextWrapping = TextWrapping.Wrap maxTextBlock.Text = "【最高気温】=" & query.Descendants("info")(no).Element("temperature").Element("range").FirstNode.ToString & "度" Dim lowTemp As String = String.Empty For Each tempResult In query.Descendants("info")(no).Elements("temperature").Elements("range") minTextBlock.Foreground = New SolidColorBrush(Colors.Beige) minTextBlock.FontSize = 22 minTextBlock.Padding = New Thickness(5) minTextBlock.Width = 300 minTextBlock.TextWrapping = TextWrapping.Wrap minTextBlock.Text = "【最低気温】=" & tempResult.Nodes(0).ToString & "度" lowTemp = tempResult.Nodes(0).ToString Next readingTenki = areaData & "の" & myDateTextBlock.Text & "の天気予報。" & "天気は" & query.Descendants("info")(no).Element("weather").Value & "です。" & "最高気温は" & query.Descendants("info")(no).Element("temperature").Element("range").FirstNode.ToString & "度で" & "最低気温は" & lowTemp & "度です。" nextButton = New Button nextButton.Content = "次" If no >= myInfoCount - 1 Then nextButton.IsEnabled = False Else nextButton.IsEnabled = True End If prevButton = New Button prevButton.Content = "前" If no = 0 Then prevButton.IsEnabled = False Else prevButton.IsEnabled = True End If Dim ButtonStackPanel As New StackPanel ButtonStackPanel.Orientation = Orientation.Horizontal ButtonStackPanel.Children.Add(nextButton) ButtonStackPanel.Children.Add(prevButton) Dim syokoStackPanel As New StackPanel syokoStackPanel.Orientation = Orientation.Horizontal Dim syokoImage As New Image With syokoImage .Width = 141 .Height = 274 .Source = New BitmapImage(New Uri("ms-appx:///Image/syoko1.png", UriKind.Absolute)) .Stretch = Stretch.None End With syokoStackPanel.Children.Add(syokoImage) AddHandler syokoImage.Tapped, Async Sub() Await syokoVoice() End Sub myTenkiStackPanel.Children.Add(maxTextBlock) myTenkiStackPanel.Children.Add(minTextBlock) myTenkiStackPanel.Children.Add(ButtonStackPanel) Dim resultStackPanel As New StackPanel resultStackPanel.Orientation = Orientation.Horizontal resultStackPanel.Children.Add(myTenkiStackPanel) resultStackPanel.Children.Add(syokoStackPanel) MapLayer.SetPosition(resultStackPanel, New Location(CDbl(myLatitude), CDbl(myLongitude))) myMap.Children.Add(resultStackPanel) AddHandler nextButton.Click, AddressOf nextButton_Click AddHandler prevButton.Click, AddressOf prevButton_Click Await syokoVoice() End Function
[次]ボタンがタップされた時の処理
myTenkiStackPanelを表示状態にします。
メンバー変数noがmyInfoCount-1より小さかった場合は、メンバー変数noを1ずつ加算します。[前]ボタンの使用を可能にし、DataShowタスクを実行します。
そうでない場合は、[次]ボタンの使用を不可とし、[前]ボタンの使用を可とします。メンバー変数noをmyInfoCount-1で初期化します。処理を抜けます。
非同期処理で行われるため、メソッドの先頭にAsyncを追加します。
Private Async Sub nextButton_Click(sender As Object, e As RoutedEventArgs) myTenkiStackPanel.Visibility = Xaml.Visibility.Visible If no < myInfoCount - 1 Then no += 1 prevButton.IsEnabled = True Await DataShow() Else nextButton.IsEnabled = False prevButton.IsEnabled = True no = myInfoCount - 1 Exit Sub End If End Sub
[前]ボタンがタップされた時の処理
myTenkiStackPanelを表示状態にします。
メンバー変数noが0か0より小さかった場合は、noを0で初期化します。[前]ボタンの使用を不可とします。
それ以外は、メンバー変数noの値を1ずつ減少させます。[次]、[前]ボタンの使用を可とします。
DataShowタスクを実行して処理を抜けます。
Private Async Sub prevButton_Click(sender As Object, e As RoutedEventArgs) myTenkiStackPanel.Visibility = Xaml.Visibility.Visible If no <= 0 Then no = 0 prevButton.IsEnabled = False Else no -= 1 nextButton.IsEnabled = True prevButton.IsEnabled = True Await DataShow() Exit Sub End If End Sub
天気予報をキャラクターが音声で喋る処理
[次]、[前]ボタンを非表示にします。
MediaElement型のmyMedia変数を宣言し、MediaElement1で初期化しておきます。
音声機能へのアクセスを提供する、新しいSpeechSynthesizerのインスタンス、synthオブジェクトを作成します。
SynthesizeTextToStreamAsyncメソッドで、指定した文字列から、音声出力を非同期に生成します。
SetSourceメソッドで、指定されたストリームおよびMIME型を使用してSourceプロパティを設定します。Playメソッドで音声を再生します。
音声にどんな言語で、どのような声で喋らすかは、SpeechSynthesizerのVoiceプロパティで参照できます。下記のURLを参照してください。Japanese JA は性別が「Female」で、名前は「Haruka」という女性が読み上げるようです。
> SpeechSynthesizer.Voice | voice property
非同期処理で行われるため、メソッドの先頭にAsyncを追加します。
Private Async Function syokoVoice() As Task nextButton.Visibility = Xaml.Visibility.Collapsed prevButton.Visibility = Xaml.Visibility.Collapsed Dim myMedia As MediaElement = Me.MediaElement1 Dim synth = New Windows.Media.SpeechSynthesis.SpeechSynthesizer Dim stream = Await synth.SynthesizeTextToStreamAsync(readingTenki) myMedia.SetSource(stream, stream.ContentType) myMedia.Play() End Function
キャラクターが天気予報を喋り終わった時の処理
[次]、[前]ボタンを表示します。
Private Sub MediaElement1_MediaEnded(sender As Object, e As RoutedEventArgs) Handles MediaElement1.MediaEnded nextButton.Visibility = Xaml.Visibility.Visible prevButton.Visibility = Xaml.Visibility.Visible End Sub End Class
今回はここまでです。また次回の記事でお会いしましょう。
キャラクター音声天気予報アプリのサンプル
『Windows 8.1+Visual Studio 2013によるWindows ストア・アプリ開発実例集』 第8回のサンプルプログラムです。