[Silverlight]要如何把Deep Zoom產生的檔案內嵌到已完成的Silverlight網頁中?
我們知道可以透過Deep Zoom Composer輕易地作出可以Zoom In & Zoom Out的圖片瀏覽功能:
1. Import 圖片進Deep Zoom Composer:
2. Compose圖片,這邊就輕鬆擺一下:
3. 設定名稱、匯出專案樣板類型(這邊我們選擇Deep Zoom Classic + Source),然後按下匯出:
4. 然後我們可以看到專案被放在下列目錄:
打開Exported Data目錄,接下來再打開deepzoomtest目錄(這個名稱就是我們在匯出那步驟所命名的名稱).
接下來,我們處理要放到Silverlight專案的部分:
5. 開啟一個新的Silverlight專案(這裡我們把這個專案取名為DeepZoomMigrate),然後將GeneratedImages目錄整個複製到DeepZoomMigrate.Web
專案的ClientBin目錄下。
6. 在DeepZoomMigrate專案中加入DeepZoomProject目錄下的MouseWheelHelper.cs類別檔案。
這個類別顧名思義是用來處理滑鼠滾輪的事件及方法:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;
namespace DeepZoomProject
{
// Courtesy of Pete Blois
public class MouseWheelEventArgs : EventArgs
{
private double delta;
private bool handled = false;
public MouseWheelEventArgs(double delta)
{
this.delta = delta;
}
public double Delta
{
get { return this.delta; }
}
// Use handled to prevent the default browser behavior!
public bool Handled
{
get { return this.handled; }
set { this.handled = value; }
}
}
public class MouseWheelHelper
{
public event EventHandler<MouseWheelEventArgs> Moved;
private static Worker worker;
private bool isMouseOver = false;
public MouseWheelHelper(FrameworkElement element)
{
if (MouseWheelHelper.worker == null)
MouseWheelHelper.worker = new Worker();
MouseWheelHelper.worker.Moved += this.HandleMouseWheel;
element.MouseEnter += this.HandleMouseEnter;
element.MouseLeave += this.HandleMouseLeave;
element.MouseMove += this.HandleMouseMove;
}
private void HandleMouseWheel(object sender, MouseWheelEventArgs args)
{
if (this.isMouseOver)
this.Moved(this, args);
}
private void HandleMouseEnter(object sender, EventArgs e)
{
this.isMouseOver = true;
}
private void HandleMouseLeave(object sender, EventArgs e)
{
this.isMouseOver = false;
}
private void HandleMouseMove(object sender, EventArgs e)
{
this.isMouseOver = true;
}
private class Worker
{
public event EventHandler<MouseWheelEventArgs> Moved;
public Worker()
{
if (HtmlPage.IsEnabled)
{
HtmlPage.Window.AttachEvent("DOMMouseScroll", this.HandleMouseWheel);
HtmlPage.Window.AttachEvent("onmousewheel", this.HandleMouseWheel);
HtmlPage.Document.AttachEvent("onmousewheel", this.HandleMouseWheel);
}
}
private void HandleMouseWheel(object sender, HtmlEventArgs args)
{
double delta = 0;
ScriptObject eventObj = args.EventObject;
if (eventObj.GetProperty("wheelDelta") != null)
{
delta = ((double)eventObj.GetProperty("wheelDelta")) / 120;
if (HtmlPage.Window.GetProperty("opera") != null)
delta = -delta;
}
else if (eventObj.GetProperty("detail") != null)
{
delta = -((double)eventObj.GetProperty("detail")) / 3;
if (HtmlPage.BrowserInformation.UserAgent.IndexOf("Macintosh") != -1)
delta = delta * 3;
}
if (delta != 0 && this.Moved != null)
{
MouseWheelEventArgs wheelArgs = new MouseWheelEventArgs(delta);
this.Moved(this, wheelArgs);
if (wheelArgs.Handled)
args.PreventDefault();
}
}
}
}
}
7. 然後我們在剛剛新增的Silverlight專案的MainPage.xaml,新增一個MultiScaleImage物件如下:
<UserControl x:Class="DeepZoomMigrate.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="1024" d:DesignHeight="768">
<StackPanel HorizontalAlignment="Left" >
<MultiScaleImage x:Name="uxMS" Width="800" Height="600" ></MultiScaleImage>
</StackPanel>
</UserControl>
8. 複製剛剛DeepZoomProject目錄下的Page.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 DeepZoomProject;
namespace DeepZoomMigrate
{
public partial class MainPage : UserControl
{
//
// Based on prior work done by Lutz Gerhard, Peter Blois, and Scott Hanselman
//
double zoom = 1;
bool duringDrag = false;
bool mouseDown = false;
Point lastMouseDownPos = new Point();
Point lastMousePos = new Point();
Point lastMouseViewPort = new Point();
public double ZoomFactor
{
get { return zoom; }
set { zoom = value; }
}
public MainPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Page_Loaded);
//
// Firing an event when the MultiScaleImage is Loaded
//
this.uxMS.Loaded += new RoutedEventHandler(uxMS_Loaded);
//
// Firing an event when all of the images have been Loaded
//
this.uxMS.ImageOpenSucceeded += new RoutedEventHandler(uxMS_ImageOpenSucceeded);
//
// Handling all of the mouse and keyboard functionality
//
this.MouseMove += delegate(object sender, MouseEventArgs e)
{
lastMousePos = e.GetPosition(uxMS);
if (duringDrag)
{
Point newPoint = lastMouseViewPort;
newPoint.X += (lastMouseDownPos.X - lastMousePos.X) / uxMS.ActualWidth * uxMS.ViewportWidth;
newPoint.Y += (lastMouseDownPos.Y - lastMousePos.Y) / uxMS.ActualWidth * uxMS.ViewportWidth;
uxMS.ViewportOrigin = newPoint;
}
};
this.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e)
{
lastMouseDownPos = e.GetPosition(uxMS);
lastMouseViewPort = uxMS.ViewportOrigin;
mouseDown = true;
uxMS.CaptureMouse();
};
this.MouseLeftButtonUp += delegate(object sender, MouseButtonEventArgs e)
{
if (!duringDrag)
{
bool shiftDown = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
double newzoom = zoom;
if (shiftDown)
{
newzoom /= 2;
}
else
{
newzoom *= 2;
}
Zoom(newzoom, uxMS.ElementToLogicalPoint(this.lastMousePos));
}
duringDrag = false;
mouseDown = false;
uxMS.ReleaseMouseCapture();
};
this.MouseMove += delegate(object sender, MouseEventArgs e)
{
lastMousePos = e.GetPosition(uxMS);
if (mouseDown && !duringDrag)
{
duringDrag = true;
double w = uxMS.ViewportWidth;
Point o = new Point(uxMS.ViewportOrigin.X, uxMS.ViewportOrigin.Y);
uxMS.UseSprings = false;
uxMS.ViewportOrigin = new Point(o.X, o.Y);
uxMS.ViewportWidth = w;
zoom = 1 / w;
uxMS.UseSprings = true;
}
if (duringDrag)
{
Point newPoint = lastMouseViewPort;
newPoint.X += (lastMouseDownPos.X - lastMousePos.X) / uxMS.ActualWidth * uxMS.ViewportWidth;
newPoint.Y += (lastMouseDownPos.Y - lastMousePos.Y) / uxMS.ActualWidth * uxMS.ViewportWidth;
uxMS.ViewportOrigin = newPoint;
}
};
new MouseWheelHelper(this).Moved += delegate(object sender, DeepZoomProject.MouseWheelEventArgs e)
{
e.Handled = true;
double newzoom = zoom;
if (e.Delta < 0)
newzoom /= 1.3;
else
newzoom *= 1.3;
Zoom(newzoom, uxMS.ElementToLogicalPoint(this.lastMousePos));
uxMS.CaptureMouse();
};
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
//這裡先註解
//string path = App.Current.Resources["path"].ToString();
//string zoomIn = App.Current.Resources["zoomIn"].ToString();
this.uxMS.Source = new DeepZoomImageTileSource(new Uri("/GeneratedImages/dzc_output.xml", UriKind.Relative));
//zoom = Int32.Parse(zoomIn);
}
void uxMS_ImageOpenSucceeded(object sender, RoutedEventArgs e)
{
//If collection, this gets you a list of all of the MultiScaleSubImages
//
//foreach (MultiScaleSubImage subImage in uxMS.SubImages)
//{
// // Do something
//}
uxMS.ViewportWidth = 1;
}
void uxMS_Loaded(object sender, RoutedEventArgs e)
{
}
private void Zoom(double newzoom, Point p)
{
if (newzoom < 0.5)
{
newzoom = 0.5;
}
uxMS.ZoomAboutLogicalPoint(newzoom / zoom, p.X, p.Y);
zoom = newzoom;
}
//private void ZoomInClick(object sender, System.Windows.RoutedEventArgs e)
//{
// Zoom(zoom * 1.3, uxMS.ElementToLogicalPoint(new Point(.5 * uxMS.ActualWidth, .5 * uxMS.ActualHeight)));
//}
//private void ZoomOutClick(object sender, System.Windows.RoutedEventArgs e)
//{
// Zoom(zoom / 1.3, uxMS.ElementToLogicalPoint(new Point(.5 * uxMS.ActualWidth, .5 * uxMS.ActualHeight)));
//}
//private void GoHomeClick(object sender, System.Windows.RoutedEventArgs e)
//{
// this.uxMS.ViewportWidth = 1;
// this.uxMS.ViewportOrigin = new Point(0, 0);
// ZoomFactor = 1;
//}
//private void GoFullScreenClick(object sender, System.Windows.RoutedEventArgs e)
//{
// if (!Application.Current.Host.Content.IsFullScreen)
// {
// Application.Current.Host.Content.IsFullScreen = true;
// }
// else
// {
// Application.Current.Host.Content.IsFullScreen = false;
// }
//}
//// Handling the VSM states
//private void LeaveMovie(object sender, System.Windows.Input.MouseEventArgs e)
//{
// VisualStateManager.GoToState(this, "FadeOut", true);
//}
//private void EnterMovie(object sender, System.Windows.Input.MouseEventArgs e)
//{
// VisualStateManager.GoToState(this, "FadeIn", true);
//}
//// unused functions that show the inner math of Deep Zoom
//public Rect getImageRect()
//{
// return new Rect(-uxMS.ViewportOrigin.X / uxMS.ViewportWidth, -uxMS.ViewportOrigin.Y / uxMS.ViewportWidth, 1 / uxMS.ViewportWidth, 1 / uxMS.ViewportWidth * uxMS.AspectRatio);
//}
//public Rect ZoomAboutPoint(Rect img, double zAmount, Point pt)
//{
// return new Rect(pt.X + (img.X - pt.X) / zAmount, pt.Y + (img.Y - pt.Y) / zAmount, img.Width / zAmount, img.Height / zAmount);
//}
//public void LayoutDZI(Rect rect)
//{
// double ar = uxMS.AspectRatio;
// uxMS.ViewportWidth = 1 / rect.Width;
// uxMS.ViewportOrigin = new Point(-rect.Left / rect.Width, -rect.Top / rect.Width);
//}
}
}
注解掉的地方是原本Deep Zoom Composer產生的按鈕的方法。
這裡要注意兩個地方:
1.
void Page_Loaded(object sender, RoutedEventArgs e)
{
//這裡先註解
//string path = App.Current.Resources["path"].ToString();
//string zoomIn = App.Current.Resources["zoomIn"].ToString();
this.uxMS.Source = new DeepZoomImageTileSource(new Uri("/GeneratedImages/dzc_output.xml", UriKind.Relative));
//zoom = Int32.Parse(zoomIn);
}
這裡把原先程式碼中去讀resouce的圖片的部分改成讀ClientBin目錄下的圖片檔案
2.
new MouseWheelHelper(this).Moved += delegate(object sender, DeepZoomProject.MouseWheelEventArgs e)
{
e.Handled = true;
double newzoom = zoom;
if (e.Delta < 0)
newzoom /= 1.3;
else
newzoom *= 1.3;
Zoom(newzoom, uxMS.ElementToLogicalPoint(this.lastMousePos));
uxMS.CaptureMouse();
};
MouseWheekEventArgs是要引用DeepZoomProject的NameSpace。
結果:
參考連結:
MultiScaleImage 類別 - http://msdn.microsoft.com/zh-tw/library/system.windows.controls.multiscaleimage%28VS.95%29.aspx
如果您有微軟技術開發的問題,可以到MSDN Forum發問。
如果您有微軟IT管理的問題,可以到TechNet Forum發問喔。