첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

■ 이미지 롤 애니메이션(Roll Animation)을 사용하는 방법을 보여준다.

TestProject.zip
3.97MB

 

▶ ImageRollControl.xaml

<UserControl Name="userControl" x:Class="TestProject.ImageRollControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    ClipToBounds="True">
    <Canvas
        Width="{Binding ElementName=userControl, Path=ActualWidth}"
        Height="{Binding ElementName=userControl, Path=ActualHeight}">
        <Image Name="image"
            Width="{Binding ElementName=userControl, Path=ActualWidth}"
            Height="{Binding ElementName=userControl, Path=ActualHeight}"
            Source="{Binding ElementName=userControl, Path=ImageSource}"
            Stretch="Fill" />
        <Canvas Name="wrapCanvas"
            Background="White"
            Width="{Binding ElementName=userControl, Path=ActualWidth}"
            Height="{Binding ElementName=userControl, Path=RollSize}">
            <Canvas Name="rollCanvas"
                Width="{Binding ElementName=userControl, Path=ActualWidth}"
                Height="{Binding ElementName=userControl, Path=RollSize}">
                <Line Name="line1"
                    X1="0"
                    Y1="0"
                    X2="{Binding ElementName=userControl, Path=ActualWidth}"
                    Y2="0"
                    StrokeThickness="1"
                    Stroke="Black"
                    Visibility="Collapsed">
                    <Line.BitmapEffect>
                        <BlurBitmapEffect
                            Radius="1"
                            KernelType="Box" />
                    </Line.BitmapEffect>
                </Line>
                <Line Name="line2"
                    X1="0"
                    Y1="50"
                    X2="{Binding ElementName=userControl, Path=ActualWidth}"
                    Y2="50"
                    StrokeThickness="1"
                    Stroke="Black"
                    Visibility="Collapsed">
                    <Line.BitmapEffect>
                        <BlurBitmapEffect
                            Radius="1"
                            KernelType="Box" />
                    </Line.BitmapEffect>
                </Line>
            </Canvas>
        </Canvas>
    </Canvas>
</UserControl>

 

