locked
Storyboard和Canvas RRS feed

  • 问题

  • 我做一个图片浏览的控件,用Canvas做容器,里面包含一个子Canvas,子Canvas里面又很多Image,然后我控制子Canvas的坐标,实现滚动显示,当用户手指拖动图片超过宽度一半就滑动到下一张图片,否则回到当前图片。但是我发现图片到第五张时会有一个闪动效果;就是第五张滑动一下,图片只出来一半不到,滑动指定位置后才出来;,布局代码如下:

        <Canvas x:Name="LayoutRoot" ManipulationDelta="canImages_ManipulationDelta" ManipulationStarted="canImages_ManipulationStarted" ManipulationCompleted="LayoutRoot_ManipulationCompleted">
            <Canvas x:Name="canImages"  Canvas.ZIndex="0" Background="#FF7CDEF1"/>
            <StackPanel x:Name="spEllipse" Canvas.ZIndex="1"  Height="20" Width="480" Orientation="Horizontal" Background="#FF8F9295" Opacity="0.5" Margin="0">
            </StackPanel>
        </Canvas>

    然后代码如下:

            private double startX;//用户操作开始时容器位置
            private void LayoutRoot_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
            {
                startX = Canvas.GetLeft(canImages);
                double y = Canvas.GetTop(spEllipse);
                ShowStackPanel(y, y >= this.LayoutRoot.Height ? y - 60 : y + 60);
            }
            /// <summary>
            /// 用户屏幕滑动
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void LayoutRoot_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
            {
                double value_x = e.CumulativeManipulation.Translation.X;
                Canvas.SetLeft(canImages, value_x + startX);
            }
            /// <summary>
            /// 操作完成时判断是否跳到下一张图片
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void LayoutRoot_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
            {
                double endX = Canvas.GetLeft(canImages);
                if (Math.Abs(endX - startX) >= this.LayoutRoot.Width / 2)
                {
                    int index = endX < startX ? cIndex + 1 : cIndex - 1;
                    if (index <= 0)
                        index = 0;
                    if (index >= smallSource.Length - 1)
                        index = smallSource.Length - 1;
                    Show(index);
                }
                else
                {
                    Show(cIndex);
                }
            }
    
            /// 滑动到第几张图片
            /// </summary>
            /// <param name="index"></param>
            private void Show(int index)
            {
                double endX = 0 - index * this.LayoutRoot.Width;
                double sx = Canvas.GetLeft(canImages);
                if (endX != sx)
                {
                    Storyboard board = new Storyboard();
                    board.Completed += new EventHandler(ShowCompleted);
                    DoubleAnimation da = new DoubleAnimation();
                    da.From = sx;
                    da.To = endX;
                    da.Duration = new Duration(TimeSpan.FromMilliseconds(500));
                    Storyboard.SetTarget(da, canImages);
                    Storyboard.SetTargetProperty(da, new PropertyPath(Canvas.LeftProperty));
                    board.Children.Add(da);
                    board.Begin();
                    ellipse[cIndex].Fill = null;
                    ellipse[index].Fill = scb;
                    cIndex = index;
                }
                else
                {
                    double y = Canvas.GetTop(spEllipse);
                    ShowStackPanel(y, y >= this.LayoutRoot.Height ? y - 60 : y + 60);
                }
            }

    如上图,移动只有图片一部分,滑动完后才显示整张图片 

    2012年12月21日 9:05

答案

  • 你好,

    我测试你的代码,确实是这种情况。StoryBoard的宽度不能超过2000,虽然你设置了canvas为2400。

    所以你的StoryBoard就只有2000(width),这里面包括4张完整图片(4*480),再加上一小部分的图片(80)。 在这种情况下,我建议你StoryBoard不超过2000或不使用StoryBoard。


    Mark Yu - MSFT
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    2012年12月25日 8:56
    版主

全部回复

  • 自己发现如果不适用StoryBoard滑动,直接设置坐标,没这种问题
    2012年12月21日 9:28
  • 没人吗,我有源码,帮忙看下问题,有时间的朋友留下邮箱。感激不尽
    2012年12月22日 8:18
  • 你好,

    你可以把源码(精简过,不涉及隐私的)上传到skydrive吗?然后把链接贴到这里,我会去下载的


    Mark Yu - MSFT
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.



    2012年12月24日 7:05
    版主
  • 谢谢,源码路径 https://skydrive.live.com/redir?resid=B970ABAC86ED6D0B!128 很简单的滑动,最后一张图片滑动的时候显示不出来

    2012年12月25日 1:36
  • 你好,

    我测试你的代码,确实是这种情况。StoryBoard的宽度不能超过2000,虽然你设置了canvas为2400。

    所以你的StoryBoard就只有2000(width),这里面包括4张完整图片(4*480),再加上一小部分的图片(80)。 在这种情况下,我建议你StoryBoard不超过2000或不使用StoryBoard。


    Mark Yu - MSFT
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    2012年12月25日 8:56
    版主
  • 原来如此,现在还有2点疑问:

    1.我现在做法是去掉了canavs容器,直接移动里面所有image坐标,发现没这个问题;

    2.如果不用StoaryBoard,那这种平滑移动还可以用什么方法?

    2012年12月25日 9:08
  • 你好,

    1.你是否可以提供你的代码告诉我们你是怎么做的?

    2.如果你用XNA的话,你可以用XNA做:

    http://www.silverlightshow.net/items/XNA-for-Silverlight-developers-Part-4-Animation-frame-based.aspx


    Mark Yu - MSFT
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年12月25日 10:30
    版主
  • 1.我的意思是一个Canvas里包含很多图片,然后滑动时去计算所有图片的位置,然后移动,这样相比直接移动一个容器来说比较麻烦,不知道有性能问题没和好
    2012年12月26日 1:26
  • 来,我来给你说,这个我做过,很简单的。

    <Canvas>
                <Canvas  x:Name="CanvasImageView" CacheMode="BitmapCache" Canvas.Left="-480">
                    <Grid Style="{StaticResource GridStyle}" Canvas.Left="5" >
                        <Image Source="{Binding Path=LeftFrame}"/>
                    </Grid>
                    <Grid  x:Name="GridMidFrame" Style="{StaticResource GridStyle}" Canvas.Left="485">
                        <Image x:Name="ImageMidFrame" Source="{Binding Path=MidFrame}"/>
                    </Grid>
                    <Grid Style="{StaticResource GridStyle}" Canvas.Left="965">
                        <Image Source="{Binding Path=RightFrame}"/>
                    </Grid>
                </Canvas>
     </Canvas>

    你的容器里面只需要包含三张图片。

    当滑动的时候触发DragDelta事件,在事件里面去修改CanvasImageView的位置。

    当松手的时候就去判断 滑动距离是否小于滑动最小距离,如果小于则,回滚,如果大于,则判断是正还是负,这样就去滚动到下一页 or 上一页。

    滚动结束后, CanvasImageView的位置应该是 0 or 960

    这时 将CanvasImageView的位置设置为480 并去重新修改三张图片的值和索引的值。

    2012年12月28日 10:22