从绑定设置 HeightRequest/WidthRequest 时 FFImageLoading、SVGCachedImage 模糊
FFImageLoading, SVGCachedImage blurry when setting HeightRequest/WidthRequest from a binding
我正在使用 FFImageLoading 在我的 Xamarin.Forms 项目中显示 svg 图标。我的理解是必须明确设置高度和宽度请求才能正确呈现 SVG。每当我尝试将 Height/Width 请求绑定到 ViewModel 上的值时,我都会得到很多像素化(我有这个需要,因为所需的大小取决于数据)。如果我明确设置大小,一切看起来都很好。
每当 Height/Width 请求的绑定发生变化时,SvgCachedImage 不会重新绘制 SVG 吗?
如果不是,有没有办法让我在大小改变时明确强制它们失效并重绘?
模糊问题已通过将水平和垂直选项设置为填充而不是中心来解决:
<Grid>
<ffimageloadingsvg:SvgCachedImage BackgroundColor="Transparent"
Margin="{Binding HarmonicIconMargin}"
HorizontalOptions="Fill"
VerticalOptions="Fill"
WidthRequest="{Binding HarmonicIconWidth}"
HeightRequest="{Binding HarmonicIconWidth}"
Source="{Binding CurrentTestItem, Converter={StaticResource TestItemToHarmonicIconConverter}}" />
</Grid>
那时它似乎忽略了 height/width 请求。我本可以尝试更多(也许请求太多 space),但我发现将边距绑定到计算的 属性 有效地使我能够控制 SVG 图像的大小,同时不会导致它变得模糊。
为了解决缩放视图时svg模糊问题,
- 更改
SvgImageSource.VectorWidth
或SvgImageSource.VectorHeight
- 重新加载图像
protected override void OnSizeAllocated(double width, double height)
{
if (0 < width && 0 < height && && Source is SvgImageSource imageSource)
{
imageSource.VectorWidth = (int)Math.Ceiling(width);
imageSource.VectorHeight = (int)Math.Ceiling(height);
svgImage.ReloadImage();
base.OnSizeAllocated(width, height);
}
}
根据FFImageLoading source code,SVG图像大小由SvgImageSource.VectorWidth
或SvgImageSource.VectorHeight
决定。
double sizeX = VectorWidth;
double sizeY = VectorHeight;
if (UseDipUnits)
{
sizeX = VectorWidth.DpToPixels();
sizeY = VectorHeight.DpToPixels();
}
if (sizeX <= 0 && sizeY <= 0)
{
if (picture.CullRect.Width > 0)
sizeX = picture.CullRect.Width;
else
sizeX = 400;
if (picture.CullRect.Height > 0)
sizeY = picture.CullRect.Height;
else
sizeY = 400;
}
else if (sizeX > 0 && sizeY <= 0)
{
sizeY = (int)(sizeX / picture.CullRect.Width * picture.CullRect.Height);
}
else if (sizeX <= 0 && sizeY > 0)
{
sizeX = (int)(sizeY / picture.CullRect.Height * picture.CullRect.Width);
}
resolvedData.ImageInformation.SetType(ImageInformation.ImageType.SVG);
using (var bitmap = new SKBitmap(new SKImageInfo((int)sizeX, (int)sizeY)))
using (var canvas = new SKCanvas(bitmap))
using (var paint = new SKPaint())
{
canvas.Clear(SKColors.Transparent);
var scaleX = (float)sizeX / picture.CullRect.Width;
var scaleY = (float)sizeY / picture.CullRect.Height;
var matrix = SKMatrix.MakeScale(scaleX, scaleY);
canvas.DrawPicture(picture, ref matrix, paint);
canvas.Flush();
token.ThrowIfCancellationRequested();
return await Decode(picture, bitmap, resolvedData).ConfigureAwait(false);
}
binding
导致像素化,因为视图的初始宽度和高度用作 VectorWidth
和 VectorHeight
,即 -1
或您设置为 [=20= 的东西] 用于绑定 属性。因此,您的 svg 图像分辨率一开始设置得太低,然后绑定过程在不重绘 svg 图像的情况下放大视图。
我正在使用 FFImageLoading 在我的 Xamarin.Forms 项目中显示 svg 图标。我的理解是必须明确设置高度和宽度请求才能正确呈现 SVG。每当我尝试将 Height/Width 请求绑定到 ViewModel 上的值时,我都会得到很多像素化(我有这个需要,因为所需的大小取决于数据)。如果我明确设置大小,一切看起来都很好。
每当 Height/Width 请求的绑定发生变化时,SvgCachedImage 不会重新绘制 SVG 吗?
如果不是,有没有办法让我在大小改变时明确强制它们失效并重绘?
模糊问题已通过将水平和垂直选项设置为填充而不是中心来解决:
<Grid>
<ffimageloadingsvg:SvgCachedImage BackgroundColor="Transparent"
Margin="{Binding HarmonicIconMargin}"
HorizontalOptions="Fill"
VerticalOptions="Fill"
WidthRequest="{Binding HarmonicIconWidth}"
HeightRequest="{Binding HarmonicIconWidth}"
Source="{Binding CurrentTestItem, Converter={StaticResource TestItemToHarmonicIconConverter}}" />
</Grid>
那时它似乎忽略了 height/width 请求。我本可以尝试更多(也许请求太多 space),但我发现将边距绑定到计算的 属性 有效地使我能够控制 SVG 图像的大小,同时不会导致它变得模糊。
为了解决缩放视图时svg模糊问题,
- 更改
SvgImageSource.VectorWidth
或SvgImageSource.VectorHeight
- 重新加载图像
protected override void OnSizeAllocated(double width, double height)
{
if (0 < width && 0 < height && && Source is SvgImageSource imageSource)
{
imageSource.VectorWidth = (int)Math.Ceiling(width);
imageSource.VectorHeight = (int)Math.Ceiling(height);
svgImage.ReloadImage();
base.OnSizeAllocated(width, height);
}
}
根据FFImageLoading source code,SVG图像大小由SvgImageSource.VectorWidth
或SvgImageSource.VectorHeight
决定。
double sizeX = VectorWidth;
double sizeY = VectorHeight;
if (UseDipUnits)
{
sizeX = VectorWidth.DpToPixels();
sizeY = VectorHeight.DpToPixels();
}
if (sizeX <= 0 && sizeY <= 0)
{
if (picture.CullRect.Width > 0)
sizeX = picture.CullRect.Width;
else
sizeX = 400;
if (picture.CullRect.Height > 0)
sizeY = picture.CullRect.Height;
else
sizeY = 400;
}
else if (sizeX > 0 && sizeY <= 0)
{
sizeY = (int)(sizeX / picture.CullRect.Width * picture.CullRect.Height);
}
else if (sizeX <= 0 && sizeY > 0)
{
sizeX = (int)(sizeY / picture.CullRect.Height * picture.CullRect.Width);
}
resolvedData.ImageInformation.SetType(ImageInformation.ImageType.SVG);
using (var bitmap = new SKBitmap(new SKImageInfo((int)sizeX, (int)sizeY)))
using (var canvas = new SKCanvas(bitmap))
using (var paint = new SKPaint())
{
canvas.Clear(SKColors.Transparent);
var scaleX = (float)sizeX / picture.CullRect.Width;
var scaleY = (float)sizeY / picture.CullRect.Height;
var matrix = SKMatrix.MakeScale(scaleX, scaleY);
canvas.DrawPicture(picture, ref matrix, paint);
canvas.Flush();
token.ThrowIfCancellationRequested();
return await Decode(picture, bitmap, resolvedData).ConfigureAwait(false);
}
binding
导致像素化,因为视图的初始宽度和高度用作 VectorWidth
和 VectorHeight
,即 -1
或您设置为 [=20= 的东西] 用于绑定 属性。因此,您的 svg 图像分辨率一开始设置得太低,然后绑定过程在不重绘 svg 图像的情况下放大视图。