DeepZoom 강좌 1. Deep Zoom Composer를 이용하여 .sdi 파일 만들기
DeepZoom 강좌 2. 실버라이트의 <MultiScaleImage> 컨트롤 사용
DeepZoom 강좌 3. Deep Zoom 마우스로 컨트롤 하기
DeepZoom 강좌 4. Deep Zoom 마우스 컨트롤 코드 살펴보기

DeepZoom 강좌 4. Deep Zoom 마우스 컨트롤 코드 살펴보기

지난 3개의 Deep Zoom 강좌를 통해서 우리는 Deep Zoom Composer를 이용해서 SeaDragon Image(.sdi)를 만들고 <MultiScaleImage>를 사용하여 Silverlight2 Developer Poster를 브라우저에 올렸습니다. 그리고 마우스 클릭, 휠, 드래그를 구현하여 큰 이미지를 줌인/줌아웃하면서 네비게이션을 했습니다. 그 과정에서 마우스 컨트롤을 담당하는 클래스를 만들어서 사용했었는데 이번 강좌에서는 그 코드를 조금만 살펴보겠습니다.

강좌에 사용한 코드는
* The Weekly Source Code 18 - Deep Zoom (Seadragon) Silverlight 2 MultiScaleImage Mouse Wheel Zooming and Panning Edition - Scott Hanselman
* 마우스 휠 사용을 위한 코드 - pete blois
에서 가져왔습니다.

위의 코드를 통합해서 만든 DeepZoomMouseController.cs 를 다운받으세요.


1. <MultiScaleImage> 의 줌인/줌아웃 코드 

  마우스의 이벤트를 받아서 계산을 거쳐서 결국에는 <MultiScaleImage>의 줌인/줌아웃 메서드를 호출하게됩니다. 줌인/줌아웃하는 코드는 두군데 있는데 이렇습니다.

Zoom(ZoomFactor, this.lastMousePos);

 여기서 lastMousePos 은 MouseMove 이벤트 핸들러에서 마우스 움직일 때 마다 현재 마우스의 위치를 Point 개체에 넣어서 가지고 있습니다. ZoomFactor 라는 변수는 0보다 크고 1보다 작으면 줌아웃, 1보다 크면 줌인으로 그 크기는 줌인/줌아웃의 정도를 나타냅니다. Zoom이라는 메서드는 아래와 같죠.

public void Zoom(double zoom, Point pointToZoom)
{
    Point logicalPoint = this.Source.ElementToLogicalPoint(pointToZoom);
    this.Source.ZoomAboutLogicalPoint(zoom, logicalPoint.X, logicalPoint.Y);
}

MultiScaleImage의 두가지 메서드를 사용합니다. MSDN의 도움말이 비어 있어서 자세한 내용파악이 힘드네요. 어째든 ElementToLogicalPoint를 이용해서 현재 마우스 좌표를 MultiScaleImage 컨트롤의 논리적인 좌표로 변환을 하고 ZoomFactor 값만큼 ZoomAboutLogicalPoint 메서드를 이용해서 줌인/줌아웃을 하라는 코드입니다.

줌인/줌아웃과 관련된 사용자의 입력(마우스 휠을 돌린다던지 클릭 또는 Shift 누르고 클릭)은 모두 결국 적당한 ZoomFactor값을 계산하고 난 후에 Zoom 메서드를 호출합니다.

2. 마우스 휠 컨트롤 

 마우스 휠에 관련한 이벤트는 실버라이트 자체에는 없고 실버라이트를 가지고 있는 웹 브라우저에서 발생합니다. 그래서 그 이벤트를 우리가 작성하고 있는 C# Managed Code로 가져와야 합니다. 한가지 방법은 Javascript에서 실버라이트 플러그 인으로 이벤트를 전달하는 방법이지만 Javascript를 작성해야 한다는 불편함이 있는데요. pete blois 가 Managed Code에서 Silverlight's DOM bridge를 이용하여 브라우저의 휠 이벤트를 훅(Hook)하는 방법을 공개했습니다. 그 코드가 아래와 같습니다.

