【问题标题】:How to center image in MultiScaleImage如何在 MultiScaleImage 中居中图像
【发布时间】:2010-09-08 06:38:14
【问题描述】:

找到在多尺度图像中定位图像的函数...但我不确定如何获取实际图像宽度(单个或多个)并基于此更改 _msi.ViewportOrigin x 参数。

有 2 行会影响图像位置... 1 是

_msi.ViewportOrigin = new Point(0, 0);

另一个是:

//if (layout == ImageLayout.Vertical) //single column
//    X = ((_msi.ViewportWidth - subImages[i].Width) / 2);

我可以更改其中任何一个.. 但需要一些帮助。

以上sn-ps取自的代码:

 private void ArrangeImagesTile(ImageLayout layout)
        {
            if (_msi.ActualWidth <= 0 || _msi.ActualHeight <= 0)
                return;

            _lastMousePos = new Point(0, 0);
            _msi.ViewportOrigin = new Point(0, 0);
            _msi.ViewportWidth = 1;


            Storyboard moveStoryboard = initStoryboard();

            double containerAspectRatio = this._msi.ActualWidth / this._msi.ActualHeight;
            double spaceBetweenImages = 0.005;

            List<SubImage> subImages = new List<SubImage>();
            _imagesToShow.ForEach(subImage => subImages.Add(new SubImage(subImage)));

            // Capture the total width of all images
            double totalImagesWidth = 0.0;
            subImages.ForEach(subImage => totalImagesWidth += subImage.Width);

            // Calculate the total number of rows required to display all the images
            int numRows = 1; // layout - horizontal
            if (layout == ImageLayout.One)
                numRows = 1; //(int)Math.Sqrt((totalImagesWidth / containerAspectRatio) + 1);
            else if (layout == ImageLayout.Four) //.Vertical)
                numRows = 2; // subImages.Count;

            // Assign images to each row
            List<Row> rows = new List<Row>(numRows);
            for (int i = 0; i < numRows; i++)
                rows.Add(new Row(spaceBetweenImages));

            double widthPerRow = totalImagesWidth / numRows;
            double imagesWidth = 0;

            // Separate the images into rows. The total width of all images in a row should not exceed widthPerRow
            for (int i = 0, j = 0; i < numRows; i++, imagesWidth = 0)
            {
                while (imagesWidth < widthPerRow && j < subImages.Count)
                {
                    rows[i].AddImage(subImages[j]);
                    subImages[j].RowNum = i;
                    imagesWidth += subImages[j++].Width;
                }
            }

            // At this point in time the subimage height is 1 
            // If we assume that the total height is also 1 we need to scale the subimages to fit within a total height of 1
            // If the total height is 1, the total width is aspectRatio. Hence (aspectRatio)/(total width of all images in a row) is the scaling factor.
            // Added later: take into account spacing between images
            rows.ForEach(Row => Row.Scale(containerAspectRatio));

            // Calculate the total height, with space between images, of the images across all rows
            // Also adjust the colNum for each image
            double totalImagesHeight = (numRows - 1) * spaceBetweenImages;
            rows.ForEach(Row => totalImagesHeight += Row.Height);

            // The totalImagesHeight should not exceed 1. 
            // if it does, we need to scale all images by a factor of (1 / totalImagesHeight)
            if (totalImagesHeight > 1)
            {
                subImages.ForEach(subImage => subImage.Scale(1 / (totalImagesHeight + spaceBetweenImages)));
                totalImagesHeight = (numRows - 1) * spaceBetweenImages;
                rows.ForEach(Row => totalImagesHeight += Row.Height);
            }

            // Calculate the top and bottom margin
            double margin = (1 - totalImagesHeight) / 2;

            if (_imagesToHide != null)
            {
                // First hide all the images that should not be displayed
                _imagesToHide.ForEach(subImage =>
                {
                    //Do not use opacity for this as it slows down the animation after a few arranges
                    subImage.ViewportWidth = 0;
                });
            }

            // Then display the displayable images to scale
            for (int i = 0; i < _imagesToShow.Count; i++)
            {
                double X = rows[subImages[i].RowNum].CalcX(subImages[i].ColNum);
                //if (layout == ImageLayout.Vertical) //single column
                //    X = ((_msi.ViewportWidth - subImages[i].Width) / 2);

                double Y = margin;
                for (int j = 0; j < subImages[i].RowNum; j++)
                    Y += spaceBetweenImages + rows[j].Height;

                _imagesToShow[i].ViewportWidth = containerAspectRatio / subImages[i].Width;
                animateImage(moveStoryboard, _imagesToShow[i], new Point(-(X / subImages[i].Width), -(Y / subImages[i].Width)));    // for animation, use this statement instead of the next one                
                _imagesToShow[i].Opacity = 1.0;
            }

            if (ImagesRearranged != null)
            {
                ImagesRearranged(this, EventArgs.Empty);
            }

            // Play Storyboard
            moveStoryboard.Begin();
        }

