none
动画问题 RRS feed

  • 问题

  • for (int i = 0; i <= NumItems; i++ )
                {
                    CarouselItem item = new CarouselItem();
                    item.MsgNumber.Text = String.Format("{0:00}", i);

                    item.Angle = i * ((Math.PI * 2) / NumItems);
                    Position.X = Math.Cos(item.Angle) * Radius.X;
                    Position.Y = Math.Sin(item.Angle) * Radius.Y;

                    Canvas.SetLeft(item, Position.X);
                    Canvas.SetTop(item, Position.Y);

                    Distance = 1 / (1 - (Position.Y / Perspective));

                    item.Opacity = item.ItemScale.ScaleX = item.ItemScale.ScaleY = Distance;

                    Items.Add(item);
                    CarouselCanvas.Children.Add(item);
                }
    以上一段代码是建立一个图片滚动的代码。图片绕y轴运动。
    这里涉及到了一个层的问题。最后一张图片应该显示在最后一层上,但是结果却是显示在第一层上。
    不知道这么说能不能说明白。
    这个能不能上传图片啊?那样更能直接说明问题。

    2009年6月22日 6:58

答案

  •     public partial class Page : UserControl
        {
            List<CarouselItem> Items;
            int NumItems = 8;
    
            Point Radius;
            Point Position;
    
            double Speed = .0125;
            double Distance;
            double Perspective = 300;
    
            public Page()
            {
                InitializeComponent();
    
                Items = new List<CarouselItem>(NumItems);
    
                Radius.X = 300;
                Radius.Y = -50;
    
                MouseControl.Width = Math.Abs(Radius.X * 2) + CarouselCanvas.Width;
                Canvas.SetLeft(MouseControl, -(Math.Abs(Radius.X)));
                Canvas.SetTop(MouseControl, (Math.Abs(Radius.Y) * 2));
                MouseControl.MouseMove += new MouseEventHandler(MouseControl_MouseMove);
    
                Canvas.SetLeft(CarouselCanvas, LayoutRoot.Width / 2 - CarouselCanvas.Width / 2);
                Canvas.SetTop(CarouselCanvas, LayoutRoot.Height / 2 - CarouselCanvas.Height / 2);
                BuildCarousel();
    
                Spin.Completed += new EventHandler(MoveCarousel);
                Spin.Begin();
            }
    
            void MouseControl_MouseMove(object sender, MouseEventArgs e)
            {
                Point MousePoint = e.GetPosition(MouseControl);
                double OffsetCalc = MousePoint.X - (MouseControl.Width / 2);
                Speed = -OffsetCalc / 10000;
                if (Speed < 0 && Speed < -0.0250) Speed = -0.0250;
                else if (Speed > 0 && Speed > 0.0250) Speed = 0.0250;
            }
    
            private void BuildCarousel()
            {
                for (int i = 0; i < NumItems; i++)
                {
                    CarouselItem item = new CarouselItem();
                    item.MsgNumber.Text = String.Format("{0:00}", i);
    
                    item.Angle = i * ((Math.PI * 2) / NumItems);
    
                    Position.X = Math.Cos(item.Angle) * Radius.X;
                    Position.Y = Math.Sin(item.Angle) * Radius.Y;
    
                    Canvas.SetLeft(item, Position.X);
                    Canvas.SetTop(item, Position.Y);
    
                    item.MouseEnter += new MouseEventHandler(item_MouseEnter);
                    item.MouseLeave += new MouseEventHandler(item_MouseLeave);
                    item.MouseLeftButtonUp += new MouseButtonEventHandler(item_MouseLeftButtonUp);
    
                    Distance = 1 / (1 - (Position.Y / Perspective));
                    item.Opacity = item.ItemScale.ScaleX = item.ItemScale.ScaleY = Distance;
    
                    Items.Add(item);
                    CarouselCanvas.Children.Add(item);
                }
            }
    
            void item_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                CarouselItem WhichItem = sender as CarouselItem;
                MsgSelected.Text = "You clicked: " + WhichItem.MsgNumber.Text;
            }
    
            void item_MouseLeave(object sender, MouseEventArgs e)
            {
                Spin.Begin();
            }
    
            void item_MouseEnter(object sender, MouseEventArgs e)
            {
                Spin.Stop();
            }
    
            private void MoveCarousel(object sender, EventArgs e)
            {
                foreach (CarouselItem item in Items)
                {
                    item.Angle -= Speed;
    
                    Position.X = Math.Cos(item.Angle) * Radius.X;
                    Position.Y = Math.Sin(item.Angle) * Radius.Y;
    
                    Canvas.SetLeft(item, Position.X);
                    Canvas.SetTop(item, Position.Y);
    
                    if (Radius.Y >= 0)
                    {
                        Distance = 1 * (1 - (Position.Y / Perspective));
                        Canvas.SetZIndex(item, -(int)Position.Y);
                    }
                    else
                    {
                        Distance = 1 / (1 - (Position.Y / Perspective));
                        Canvas.SetZIndex(item, (int)Position.Y);
                    }
    
                    item.Opacity = item.ItemScale.ScaleX = item.ItemScale.ScaleY = Distance;
                }
                Spin.Begin();
            }
        }
    2009年6月24日 3:08
    版主