▶ ImageRollControl.xaml

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace TestProject
{
    /// <summary>
    /// 이미지 롤 컨트롤
    /// </summary>
    public partial class ImageRollControl : UserControl
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Dependency Property
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 이미지 속성 - ImageSourceProperty

        /// <summary>
        /// 이미지 소스 속성
        /// </summary>
        public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register
        (
            "ImageSource",
            typeof(ImageSource),
            typeof(ImageRollControl),
            new UIPropertyMetadata
            (
                null,
                null,
                null,
                false
            )
        );

        #endregion
        #region 롤링 속도 속성 - RollSpeedProperty

        /// <summary>
        /// 롤링 속도 속성
        /// </summary>
        public static readonly DependencyProperty RollSpeedProperty = DependencyProperty.Register
        (
            "RollSpeed",
            typeof(double),
            typeof(ImageRollControl),
            new UIPropertyMetadata
            (
                15d,
                null,
                null,
                false
            )
        );

        #endregion
        #region 롤 크기 속성 - RollSizeProperty

        /// <summary>
        /// 롤 크기 속성
        /// </summary>
        public static readonly DependencyProperty RollSizeProperty = DependencyProperty.Register
        (
            "RollSize",
            typeof(double),
            typeof(ImageRollControl),
            new UIPropertyMetadata
            (
                50d,
                null,
                null,
                false
            )
        );

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 타이머
        /// </summary>
        private DispatcherTimer timer = null;

        /// <summary>
        /// 롤 위쪽
        /// </summary>
        private double rollTop = 0;

        /// <summary>
        /// 임시 이미지
        /// </summary>
        private Image temporaryImage = null;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 이미지 소스 - ImageSource

        /// <summary>
        /// 이미지 소스
        /// </summary>
        public ImageSource ImageSource
        {
            get
            {
                return (ImageSource)GetValue(ImageSourceProperty);
            }
            set
            {
                SetValue(ImageSourceProperty, value);
            }
        }

        #endregion
        #region 롤링 속도 - RollSpeed

        /// <summary>
        /// 롤링 속도
        /// </summary>
        public double RollSpeed
        {
            get
            {
                return (double)GetValue(RollSpeedProperty);
            }
            set
            {
                SetValue(RollSpeedProperty, value);
            }
        }

        #endregion
        #region 롤 크기 - RollSize

        /// <summary>
        /// 롤 크기
        /// </summary>
        public double RollSize
        {
            get
            {
                return (double)GetValue(RollSizeProperty);
            }
            set
            {
                SetValue(RollSizeProperty, value);
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - ImageRollControl()

        /// <summary>
        /// 생성자
        /// </summary>
        public ImageRollControl()
        {
            InitializeComponent();

            Loaded += UserControl_Loaded;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Public
        //////////////////////////////////////////////////////////////////////////////// Function

        #region 시작하기 - Start()

        /// <summary>
        /// 시작하기
        /// </summary>
        public void Start()
        {
            if(ImageSource == null)
            {
                return;
            }

            if(this.timer.IsEnabled)
            {
                return;
            }

            this.rollTop = 0;

            this.timer.Start();
        }

        #endregion
        #region 중단하기 - Stop()

        /// <summary>
        /// 중단하기
        /// </summary>
        public void Stop()
        {
            if(ImageSource == null)
            {
                return;
            }

            if(!this.timer.IsEnabled)
            {
                return;
            }

            this.timer.Stop();
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 사용자 컨트롤 로드시 처리하기 - UserControl_Loaded(sender, e)

        /// <summary>
        /// 사용자 컨트롤 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            ScaleTransform scaleTransform = new ScaleTransform(1, -1, 0, 0);

            this.temporaryImage = new Image();

            this.temporaryImage.Source          = ImageSource;
            this.temporaryImage.Width           = ActualWidth;
            this.temporaryImage.Height          = ActualHeight;
            this.temporaryImage.RenderTransform = scaleTransform;
            this.image.Clip                     = new RectangleGeometry(new Rect(0, 0, ActualWidth, this.rollTop));

            LinearGradientBrush maskBrush = new LinearGradientBrush();

            maskBrush.StartPoint = new Point(0, 0);
            maskBrush.EndPoint   = new Point(0, 1);

            GradientStop blackStop1      = new GradientStop(Color.FromArgb(30 , 255, 255, 255), 0.0);
            GradientStop transparentStop = new GradientStop(Color.FromArgb(175, 255, 255, 255), 0.5);
            GradientStop blackStop2      = new GradientStop(Color.FromArgb(100, 255, 255, 255), 1.0);
            GradientStop blackStop3      = new GradientStop(Colors.Black                      , 0.0);
            GradientStop blackStop4      = new GradientStop(Colors.Black                      , 0.9);

            maskBrush.GradientStops.Add(blackStop1);
            maskBrush.GradientStops.Add(transparentStop);
            maskBrush.GradientStops.Add(blackStop2);
            maskBrush.GradientStops.Add(blackStop3);
            maskBrush.GradientStops.Add(blackStop4);

            this.rollCanvas.OpacityMask = maskBrush;

            this.timer = new DispatcherTimer();

            this.timer.Interval = TimeSpan.FromSeconds(.1);

            this.timer.Tick += timer_Tick;
        }

        #endregion
        #region 타이머 틱 처리하기 - timer_Tick(sender, e)

        /// <summary>
        /// 타이머 틱 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void timer_Tick(object sender, EventArgs e)
        {
            if(this.rollTop + RollSpeed > ActualHeight)
            {
                this.timer.Stop();

                this.line1.Visibility = Visibility.Collapsed;
                this.line2.Visibility = Visibility.Collapsed;

                this.wrapCanvas.Visibility = Visibility.Collapsed;

                return;
            }

            double height;

            if(this.rollTop + RollSize > ActualHeight)
            {
                height = ActualHeight - this.rollTop;
            }
            else
            {
                height = RollSize;
            }

            this.rollCanvas.Height = height;
            this.wrapCanvas.Height = height;

            this.line2.Y1 = height;
            this.line2.Y2 = height;

            this.image.Clip = new RectangleGeometry(new Rect(0, 0, ActualWidth, this.rollTop + height));

            this.line1.Visibility = Visibility.Visible;
            this.line2.Visibility = Visibility.Visible;

            this.wrapCanvas.Visibility = Visibility.Visible;

            Rect clippingRect = new Rect(0, this.rollTop, ActualWidth, height);

            this.temporaryImage.Clip = new RectangleGeometry(clippingRect);

            VisualBrush brush = new VisualBrush(this.temporaryImage as Visual);

            this.rollCanvas.Background = brush;

            Canvas.SetTop(this.wrapCanvas, this.rollTop);

            this.rollTop += RollSpeed;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Function

        #region 리소스 URI 구하기 - GetResourceURI(assemblyName, resourcePath)

        /// <summary>
        /// 리소스 URI 구하기
        /// </summary>
        /// <param name="assemblyName">어셈블리명</param>
        /// <param name="resourcePath">리소스 경로</param>
        /// <returns>리소스 URI</returns>
        private Uri GetResourceURI(string assemblyName, string resourcePath)
        {
            if(string.IsNullOrEmpty(assemblyName))
            {
                return new Uri(string.Format("pack://application:,,,/{0}", resourcePath));
            }
            else
            {
                return new Uri(string.Format("pack://application:,,,/{0};component/{1}", assemblyName, resourcePath));
            }
        }

        #endregion
        #region 비트맵 이미지 구하기 - GetBitmapImage(sourceURI)

        /// <summary>
        /// 비트맵 이미지 구하기
        /// </summary>
        /// <param name="sourceURI">소스 URI</param>
        /// <returns>비트맵 이미지</returns>
        private BitmapImage GetBitmapImage(Uri sourceURI)
        {
            BitmapImage bitmap = new BitmapImage();

            bitmap.BeginInit();

            bitmap.UriSource     = sourceURI;
            bitmap.CacheOption   = BitmapCacheOption.OnDemand;
            bitmap.CreateOptions = BitmapCreateOptions.IgnoreImageCache;

            bitmap.EndInit();

            return bitmap;
        }

        #endregion
    }
}

 

▶ MainWindow.xaml

<Window x:Class="TestProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestProject"
    Width="800"
    Height="600"
    Title="이미지 롤 애니메이션(Roll Animation) 사용하기"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Grid>
        <Border
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            BorderThickness="1"
            BorderBrush="DarkGray">
            <local:ImageRollControl x:Name="imageRollControl"
               ImageSource="IMAGE\sample.png"
                Width="600"
                Height="400" />
        </Border>
        <StackPanel
            HorizontalAlignment="Right"
            VerticalAlignment="Bottom"
            Margin="10"
            Orientation="Horizontal">
            <Button Name="startButton"
                Width="100"
                Height="30"
                Content="Start" />
            <Button Name="stopButton"
                Margin="10 0 0 0"
                Width="100"
                Height="30"
                Content="Stop" />
        </StackPanel>
    </Grid>
</Window>

 

▶ MainWindow.xaml.cs

using System.Windows;

namespace TestProject
{
    /// <summary>
    /// 메인 윈도우
    /// </summary>
    public partial class MainWindow : Window
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainWindow()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            this.startButton.Click += startButton_Click;
            this.stopButton.Click  += stopButton_Click;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 시작 버튼 클릭시 처리하기 - startButton_Click(sender, e)

        /// <summary>
        /// 시작 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void startButton_Click(object sender, RoutedEventArgs e)
        {
            this.startButton.IsEnabled = false;
            this.stopButton.IsEnabled  = true;

            this.imageRollControl.Start();
        }

        #endregion
        #region 중단 버튼 클릭시 처리하기 - stopButton_Click(sender, e)

        /// <summary>
        /// 중단 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void stopButton_Click(object sender, RoutedEventArgs e)
        {
            this.startButton.IsEnabled = true;
            this.stopButton.IsEnabled  = false;

            this.imageRollControl.Stop();
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요