if (HtmlPage.IsEnabled)
{
     HtmlPage.Window.AttachEvent("DOMMouseScroll",
                             new EventHandler<HtmlEventArgs>(this.HandleMouseWheel));
     HtmlPage.Window.AttachEvent("onmousewheel",
                             new EventHandler<HtmlEventArgs>(this.HandleMouseWheel));
      HtmlPage.Document.AttachEvent("onmousewheel",
                             new EventHandler<HtmlEventArgs>(this.HandleMouseWheel));
}

이제 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 && mouseIsOver)
            {
                args.PreventDefault();
                if (delta > 0)
                    ZoomFactor = 1.2;
                else
                    ZoomFactor = .80;
             }
            Zoom(ZoomFactor, this.lastMousePos);
        }

HandleMouseWheel 핸들러를 보면 휠을 돌린 delta 값을 계산하고 있습니다. 그 delta 값을 이용해서 Zoom(ZoomFactor, this.lastMousePos); 를 호출하게 됩니다. 각 브라우저에서 넘어오는 delta 값의 특성에 따라서 약간의 보정 계산이 들어가 있습니다. 이것은 시행착오와 실험으로 정리가 되었겠죠. delta의 양수/음수를 판단해서 ZoomFactor를 1.2 가되면 줌인, 0.8이 되면 줌아웃이 작동됩니다.

3. 마우스 클릭, Shift + 마우스 클릭

마우스 클릭은 최상위 컨트롤인 Page에서 받습니다. 그 이벤트 핸들러를 등록을 해줍니다.

RootControl.MouseLeftButtonDown +=
                        new MouseButtonEventHandler(RootControl_MouseLeftButtonDown);
RootControl.MouseLeftButtonUp +=
                        new MouseButtonEventHandler(RootControl_MouseLeftButtonUp);

마우스 버튼을 Up 할 때 마찬가지로 ZoomFactor 값을 적당히 주고 Zoom(ZoomFactor, this.lastMousePos); 를 호출하여 줌인/줌아웃을 하네요.

void RootControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    mouseButtonPressed = false;
    if (mouseIsDragging == false)
   {
         bool shiftDown = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;

         ZoomFactor = 2.0;
         if (shiftDown) ZoomFactor = 0.5; //back out when shift is down
         Zoom(ZoomFactor, this.lastMousePos);
   }
   mouseIsDragging = false;
}

4. 마우스 드래깅을 이용한 위치 이동

마우스를 드래그 하면 그림의 위치가 이동을 합니다. 그 구현은 MouseMove 이벤트 핸들러에 있습니다. 우선 MouseEnter와 MouseLeave 이벤트 핸들러에서 mouseButtonPressed 플래그를 변화시키고 그 값을 이용해서 드래그 상태인지 아닌지 판단을 합니다.

if (mouseButtonPressed)
{
    mouseIsDragging = true;
}
if (mouseIsDragging)
{
    Point newOrigin = new Point();
    newOrigin.X = currentPosition.X - (((e.GetPosition(Source).X - dragOffset.X)
                                  / Source.ActualWidth) * Source.ViewportWidth);
    newOrigin.Y = currentPosition.Y - (((e.GetPosition(Source).Y - dragOffset.Y)
                                 / Source.ActualHeight) * Source.ViewportWidth);
    Source.ViewportOrigin = newOrigin;
}

MultiScaleImage 의 ViewportOrigin 의 위치를 변화 시키면서 이동을 하게 되네요. 역시 msdn의 설명이 비어 있어서 구체적인 내용은 파악하기 힘들지만 말이죠.

HTML과 Managed Code 사이의 인터렉션에 관해서는 튜토리얼을 참조하세요.

여기까지 마우스 컨트롤을 하는 소스분석을 해봤습니다. 이것으로 Deep Zoom 강좌를 마치겠습니다. Deep Zoom을 이용해서 창의적인 표현을 많이 봤으면 좋겠습니다. 도움이 되셨기를 바랍니다.
감사합니다.



마지막으로 Deep Zoom에 관련한 블로그 및 강좌를 모아 봤습니다.