全部回复

  • for (int i = 0; i <= NumItems; i++ )
                {
                    ....
                    Canvas.SetZIndex(item, NumItems -i);
                    ...
                }


    每个UserControl再附加上ZIndex属性就好了,ZIndex越大,呈现越靠前

    2009年6月22日 8:24
    版主
  • 恩,问题解决了。谢了。
    还有一个问题,想请教一下。
    foreach(CarouselItem item in Items)
                {
                    item.Angle -= Speed;
                    Position.X = Math.Cos(item.Angle) * Radius.X;
                    Position.Y = Math.Sign(item.Angle) * Radius.Y;

                    Canvas.SetLeft(item, Position.X);
                    Canvas.SetTop(item, Position.Y);

                    if (Radius.Y >= 0)
                    {
                        Distance = 1 * (1 - (Position.Y / Perspective));
                        Canvas.SetZIndex(item, -(int)Position.Y);
                    }
                    else
                    {
                        Distance = 1 / ( 1 - (Position.Y / Perspective));
                        Canvas.SetZIndex(item, (int)Position.Y);
                    }
                    item.Opacity = item.ItemScale.ScaleX = item.ItemScale.ScaleY = Distance;
                }
    以上代码是一个让图片滚动的程序。执行出来的效果是最后一张图片总是在最前面,我调试了一下z轴的坐标,但是不好用,不知道为什么。
    能帮我看一下吗?Speed是滚动的速度。

    2009年6月22日 11:46
  •  Canvas.SetZIndex(item, -(int)Position.Y);

    这里不对,你是2D做的3D投影算法吧,那每次变动之后,要计算z的位置,然后每次变换都要赋予新的ZIndex让他们呈现不同层次的显示
    2009年6月22日 12:38
    版主
  • 我做的确实是2D到3D的投影。
    初始话的时候,我用Canvas.SetZIndex(item, (int)Position.Y)固定了z轴的值,就如上一个问题所说的没有给z轴值。这个好用。
    但是在移动的时候,怎样更新z的值,我试了一下,没好用,还请熊大指点我一下。

    2009年6月22日 14:22
  • 你这个算法我看不太懂怎么映射的
    一般是2维映射为3D球算法
    先确定

    Θ(某点与求新连线AB在XY平面上投影线与X方向夹角)与Φ(是某点与求新连线AB与Z轴夹角)

    然后把它的2维坐标投影到3维平面上

    X = radius * Math.Cos(Θ) * Math.Sin(Φ);
    Y = radius * Math.Sin(Θ) * Math.Sin(Φ);
    Z = radius * Math.Cos(Φ);



    你的算法是

    Position.X = Math.Cos(item.Angle) * Radius.X;
    Position.Y = Math.Sign(item.Angle) * Radius.Y;



    这里你的半径还分X Y是什么意思呢?请解释你下并想清楚你的3D投影的数学原理,然后再整公式.

    2009年6月22日 14:39
    版主
  • 如果不懂算法的话,在Silverlight 3中你可以直接使用
    Perspective 3D来进行单一控件的3D变换,这样就省去自己整算法的麻烦,而且很方便,可以看看
    2009年6月22日 14:46
    版主
  • public partial class Page : UserControl
        {
            List<CarouselItem> Items;
            int NumItems = 8;
            Point Radius;
            Point Origin;
            Point Position;
            double Speed = .005;
            double Distance;
            double Perspective = 300;

            Storyboard Spin = new Storyboard();

            public Page()
            {
                InitializeComponent();

                Items = new List<CarouselItem>(NumItems);

                Radius.X = 300;
                Radius.Y = -50;

                Origin.X = LayoutRoot.Width / 2 - CarouselCanvas.Width / 2;
                Origin.Y = LayoutRoot.Height / 2 - CarouselCanvas.Height / 2;

                Canvas.SetLeft(CarouselCanvas, LayoutRoot.Width / 2 - CarouselCanvas.Width / 2);
                Canvas.SetTop(CarouselCanvas, LayoutRoot.Height / 2 - CarouselCanvas.Height / 2);

                BuildCarousel();

                Spin.Completed += new EventHandler(MoveCarousel);
                Spin.Begin();
            }

            private void BuildCarousel()
            {
                for (int i = 0; i <= NumItems; i++ )
                {
                    CarouselItem item = new CarouselItem();
                    item.MsgNumber.Text = String.Format("{0:00}", i);

                    item.Angle = i * ((Math.PI * 2) / NumItems);
                    Position.X = Math.Cos(item.Angle) * Radius.X;
                    Position.Y = Math.Sin(item.Angle) * Radius.Y;

                    Canvas.SetLeft(item, Position.X);
                    Canvas.SetTop(item, Position.Y);
                    Canvas.SetZIndex(item, (int)Position.Y);

                    Distance = 1 / (1 - (Position.Y / Perspective));

                    item.Opacity = item.ItemScale.ScaleX = item.ItemScale.ScaleY = Distance;

                    Items.Add(item);
                    CarouselCanvas.Children.Add(item);

                    item.MouseEnter += new MouseEventHandler(item_MouseEnter);
                    item.MouseLeave += new MouseEventHandler(item_MouseLeave);
                }
            }

            private void MoveCarousel(object sender, EventArgs e)
            {
                foreach(CarouselItem item in Items)
                {
                    Position.X = Math.Cos(item.Angle) * Radius.X;
                    Position.Y = Math.Sign(item.Angle) * Radius.Y;

                    Canvas.SetLeft(item, Position.X + Origin.X);
                    Canvas.SetTop(item, Position.Y + Origin.Y);

                    if (Radius.Y >= 0)
                    {
                        Distance = 1 * (1 - (Position.Y / Perspective));
                        Canvas.SetZIndex(item, -(int)Position.Y);
                    }
                    else
                    {
                        Distance = 1 / ( 1 - (Position.Y / Perspective));
                        Canvas.SetZIndex(item, (int)Position.Y);
                    }
                    item.Angle -= Speed;
                    item.Opacity = item.ItemScale.ScaleX = item.ItemScale.ScaleY = Distance;
                }

                Spin.Begin();
            }

            void item_MouseEnter(object sender, MouseEventArgs e)
            {
                Spin.Stop();
            }

            void item_MouseLeave(object sender, MouseEventArgs e)
            {
                Spin.Begin();
            }
        }
    这个是整个程序的代码。xaml中基本上没有什么代码。
    是动态生成的。
    执行出来的效果很不理想。

    2009年6月23日 14:31
  • 就是说啊
    我说你的算法
    Radius.X = 300;
    Radius.Y = -50;
    这里指定半径的x y我没看懂是什么意思,貌似没有数学根据,半径应该为一个值,而不是一个点,你是根据哪个数学公式写出来的这个算法?
    2009年6月23日 14:51
    版主
  • jeff paries写的silverlight Animation.
    我觉得jeff写的不应该有问题,但是我就执行不出来要求的效果,比较郁闷。
    斑竹能帮我看看哪里出了问题吗?
    2009年6月23日 14:55
  • 熊大有没有msn什么的,可以告诉我吗?
    donaldzj120@hotmail.com
    可以发到这个
    邮箱里。
    2009年6月23日 14:57
  • .....你这算法抄的有问题吧,我搜他的书里面没有

    Radius.X这东西
    2009年6月24日 0:46
    版主
  • ?不太可能吧。
    silverlight Animation 第7章里,2d到3d,肯定有啊
    2009年6月24日 0:49
  • 版主所看的是在网上吗?还是书?
    如果是网上的话,把网址告诉我好吗?
    感觉咱俩说的不是一本书呢。呵呵

    2009年6月24日 1:14
  •     public partial class Page : UserControl
        {
            List<CarouselItem> Items;
            int NumItems = 8;
    
            Point Radius;
            Point Position;
    
            double Speed = .0125;
            double Distance;
            double Perspective = 300;
    
            public Page()
            {
                InitializeComponent();
    
                Items = new List<CarouselItem>(NumItems);
    
                Radius.X = 300;
                Radius.Y = -50;
    
                MouseControl.Width = Math.Abs(Radius.X * 2) + CarouselCanvas.Width;
                Canvas.SetLeft(MouseControl, -(Math.Abs(Radius.X)));
                Canvas.SetTop(MouseControl, (Math.Abs(Radius.Y) * 2));
                MouseControl.MouseMove += new MouseEventHandler(MouseControl_MouseMove);
    
                Canvas.SetLeft(CarouselCanvas, LayoutRoot.Width / 2 - CarouselCanvas.Width / 2);
                Canvas.SetTop(CarouselCanvas, LayoutRoot.Height / 2 - CarouselCanvas.Height / 2);
                BuildCarousel();
    
                Spin.Completed += new EventHandler(MoveCarousel);
                Spin.Begin();
            }
    
            void MouseControl_MouseMove(object sender, MouseEventArgs e)
            {
                Point MousePoint = e.GetPosition(MouseControl);
                double OffsetCalc = MousePoint.X - (MouseControl.Width / 2);
                Speed = -OffsetCalc / 10000;
                if (Speed < 0 && Speed < -0.0250) Speed = -0.0250;
                else if (Speed > 0 && Speed > 0.0250) Speed = 0.0250;
            }
    
            private void BuildCarousel()
            {
                for (int i = 0; i < NumItems; i++)
                {
                    CarouselItem item = new CarouselItem();
                    item.MsgNumber.Text = String.Format("{0:00}", i);
    
                    item.Angle = i * ((Math.PI * 2) / NumItems);
    
                    Position.X = Math.Cos(item.Angle) * Radius.X;
                    Position.Y = Math.Sin(item.Angle) * Radius.Y;
    
                    Canvas.SetLeft(item, Position.X);
                    Canvas.SetTop(item, Position.Y);
    
                    item.MouseEnter += new MouseEventHandler(item_MouseEnter);
                    item.MouseLeave += new MouseEventHandler(item_MouseLeave);
                    item.MouseLeftButtonUp += new MouseButtonEventHandler(item_MouseLeftButtonUp);
    
                    Distance = 1 / (1 - (Position.Y / Perspective));
                    item.Opacity = item.ItemScale.ScaleX = item.ItemScale.ScaleY = Distance;
    
                    Items.Add(item);
                    CarouselCanvas.Children.Add(item);
                }
            }
    
            void item_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                CarouselItem WhichItem = sender as CarouselItem;
                MsgSelected.Text = "You clicked: " + WhichItem.MsgNumber.Text;
            }
    
            void item_MouseLeave(object sender, MouseEventArgs e)
            {
                Spin.Begin();
            }
    
            void item_MouseEnter(object sender, MouseEventArgs e)
            {
                Spin.Stop();
            }
    
            private void MoveCarousel(object sender, EventArgs e)
            {
                foreach (CarouselItem item in Items)
                {
                    item.Angle -= Speed;
    
                    Position.X = Math.Cos(item.Angle) * Radius.X;
                    Position.Y = Math.Sin(item.Angle) * Radius.Y;
    
                    Canvas.SetLeft(item, Position.X);
                    Canvas.SetTop(item, Position.Y);
    
                    if (Radius.Y >= 0)
                    {
                        Distance = 1 * (1 - (Position.Y / Perspective));
                        Canvas.SetZIndex(item, -(int)Position.Y);
                    }
                    else
                    {
                        Distance = 1 / (1 - (Position.Y / Perspective));
                        Canvas.SetZIndex(item, (int)Position.Y);
                    }
    
                    item.Opacity = item.ItemScale.ScaleX = item.ItemScale.ScaleY = Distance;
                }
                Spin.Begin();
            }
        }
    2009年6月24日 3:08
    版主
  • 谢谢斑竹。问题解决了。
    请问一下,源码是哪里来的?
    是书上光盘的吗?我买了书,但是没有源码,如果是书上的代码能给我发一份吗?
    先谢谢了。

    2009年6月24日 11:53