如何将图像集中在多阶段
-
01-10-2019 - |
题
找到了将图像定位在多屏幕上的功能...但是我不确定如何获得实际的图像宽度(对于单个或多个),并基于此更改_msi.viewportorigin x param。
有2行影响图像位置...一个是
_msi.ViewportOrigin = new Point(0, 0);
另一个是:
//if (layout == ImageLayout.Vertical) //single column
// X = ((_msi.ViewportWidth - subImages[i].Width) / 2);
我可以更改任何一个..但需要一些帮助。
从上述摘要中获取的代码:
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" />
解决方案
我同意这是令人困惑的,但是您应该能够做到这一点。
首先,您必须检查viewportwidth是否> 1(这意味着您的图像当前相对于父母而“较窄”。如果不是这种情况,则可以检查viewportotheight> 1(图像较短,您必须中心垂直)。
假设您发现视口宽度为> 1,即您在右侧有空的空间,并希望水平居中,则将视图设置为viewportorigin,以将视口移动到右侧。
例子: :viewportwidth是3。这意味着您的图像填充了可用宽度的1/3。您必须一次将其移至正确的宽度。 viewportorigin变为(-1,0)。
另一个例子: :viewportwidth是4。您的图像填充了可用宽度的1/4。如果将视口设置为-1.5,则视口实际将其宽度向右移动1.5倍,并实际上移至中心。
通用公式* 应该是fiewportorigin.x = - (viewportwidth -1) / 2
我建议你看看 Doc 并在纸上画一些草图,直到您弄清楚。
不隶属于 StackOverflow