* Deep Zoom 소개
Deep Zoom! - 유령회사 공도 소프트
와우!! SeaDragon을 위한 Deep Zoom Composer!! - GILVERLIGHT = GILBERT + SILVERLIGHT
[MIX08] 실버라이트 딥줌(DeepZoom) 기술과 하드락 카페 사례 - UXFactory
[Silverlight] Deep Zoom을 활용한 대만의 국립 궁전 박물관 - 준서아빠가 생각하는 행복한 UX이야기

* 강좌
훈스닷넷 8회 정기세미나 5세션 발표자료 - 유령회사 공도 소프트
Deep Zoom 강좌 : 2. Silverlight 프로젝트 만들기 - ToExpert.Net (어허 ~ 어째 비슷하네요 ~ 강좌가...)


WRITTEN BY
ONESTONE

트랙백  0 , 댓글  6개가 달렸습니다.
  1. ㅠㅠ; 왜 이리 점점 어려버 지는지...해해햇...
  2. 한서영 2008.03.24 13:49
    그대로 따라하는데 namespace 가 없다는 에러 가 나네요

    오류 9 'System' 네임스페이스에 'Windows' 형식 또는 네임스페이스 이름이 없습니다. 어셈블리 참조가 있는지 확인하십시오. C:\Documents and Settings\Administrator\My Documents\SilverlightTest\DeepZoomSilverlight2poster\DeepZoomSilverlight2poster_Web\DeepZoomMouseController.cs 8 14 DeepZoomSilverlight2poster_Web
  3. 한서영 2008.03.24 13:51
    오류 1 'DeepZoomMouseController' 형식 또는 네임스페이스 이름을 찾을 수 없습니다. using 지시문 또는 어셈블리 참조가 있는지 확인하십시오. C:\Documents and Settings\Administrator\My Documents\SilverlightTest\DeepZoomSilverlight2poster\DeepZoomSilverlight2poster\Page.xaml.cs 19 13 DeepZoomSilverlight2poster
  4. 길버트 2008.03.28 15:57
    한번의 zoom-in, zoom-out으로 원래 배율로 돌아오려면,
    확대시 1.25, 축소시 0.8을 하시는 것이 좋습니다.
secret
DeepZoom 강좌 1. Deep Zoom Composer를 이용하여 .sdi 파일 만들기
DeepZoom 강좌 2. 실버라이트의 <MultiScaleImage> 컨트롤 사용
DeepZoom 강좌 3. Deep Zoom 마우스로 컨트롤 하기
DeepZoom 강좌 4. Deep Zoom 마우스 컨트롤 코드 살펴보기

DeepZoom 강좌 3. Deep Zoom 마우스로 컨트롤 하기

이전 두 강좌에서 우리는 Deep Zoom Composer로 SeaDragon 이미지 파일을 만들었고 VS 2008에서 실버라이트 프로젝트를 만들어서 <MultiScaleImage> 컨트롤을 이용하여 실버라이트에 Deep Zoom 이미지를 띄웠습니다. 하지만 가장 중요한 마우스로 줌인/줌아웃이 되지 않았죠. 이번 강좌에서는 마우스 이벤트 핸들러를 이용해서 줌인/줌아웃을 구현해 보겠습니다.

줌인/줌아웃에 관련된 소스코드는
* The Weekly Source Code 18 - Deep Zoom (Seadragon) Silverlight 2 MultiScaleImage Mouse Wheel Zooming and Panning Edition - Scott Hanselman
* 마우스 휠 사용을 위한 코드 - pete blois
에서 가져왔습니다.

우선 작동을 시켜보고 소스코드를 살펴보는것이 좋을 것 같습니다. 아래 C# 코드를 다운받아서 실버라이트 프로젝트에 추가시킵니다.

DeepZoomMouseController.cs
 
프로젝트에 추가시키는 방법은 실버라이트 프로젝트에서 오른쪽 클릭을 하고 Add - Add Existing Item을 선택하여 다운로드 받은 파일을 선택합니다.

사용자 삽입 이미지

그런후에 Page.xaml.cs 파일을 열어서 생성자에서 아래와 같이 코드를 한줄만 입력합니다.

public Page()
{
    InitializeComponent();
    DeepZoomMouseController mouseController
                          = new DeepZoomMouseController(this, msimgPoster);
}
이 코드는 방금 다운로드해서 추가한 클래스를 이용해서 마우스컨트롤러를 생성합니다. 두가지 파라미터는 <MultiScaleImage>를 포함하고 있는 컨트롤 (여기서는 Page)과 <MultiScaleImage> 컨트롤의 이름 입니다.