在 msi 中打开图像时转到上述函数的先前代码参考:

后端:

private void RootMultiScaleImage_Loaded(object sender, RoutedEventArgs e)
        {
            // Use the mid point of the image to zoom from    
            var xx = (MultiScaleImage) sender;
            xx.ZoomAboutLogicalPoint(1, 0.5, 0.5);
        }

前端:

 <ControlTemplate x:Key="DeepZoomerControlTemplate" TargetType="zoom:DeepZoomer">
            <Grid>
<MultiScaleImage x:Name="RootMultiScaleImage" Loaded="RootMultiScaleImage_Loaded" />

【问题讨论】:

  • 默认缩放将显示整个图像填充控件中的所有可用空间。当图像方面与控件方面不匹配时,您是在问如何将垂直或水平居中?
  • 是的,对于水平,当图像方面与控制方面不匹配时。
  • 你能更详细地描述这个问题吗?也许上传一两个屏幕截图?
  • 新增定位功能,_msi.ViewportOrigin = new Point(0, 0);将图像(顶部,左侧)定位到大约是应用程序宽度的 100% 的多尺度图像。我希望将 msi 控件中的图像居中。图片宽度可能会有所不同。

标签: .net silverlight image xaml deepzoom


【解决方案1】:

我同意这很令人困惑,但是使用 viewPortWidth 和 viewPortOrigin 你应该可以做到。

  • 首先您必须检查 ViewPortWidth 是否 > 1(这意味着您的图像当前相对于父图像“更窄”。如果不是这种情况,您可以检查 ViewPortHeight 是否 > 1(图像是更短,你必须垂直居中)。

  • 假设您发现 ViewPortWidth > 1,即您在右侧有空白空间并希望将视口水平居中,您将 ViewPortOrigin 设置为负值以将视口向右移动。

示例:ViewPortWidth 为 3。这意味着您的图像填充了可用宽度的 1/3。您必须将其向右移动一倍其宽度。 ViewportOrigin 变为 (-1, 0)。

另一个示例:ViewPortWidth 为 4。您的图像填充了可用宽度的 1/4。如果您将 ViewPortOrigin 设置为 -1.5,则视口实际上会向右移动 1.5 倍其宽度并实际移动到中心。

一般公式*应该是 ViewPortOrigin.x = - (ViewPortWidth - 1) / 2

我建议你看看doc,然后在纸上画一些草图,直到你弄清楚为止。

【讨论】:

  • 如果我的回答确实解决了您的问题,您介意奖励赏金吗? (这违反礼节吗?)
  • 不,我不介意,我认为这是自动的,直到收到邮件提醒我这样做,这是我第一次提供赏金。
猜你喜欢
  • 2015-04-04
  • 2015-08-19
  • 1970-01-01
  • 2017-08-02
  • 2015-08-12
  • 2020-11-22
  • 2012-05-06
  • 2014-04-09
相关资源
最近更新 更多