ASP.NET の ListView のアイテム内に表示された画像を jQuery でエフェクトしてみる
jQuery を使ってみようと思ったきっかけ
私は趣味で ASP.NET を使っている。趣味で ASP.NET をどう使うんだ?と不思議に思うところもあるかもしれないが、ホームシアター用の動画管理Webアプリ「MovieJukeBox」を作成するということで、2年前から ASP.NET を使い始めた。42歳のことである。言語は VB。C# にも挑戦したいけどちょっと難しいそうなので、VBオンリーでやってる。jQuery は JavaScript の便利なサンプルをまとめたライブラリらしい?けど、私は JavaScript のコーディングは、ほぼ未経験。
ASP.NET には MVC とかいうのもあるらしく、2014年の今、こうして ASP.NET の Webフォームでアプリを作ろうというのは、世間の状況からすると周回遅れ、いや10週遅れみたいなものらしい。5年前の2009年には、@ITで「ASP.NETプログラマーのためのjQuery入門」の連載が開始されている。
個人で利用する MovieJukeBox で、パフォーマンスに不満はない。新しいOS(Windows 8.1 Update)、新しいブラウザ(Internet Explorer 11)でもちゃんと動く。IIS8.5、.NET4.5でも動く。10週遅れだろうが、100周遅れだろうが、現時点では、まだ切り捨てられていないので、開発・手直しできる環境だ。
ただ、そうは言っても、jQuery でインタラクティブなページとかの記事を目にすると気になる。気にしないふりをしても気になる。
ということで、ASP.NET VB Webフォーム で jQuery を使用し、インタラクティブなページ作成の勉強をしようと思った。
あ、Webフォーム で jQuery 使うくらいなら、ASP.NET MVC + jQuery やれということかもしれないが、ASP.NET MVC わからんので、今はパス。
まずはWebフォームで jQuery を使って画像を拡大してみる
jQuery のライブラリ入手とWebサイトへの配置
jQueryのライブラリはこの記事を書いてる時点で最新の「2.1.1」を使用。下記からダウンロードし、フォルダ「Scripts」を作成し、そこへ jquery-2.1.1.min.js を配置した。
(入手先)
Download jQuery | jQuery
http://jquery.com/download/
内容
- id が div1 の div に asp:image の画像と img の画像を配置。両画像とも Class を imagePoster とした。
- id が div2 の div に asp:image の画像と img の画像を配置。両画像とも Class を imagePoster とした。
- div1 には aspx に静的に埋め込んだスクリプトを割り当てる
id が div1 の div 内の Class に imagePoster が割り当てられているimgタグにのみ、jQuery の animate を使って、3秒間で画像を300x400に拡大する。
スクリプトは画像よりも後ろに埋め込まないと、エフェクトが適用されないので注意。 - div2 には vb から ClientScript.RegisterStartupScript を使って動的に埋め込んだスクリプトを割り当てる。ClientScript.RegisterStartupScript でスクリプトを埋め込むと画像よりも後ろにある、</form>の直前にスクリプトが埋め込まれるのでエフェクトが適用される。
ClientScript.RegisterClientScriptBlock だと、画像よりも前にある<form>の直後にスクリプトが生成されてしまい、エフェクトが適用されないので使用しない。
w(幅)、h(高さ)、s(エフェクトスピード)の3つをテキストボックスから取得し、動的にスクリプトに埋め込む。
(参考)
@IT:.NET TIPS [ASP.NET]ページにJavaScriptを埋め込むには? - C# VB.NET Webフォーム
http://www.atmarkit.co.jp/fdotnet/dotnettips/160regscript/regscript.html
結果
ソース
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<script src="./scripts/jquery-2.1.1.min.js" type="text/javascript"></script>
</head>
<body>
<form id="form1" runat="server">
<div id="div1">
W<asp:TextBox ID="TextBoxW" runat="server" Columns="4">300</asp:TextBox>
H<asp:TextBox ID="TextBoxH" runat="server" Columns="3">400</asp:TextBox>
S<asp:TextBox ID="TextBoxS" runat="server" Columns="4">5000</asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="" />
<br />
<asp:Image ID="Image1" runat="server" ImageUrl="~/Images/zTP6q3wIkOVCTKMYZ8SfXKRZPvs.jpg" CssClass="imagePoster" />
<img alt="" class="imagePoster" src="Images/zTP6q3wIkOVCTKMYZ8SfXKRZPvs.jpg" />
</div>
<div id="div2">
<asp:Image ID="Image2" runat="server" ImageUrl="~/Images/zTP6q3wIkOVCTKMYZ8SfXKRZPvs.jpg" CssClass="imagePoster" />
<img alt="" class="imagePoster" src="Images/zTP6q3wIkOVCTKMYZ8SfXKRZPvs.jpg" />
</div>
</form>
<script type="text/javascript">
$('#div1 img.imagePoster').animate({ width: 300, height: 400 }, 3000);
</script>
</body>
</html>
スクリプトを埋め込むイベントは「Page_Load」でOKみたい。その他OKだったイベントはコメント化しておいた。
Partial Class TestJQuery
Inherits System.Web.UI.Page
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim w As String = TextBoxW.Text
Dim h As String = TextBoxH.Text
Dim s As String = TextBoxS.Text
Dim strScript As String = "<script type=""text/javascript""> $('#div2 img.imagePoster').animate({ width: " + w + ", height: " + h + " }, " + s + "); </script>"
ClientScript.RegisterStartupScript(Me.GetType(), 1, strScript)
'ClientScript.RegisterClientScriptBlock(Me.GetType(), 1, strScript)
End Sub
Protected Sub Page_LoadComplete(sender As Object, e As EventArgs) Handles Me.LoadComplete
'Dim w As String = TextBoxW.Text
'Dim h As String = TextBoxH.Text
'Dim s As String = TextBoxS.Text
'Dim strScript As String = "<script type=""text/javascript""> $('#div2 img.imagePoster').animate({ width: " + w + ", height: " + h + " }, " + s + "); </script>"
'ClientScript.RegisterStartupScript(Me.GetType(), 1, strScript)
End Sub
Protected Sub form1_Init(sender As Object, e As EventArgs) Handles form1.Init
'Dim w As String = TextBoxW.Text
'Dim h As String = TextBoxH.Text
'Dim s As String = TextBoxS.Text
'Dim strScript As String = "<script type=""text/javascript""> $('#div2 img.imagePoster').animate({ width: " + w + ", height: " + h + " }, " + s + "); </script>"
'ClientScript.RegisterStartupScript(Me.GetType(), 1, strScript)
End Sub
Protected Sub form1_Load(sender As Object, e As EventArgs) Handles form1.Load
'Dim w As String = TextBoxW.Text
'Dim h As String = TextBoxH.Text
'Dim s As String = TextBoxS.Text
'Dim strScript As String = "<script type=""text/javascript""> $('#div2 img.imagePoster').animate({ width: " + w + ", height: " + h + " }, " + s + "); </script>"
'ClientScript.RegisterStartupScript(Me.GetType(), 1, strScript)
End Sub
Protected Sub form1_PreRender(sender As Object, e As EventArgs) Handles form1.PreRender
'Dim w As String = TextBoxW.Text
'Dim h As String = TextBoxH.Text
'Dim s As String = TextBoxS.Text
'Dim strScript As String = "<script type=""text/javascript""> $('#div2 img.imagePoster').animate({ width: " + w + ", height: " + h + " }, " + s + "); </script>"
'ClientScript.RegisterStartupScript(Me.GetType(), 1, strScript)
End Sub
Protected Sub Image2_Load(sender As Object, e As EventArgs) Handles Image2.Load
'Dim w As String = TextBoxW.Text
'Dim h As String = TextBoxH.Text
'Dim s As String = TextBoxS.Text
'Dim strScript As String = "<script type=""text/javascript""> $('#div2 img.imagePoster').animate({ width: " + w + ", height: " + h + " }, " + s + "); </script>"
'ClientScript.RegisterStartupScript(Me.GetType(), 1, strScript)
End Sub
End Class
次に ListView のアイテム内に表示された画像を jQuery でエフェクトしてみる
実施内容
ListView のアイテム内に動的に描画された画像に、jQuery でエフェクトをかけてみる。画像のサイズ変更に加えて、「jqueryrotate」というライブラリを使用し画像をマウスオーバーで回転させてみる。jQuery マウスオーバーで検索したら、jqueryrotate が下記で紹介されていた。
いろんな画像をクルックルクルックル回すイケイケjQueryプラグイン 「jQueryRotate」|わざログ| うずまきブログ| 名古屋のホームページ制作/印刷物デザイン 株式会社うずまきデザイン
http://uzmk.jp/blog/tips/entry-229.html
jqueryrotate の入手と配置
(入手)
jqueryrotate - jQuery plugin that rotate images (and animate them) by any angle - Google Project Hosting
https://code.google.com/p/jqueryrotate/
入手した「jQueryRotateCompressed.js」をScriptsフォルダへ入れる。
結果
ウェイト時間を設けないと意図したリサイズ動作にならない。1200ミリ秒以上のウェイトをかけると意図したリサイズ動作になる。またマウスオーバーで画像が時計回りに、マウスアウトで反時計回りに回転できた。
特記事項
jQuery の適用をウェイトさせる
SQL Server の FILESTREAM で画像を保存しているが、うちの開発環境では、サンプルのような画像読み込みに数秒の時間が必要だ。ListView の画像表示が完了しないまま、jQuery の画像サイズ変更が適用されると、最小サイズから変更後指定サイズへのサイズ変更となってしまう。そこで、初期表示サイズの画像が表示されるまでウェイトして、変更後指定サイズへリサイズするようにしてみた。ウェイト時間はテキストボックスから指定できるようにする。
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<style></style>
<script type="text/javascript">
function loopWait(timeWait){
var timeStart = new Date().getTime();
var timeNow = new Date().getTime();
while( timeNow < (timeStart + timeWait ) )
{
timeNow = new Date().getTime();
}
return;
}
</script>
</head>
jQuery ライブラリのインポート
AJAX Contorol Toolkit の ScriptManager を配置しているので、これを使ってインポートする。マスターページに ScriptManager を配置している場合は便利じゃないかな。
id名を固定化する
ASP.NET のコントロールのプロパティ「ClientIDMode」を Static にしないと、各コントロールの id名 は html生成時に 自動的に連番のようなものが加算されてしまう。今回は asp:image に Class=imagePoster を割り当てたので、Class指定だけで jQuery はエフェクト対象のコントロールを特定できるが、参考にメモ。
Static にすると id名 は固定される。ListView の各アイテム内のコントロールには、一律同じ id名 が付与される。ListView の各アイテム内のコントロールに同じ id名を付与して、一律に jQuery から参照させる場合は Static がいいのかな。
Static にしないと id名は連番のようなものが加算されて付与される。ListView の各アイテム内のコントロールには、すべて異なる id名 が付与される。ListViewの何個目のアイテムだけに適用するとかの場合は、Static にしない感じかな。
適用先の検索方法はいろいろあるみたいなので、もう少し勉強が必要かな。
(参考)
ASP.NETプログラマーのためのjQuery入門 - @IT
http://www.atmarkit.co.jp/fdotnet/special/jquery/jquery_02.htmlRIAへの第一歩としてのjQuery (1/3):CodeZine
http://codezine.jp/article/detail/6880
ソース
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="ListViewPosterJQ.aspx.vb" Inherits="ListViewPosterJQ" %>
<%@ Register assembly="AjaxControlToolkit" namespace="AjaxControlToolkit" tagprefix="asp" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
<style></style>
<script type="text/javascript">
function loopWait(timeWait){
var timeStart = new Date().getTime();
var timeNow = new Date().getTime();
while( timeNow < (timeStart + timeWait ) )
{
timeNow = new Date().getTime();
}
return;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="./scripts/jquery-2.1.1.min.js" />
<asp:ScriptReference Path="./Scripts/jQueryRotateCompressed.js" />
</Scripts>
</asp:ToolkitScriptManager>
W:<asp:TextBox ID="TextBoxW" runat="server" Columns="4">150</asp:TextBox>
H:<asp:TextBox ID="TextBoxH" runat="server" Columns="4">300</asp:TextBox>
W:<asp:TextBox ID="TextBoxJW" runat="server" Columns="4"></asp:TextBox>
H:<asp:TextBox ID="TextBoxJH" runat="server" Columns="3"></asp:TextBox>
S:<asp:TextBox ID="TextBoxJS" runat="server" Columns="4"></asp:TextBox>
Wait:<asp:TextBox ID="TextBoxWait" runat="server" Columns="4"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="" />
<br />
<asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" DataSourceID="SqlDataSource1" GroupItemCount="10">
<AlternatingItemTemplate>
<td runat="server" style="vertical-align: top">ID:
<asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' />
<br />STREAMID:
<asp:Label ID="STREAMIDLabel" runat="server" Text='<%# Eval("STREAMID") %>' Visible="False" />
<br />TMDbID:
<asp:Label ID="TMDbIDLabel" runat="server" Text='<%# Eval("TMDbID") %>' />
<br />aspect_ratio:
<asp:Label ID="aspect_ratioLabel" runat="server" Text='<%# Eval("aspect_ratio") %>' />
<br />file_path:
<asp:Label ID="file_pathLabel" runat="server" Text='<%# Eval("file_path") %>' Visible="False" />
<br />height:
<asp:Label ID="heightLabel" runat="server" Text='<%# Eval("height") %>' />
<br />width:
<asp:Label ID="widthLabel" runat="server" Text='<%# Eval("width") %>' />
<br />
<asp:Image ID="Image2" runat="server" ImageUrl='<%# "imagePoster.aspx?ID=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "ID")) + "&w=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "w")) + "&h=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "h")) %>' CssClass="imagePoster" />
<br /></td>
</AlternatingItemTemplate>
<EmptyDataTemplate>
<table runat="server" style="">
<tr>
<td></td>
</tr>
</table>
</EmptyDataTemplate>
<EmptyItemTemplate>
<td runat="server" />
</EmptyItemTemplate>
<GroupTemplate>
<tr id="itemPlaceholderContainer" runat="server">
<td id="itemPlaceholder" runat="server"></td>
</tr>
</GroupTemplate>
<ItemTemplate>
<td runat="server" style="vertical-align: top">ID:
<asp:Label ID="IDLabel" runat="server" Text='<%# Eval("ID") %>' />
<br />STREAMID:
<asp:Label ID="STREAMIDLabel" runat="server" Text='<%# Eval("STREAMID") %>' Visible="False" />
<br />TMDbID:
<asp:Label ID="TMDbIDLabel" runat="server" Text='<%# Eval("TMDbID") %>' />
<br />aspect_ratio:
<asp:Label ID="aspect_ratioLabel" runat="server" Text='<%# Eval("aspect_ratio") %>' />
<br />file_path:
<asp:Label ID="file_pathLabel" runat="server" Text='<%# Eval("file_path") %>' Visible="False" />
<br />height:
<asp:Label ID="heightLabel" runat="server" Text='<%# Eval("height") %>' />
<br />width:
<asp:Label ID="widthLabel" runat="server" Text='<%# Eval("width") %>' />
<br />
<asp:Image ID="Image1" runat="server" ImageUrl='<%# "imagePoster.aspx?ID=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "ID")) + "&w=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "w")) + "&h=" + Convert.ToString(DataBinder.Eval(Container.DataItem, "h")) %>' CssClass="imagePoster" />
<br /></td>
</ItemTemplate>
<LayoutTemplate>
<table runat="server">
<tr id="Tr1" runat="server">
<td id="Td1" runat="server" style="">
<asp:DataPager ID="DataPager2" runat="server" PageSize="20">
<Fields>
<asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True" ShowLastPageButton="True" />
<asp:NumericPagerField ButtonCount="50" />
</Fields>
</asp:DataPager>
</td>
</tr>
<tr runat="server">
<td runat="server">
<table id="groupPlaceholderContainer" runat="server" border="0" style="">
<tr id="groupPlaceholder" runat="server">
</tr>
</table>
</td>
</tr>
<tr runat="server">
<td runat="server" style="">
<asp:DataPager ID="DataPager1" runat="server" PageSize="20">
<Fields>
<asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True" ShowLastPageButton="True" />
<asp:NumericPagerField ButtonCount="50" />
</Fields>
</asp:DataPager>
</td>
</tr>
</table>
</LayoutTemplate>
</asp:ListView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:TESTConnectionString %>" SelectCommand="SELECT [ID], [STREAMID], [TMDbID], [aspect_ratio], [file_path], [height], [width], [iso_639_1], [vote_average], [vote_count],@w as w,@h as h FROM [TMDbPoster]">
<SelectParameters>
<asp:ControlParameter ControlID="TextBoxW" Name="w" PropertyName="Text" />
<asp:ControlParameter ControlID="TextBoxH" Name="h" PropertyName="Text" />
</SelectParameters>
</asp:SqlDataSource>
</div>
</form>
<script type="text/javascript">
$("#groupPlaceholderContainer img.imagePoster").rotate({
bind:
{
mouseover : function() {
$(this).rotate({
animateTo: 360
})
},
mouseout : function() {
$(this).rotate({
animateTo: 0
})
}
}
});
</script>
</body>
</html>
Inherits System.Web.UI.Page
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim w As String = TextBoxJW.Text
Dim h As String = TextBoxJH.Text
Dim s As String = TextBoxJS.Text
Dim Wait As String = TextBoxWait.Text
Dim strScriptWait As String = "<script type=""text/javascript"">loopWait(" + Wait + "); </script>"
Dim strScriptSize As String = "<script type=""text/javascript""> $('#groupPlaceholderContainer img.imagePoster').animate({ width: " + w + ", height: " + h + " }, " + s + "); </script>"
If w = "" Or h = "" Or s = "" Or Wait = "" Then
Else
ClientScript.RegisterStartupScript(Me.GetType(), 1, strScriptWait)
ClientScript.RegisterStartupScript(Me.GetType(), 2, strScriptSize)
End If
End Sub
End Class
今後
jQuery を利用して、MovieJukeBox をインタラクティブにしたいと思う。jQuery のことをまだわかっていないので、勉強し、公開されているライブラリを吟味して、MovieJukeBox をより良いものにできたらいいな。ますます映画を観ることよりもホームシアター環境の構築に走ってしまいそうだ。
jQuery 及び それを利用したライブラリの提供者へ感謝です。
コメント
コメントを投稿