이렇게 한 다음에 F5를 눌러서 실행을 시키면 이제 드디어 마우스로 줌인/줌아웃이 가능하게 됩니다. 작동하는 기능은
 - 마우스 왼쪽 클릭 : 줌인
 - Shift 키를 누르고 마우스 왼쪽 클릭 : 줌 아웃
 - 마우스 드래그 : 이동
 - 마우스 휠 : 줌인/줌아웃

사용자 삽입 이미지


다음 강좌에서는 방금 사용한 코드를 일부만 분석을 해보겠습니다.

WRITTEN BY
ONESTONE

트랙백  0 , 댓글  1개가 달렸습니다.
  1. 이거 실버라이트 프로젝트에만 적용되는 건가요 ?
secret
DeepZoom 강좌 1. Deep Zoom Composer를 이용하여 .sdi 파일 만들기
DeepZoom 강좌 2. 실버라이트의 <MultiScaleImage> 컨트롤 사용
DeepZoom 강좌 3. Deep Zoom 마우스로 컨트롤 하기
DeepZoom 강좌 4. Deep Zoom 마우스 컨트롤 코드 살펴보기

DeepZoom 강좌 2. 실버라이트의 <MultiScaleImage> 컨트롤 사용

Deep Zoom 강좌가 진행중입니다. 이번에는 실버라이트에 새로 추가된 <MultiScaleImage>를 사용해서 Deep Zoom Composer로 만든 SeaDragon Image를 실버라이트 응용프로그램에 추가해 보겠습니다.

우선 Visual Studio 2008을 실행해서 메뉴의 File - New Project를 누릅니다. 새 프로젝트 대화상자에서 "DeepZoomSilverlight2Poster"라고 프로젝트 명을 입력합니다.
사용자 삽입 이미지

곧이어 나오는 Add Silverlight Application 에서 Project Type을 Web_Application Project로 선택을 하고 OK를 누릅니다. 그러면 실버라이트 프로젝트가 생성되죠.

이제 이전 강좌에서 만든 SeaDragon Image를 우리의 응용프로그램에 복사하겠습니다. 즉 웹에서 이미지들을 가져갈 수 있게 웹서버 루트 밑에 복사를 합니다. 우리의 경우 ClientBin 폴더에 복사를 하겠습니다. (노트: CilentBin 폴더는 빌드를 한번 해줘야 생깁니다. "F6" 키를 눌러서 빌드를 한번 진행해 주시면 생깁니다.) Deep Zoom Composer가 Export 한 폴더로 이동하여 OutputSdi 폴더 밑에 silverlight2deloperposter 폴더를 복사하여 VS 2008의 Solution Explorer에서 ClientBin 폴더에 붙여넣기합니다.

사용자 삽입 이미지


이제 Page.xaml 을 열어서 <Grid x:Name="LayoutRoot" Background="White"> 다음줄에 아래 코드를 입력합니다.

<MultiScaleImage Source="silverlight2deloperposter/info.bin" x:Name="msimgPoster" />

<MultiScaleImage> 컨트롤은 실버라이트 2에서 새로 추가된 컨트롤입니다. 이 컨트롤이 바로 Deep Zoom을 위한 컨트롤입니다. Source 에는 복사한 폴더명과 info.bin 파일을 지정합니다. xap 파일도 ClientBin 폴더에 생성되어 실행되기 때문에 상대경로로 지정합니다. x:Name=msimgPoster 는 코드 비하인드에서 사용할 이름입니다.

이제 F5를 눌러 실행을 해보겠습니다. 그러면 우선 아래처럼 우리가 원하는 Silverlight 2 Developer Poster가 보입니다.

사용자 삽입 이미지

우선 너무 작습니다. 전체 화면에 표시될 수 있도록 Page.xaml 을 수정하겠습니다. 제일 상위의 <UserControl> 에서 Width="400" Height="300" 을 삭제 합니다. 결과적으로 Page.xaml 파일을 아래와 같습니다.

