Silverlight Advent Calendar 2011 21日目の記事だよ! http://atnd.org/events/22001
Silverlight Advent Calendar 2011 3回目ですね!(やりすぎ
Silverlight 1.0って触ったことありますか?
その昔、SLはJavaScriptで開発してたんだよ。
XAMLなんてサクラエディタで手書きしてたんだよ。
なんていうと、 Σ(・ω・ノ)ノ!な人がわりといます。
C#でかけるようになったんだって2.0からやねんで!(ばんばん!
で、ですね。SL 2.0の頃にはHTML5なんてものはなく、JSで出来ることなんてちょっとしたアニメーションをjQueryでぽちぽちやったり、XMLHTTPRequest叩いたりしてたもんですよ。
HTML+JSでリッチとか。。。なんて言われてたころはSilverlightが銀色に光輝いていたものです(しみじみ。。
今となってはHTML5がどんどん力をつけてます。でもまだまだSilverlightの画面の作りやすさには敵いません。
そこで!SL 2.0の頃に培われたJSのちからを今こそ復活させましょう!
今回はSL2.0で実装されたHTML Bridgeを使ってHTML5のGeolocation APIを叩いて、その値をSL4で表示しました。
出来上がりはこんな感じです。
http://c-mitsuba.com/temp/HTML5Geo2SL/HTML5Geo2SLTestPage.html
まずはHTML5+JSで位置情報を取得しましょう。
<script type="text/javascript"> function showLocation(position) { var latitude = position.coords.latitude; var longitude = position.coords.longitude; alert("Latitude : " + latitude + " Longitude: " + longitude); } function errorHandler(err) { if(err.code == 1) { alert("Error: Access is denied!"); }else if( err.code == 2) { alert("Error: Position is unavailable!"); } } function getLocation(){ if(navigator.geolocation){ // timeout at 60000 milliseconds (60 seconds) var options = {timeout:60000}; navigator.geolocation.getCurrentPosition(showLocation, errorHandler, options); }else{ alert("Sorry, browser does not support geolocation!"); } } </script>
こんな感じのコードでgeoLocation()を実行すると、緯度経度が取れます。
ちょうどこのへんですね。
position.coords.latitude;
position.coords.longitude;
実際にTestPage.htmlは以下のように記述しました。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <title>HTML5Geo2SL</title> <style type="text/css"> html, body { height: 100%; overflow: auto; } body { padding: 0; margin: 0; } #silverlightControlHost { height: 100%; text-align:center; } </style> <script type="text/javascript" src="Silverlight.js"></script> <script type="text/javascript"> function onSilverlightError(sender, args) { var appSource = ""; if (sender != null && sender != 0) { appSource = sender.getHost().Source; } var errorType = args.ErrorType; var iErrorCode = args.ErrorCode; if (errorType == "ImageError" || errorType == "MediaError") { return; } var errMsg = "Silverlight アプリケーションのハンドルされないエラー " + appSource + "\n" ; errMsg += "コード: "+ iErrorCode + " \n"; errMsg += "カテゴリ: " + errorType + " \n"; errMsg += "メッセージ: " + args.ErrorMessage + " \n"; if (errorType == "ParserError") { errMsg += "ファイル: " + args.xamlFile + " \n"; errMsg += "行: " + args.lineNumber + " \n"; errMsg += "位置: " + args.charPosition + " \n"; } else if (errorType == "RuntimeError") { if (args.lineNumber != 0) { errMsg += "行: " + args.lineNumber + " \n"; errMsg += "位置: " + args.charPosition + " \n"; } errMsg += "メソッド名: " + args.methodName + " \n"; } throw new Error(errMsg); } function getLocationButton() { if (navigator.geolocation) { // timeout at 60000 milliseconds (60 seconds) var options = { timeout: 60000 }; navigator.geolocation.getCurrentPosition(showLocation, errorHandler, options); } else { alert("Sorry, browser does not support geolocation!"); } } function showLocation(position) { var latitude = position.coords.latitude; var longitude = position.coords.longitude; slControl = document.getElementById('SilverlightControl'); slControl.content.MySilverlightObject.HTML5Geolocation(latitude, longitude); //alert("Latitude : " + latitude + " Longitude: " + longitude); } function errorHandler(err) { if (err.code == 1) { alert("Error: Access is denied!"); } else if (err.code == 2) { alert("Error: Position is unavailable!"); } } </script> </head> <body> <div id='htmlControl'> <input id="Button1" type="button" value="HTML5による位置情報の取得" onclick="return getLocationButton()" /> </div> <form id="form1" runat="server" style="height:100%"> <div id="silverlightControlHost"> <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="50%" height="50%" id="SilverlightControl"> <param name="source" value="ClientBin/HTML5Geo2SL.xap"/> <param name="onError" value="onSilverlightError" /> <param name="background" value="white" /> <param name="minRuntimeVersion" value="4.0.60310.0" /> <param name="autoUpgrade" value="true" /> <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.60310.0" style="text-decoration:none"> <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Microsoft Silverlight の取得" style="border-style:none"/> </a> </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div> </form> </body> </html>
これだけだと位置情報を取得するボタンしかでないので、XAML書きますね。
せっかくなのでBing Mapも使いました。キーはとってないけど。
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=2949
まずは参照に
Microsoft.Maps.MapControl.Common.dll
Microsoft.Maps.MapControl.dll
を追加します。
で、MainPage.xaml
<UserControl x:Class="HTML5Geo2SL.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:Map="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid x:Name="LayoutRoot" Background="White"> <StackPanel Orientation="Vertical"> <StackPanel Orientation="Horizontal"> <TextBlock Text="Latitude:"/> <TextBlock x:Name="Latitude" Text="0"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="Longitude:"/> <TextBlock x:Name="Longitude" Text="0"/> </StackPanel> </StackPanel> <Map:Map x:Name="Map" d:LayoutOverrides="Width" Margin="0,36,0,0"> <Map:Pushpin x:Name="pin" ToolTipService.ToolTip="HTML5Geo" /> </Map:Map> </Grid> </UserControl>
で、MainPage.xaml.cs
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Browser; using Microsoft.Maps.MapControl; namespace HTML5Geo2SL { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Page_Loaded); } void Page_Loaded(object sender, RoutedEventArgs e) { //JSからSLアプリを参照できるように名前をつける HtmlPage.RegisterScriptableObject("MySilverlightObject", this); } //JSで実行できるメソッドを明言する [ScriptableMember] public void HTML5Geolocation(double Lat, double Lon) { Latitude.Text = Lat.ToString(); Longitude.Text = Lon.ToString(); //MessageBox.Show(Lon.ToString()); pin.Location = new Location(Lat, Lon); Map.Center = new Location(Lat, Lon); } } }
C#の以下と
HtmlPage.RegisterScriptableObject("MySilverlightObject", this);
以下は
public void HTML5Geolocation(double Lat, double Lon){}
JSの以下に紐づいています。
slControl.content.MySilverlightObject.HTML5Geolocation(latitude, longitude);
簡単ですね!
これでJSのボタンをクリックすると、HTML5で位置情報を取得し、取得した位置情報を引数にC#のコードをJSから実行して、SLのPushpinとMapを操作することができます。
出来上がりはこんなかんじ
ボタンを押すと、Locationとっていい?て聞かれます。
SLの作りやすさとHTML5の先進さを混ぜるとこんなこともできちゃうんですねー
いい感じに住み分けができるといいなー。
JSかわいいよJSヾ(>ヮ<)ノ゙