<UserControl x:Class="DeepZoomSilverlight2Poster.Page"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    >
    <Grid x:Name="LayoutRoot" Background="White">
        <MultiScaleImage Source="silverlight2deloperposter/info.bin" x:Name="msimgPoster" />
    </Grid>
</UserControl>
이제 다시 F5를 눌러서 실행을 시켜 보겠습니다.

이제는 전체화면에 꽉 차서 표시가 되네요. 하지만 우리가 데모에서 흔히 보았듯이 마우스를 클릭하거나 마우스 휠을 돌려서 줌인/줌아웃이 안되네요. 네 마우스를 이용한 줌인/줌아웃은 다음 강좌에 자세한 내용이 있습니다. 다음 강좌로 넘어가겠습니다.

오일석

WRITTEN BY
ONESTONE

트랙백  0 , 댓글  0개가 달렸습니다.
secret
 
사용자 삽입 이미지
Silverlight 2.0 베타의 발표가 이제 얼마 남지 않았네요. 어떤 변화가 있을지 디자이너와 개발자에게 어떤 새로운 기능을 제공할지 기대가 많이 됩니다. 그중에서 '헉 이럴수가...'하는 감탄사가 나오게 하는 새로운 기술이 있다고 전해지는데 그 중에 하나가 바로 Seadragon 이라는 기술이라고 합니다.

큰 해상도의 사진을 보는 경우 우선 전체 모양을 볼 때는 작은 이미지로 표시가 되겠죠. 이경우 전체 보기에 적당한 양의 정보를 가져와서 보여주고 줌인(Zoom-In)하면 점차 자세한 이미지의 부분을 보게된는데 그 때마다 적당한 양의 사진 정보를 가져와서 사용자에게 보여주는 기술입니다. 설명이 어렵습니다.

아래는 Seadragon 사이트의 번역본 입니다.

Seadragon은 지난 2월(2006년) Seadragon Software 인수를 통해서 수행한 인큐베이션 프로젝트 입니다. 이 프로젝트의 목적은 우리가 사용하는 스크린(벽을 덮는 큰 디스플레이에서 부터 모바일 디바이스까지)의 사용법을 바꾸것 그 이상도 그 이하도 아닙니다. Seadragon을 통해서 네트워크의 대역폭이나 데이터의 양에 관계없이 부드럽게 비주얼 정보(Visual Infomation)를 브라우징 할 수 있습니다.  
사용자 삽입 이미지

설명이 조금 막연한데요. 여기 Seadragon의 4가지 약속이 있습니다.
  1. 네비게이션의 속도가 오브젝트의 크기나 개수에 독립적이다.
  2. 성능은 단지 스크린의 픽셀수 대 네트워크 대역폭과의 비율과 관계있다.
  3. 변환(Transitions)은 버터처럼 부드럽다.
  4. 스케일링(Scaling)은 거의 완벽하고 어떤 해상도에서도 빠르다.
Seadragon 팀은 현재 DirectX 구현을 튜닝하고 있고 새로운 Windows Media Photo Format을 거의 완성했으며 Photosynth 기술과 접목시키고 있습니다. 


마지막 설명에 Seadragon 기술을 Phothosynth와 접목시키고 있다고 하는데요. Phothsynth는 컴퓨터를 통해서 많은 양의 사진을 보는 새로운 경험을 제공합니다. 3차원 공간에서 어떤 사물이나 장소에 대한 수 많은 사진을 보여 줍니다. 저의 글로는 설명이 어렵네요. 영상을 보시죠.

이 영상은 준서아빠의 블로그에서 소개된 TED 컨퍼런스 영상입니다. 초반부에 Seadragon의 데모가 보여지고 후반부에 Seadragon을 이용한 Photosynth에 대한 데모 입니다.



추가적인 데모 영상은 Photysynth 사이트에 있습니다.



세상은 변해서 사용자의 경험은 새로운 국면을 맞이하고 있습니다. 상상만 했던 것들이 실현되는 것 같습니다. 이정도도 구현을 하는데 못할게 없을 것 같습니다. 상상력이 필요합니다. 상상만하면 구현을 할 수 있을 테니까요.

WRITTEN BY
ONESTONE

트랙백  0 , 댓글  0개가 달렸습니다.
secret