图层蒙版的蒙版。核心动画
Mask of layer mask. Core animation
我深入研究了 Core Animation 并且在图层蒙版方面遇到了一些问题
出于研究原因,我尝试制作一个复杂的 UI 透明层
此视图已并放入ViewController
public class TestView : UIView
{
public TestView()
{
Layer.Delegate = this;
Frame = new CGRect(100f,200f, 100f, 100f);
}
public override void LayoutSublayersOfLayer(CALayer layer)
{
base.LayoutSublayersOfLayer(layer);
var bounds = Bounds;
var circleFrame = new CGRect(20, 20, 60, 60);
var imageFrame = new CGRect(30, 30, 40, 40);
Layer.BorderWidth = 5;
Layer.BorderColor = UIColor.Red.CGColor;
Layer.CornerRadius = 4;
var gradientLayer = new CAGradientLayer();
gradientLayer.Colors = new[] { UIColor.Green.CGColor, UIColor.Red.CGColor };
gradientLayer.Frame = bounds;
Layer.AddSublayer(gradientLayer);
var maskOfGradientLayer = new CAShapeLayer();
var path = UIBezierPath.FromRoundedRect(circleFrame, 30);
path.UsesEvenOddFillRule = true;
maskOfGradientLayer.Path = path.CGPath;
maskOfGradientLayer.FillRule = CAShapeLayer.FillRuleEvenOdd;
maskOfGradientLayer.FillColor = UIColor.Black.CGColor;
maskOfGradientLayer.Frame = bounds;
gradientLayer.Mask = maskOfGradientLayer;
var maskOfMaskLayer = new CAShapeLayer();
maskOfMaskLayer.Frame = imageFrame;
maskOfMaskLayer.FillColor = UIColor.Black.CGColor;
maskOfMaskLayer.Contents = Bundles.ImageOff.CGImage;
Layer.AddSublayer(maskOfMaskLayer);
}
}
我有,这正是我想要的。
不过我也想把圆形做成透明的而不是黑色。
我试过这样做maskOfGradientLayer.Mask = maskOfMaskLayer.
但是这样maskOfMaskLayer
什么都不做!它不像面具必须做的那样工作。
我该怎么办?
But I also want can to make transparent in circle instead black color.
解决方案探索版:
你也可以用UIBezierPath画你想要的,设置为maskOfMaskLayer
:
var maskOfMaskLayer = new CAShapeLayer();
maskOfMaskLayer.Frame = imageFrame;
maskOfMaskLayer.FillColor = UIColor.Black.CGColor;
maskOfMaskLayer.Contents = Bundles.ImageOff.CGImage;
Layer.AddSublayer(maskOfMaskLayer);
上行代码替换为:
UIBezierPath offCirclePath = new UIBezierPath();
// draw an arc
offCirclePath.AddArc(new CGPoint(50, 50), circleFrame.Width / 3, (nfloat)(1.75 * Math.PI), (nfloat)(1.25 * Math.PI), true);
//draw a line
offCirclePath.MoveTo(new CGPoint(50, 30));
offCirclePath.AddLineTo(new CGPoint(50, 45));
//set to maskOfMaskLayer
var maskOfMaskLayer = new CAShapeLayer();
maskOfMaskLayer.FillColor = UIColor.Clear.CGColor;
maskOfMaskLayer.Path = offCirclePath.CGPath;
maskOfMaskLayer.LineWidth = 5;
maskOfMaskLayer.StrokeColor = UIColor.White.CGColor;
maskOfMaskLayer.LineCap = new NSString("round");
Layer.AddSublayer(maskOfMaskLayer);
其他代码未更改。
But I from starts thought about setting any custom image.
方案二:(方向错误)
我测试过CAShapeLayer
不能有这个从图片变色的功能。 CAShapeLayer Class
但是,我发现 UIImageView
Can do that.There 是 it.This 的 TintColor
属性 属性 来自 UiView。UIView.TintColor Property。
var maskOfMaskLayer = new CAShapeLayer();
maskOfMaskLayer.Frame = imageFrame;
maskOfMaskLayer.FillColor = UIColor.Black.CGColor;
maskOfMaskLayer.Contents = Bundles.ImageOff.CGImage;
Layer.AddSublayer(maskOfMaskLayer);
更改为:
UIImageView imageView = new UIImageView();
imageView.Frame = imageFrame;
imageView.Image = Bundles.ImageOff;
imageView.TintColor = UIColor.White;
AddSubview(imageView);
正确解:
抱歉误解了真正想要的效果,更新如下:
Layer.Mask = maskOfMaskLayer;
如果你用AddSublayer
只是把你的图像覆盖在Layer上,Layer.Mask
是相反的效果,它只显示覆盖部分的背景,其余区域将被覆盖白色.CALayer.Mask
所有需要做的就是通过 Core Graphics 反转图像颜色,任何颜色透明,透明任何颜色。在这种情况下,黑色就足够了
public static UIImage GetRevertImage(UIImage image, CGRect rect, CGRect cropFrame)
{
UIGraphics.BeginImageContextWithOptions(rect.Size, false, 1);
UIColor.Black.SetColor();
UIGraphics.RectFill(rect);
image.Draw(cropFrame, CGBlendMode.DestinationOut, 1);
var newImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return newImage;
}
并将遮罩层的遮罩设置为父层
Layer.Mask = maskOfMaskLayer;
代码的最终版本:
public class TestView : UIView
{
public TestView()
{
Layer.Delegate = this;
Frame = new CGRect(50f, 50f, 100f, 100f);
}
public override void LayoutSublayersOfLayer(CALayer layer)
{
base.LayoutSublayersOfLayer(layer);
var bounds = Bounds;
var circleFrame = new CGRect(20, 20, 60, 60);
var imageFrame = new CGRect(30, 30, 40, 40);
Layer.BorderWidth = 5;
Layer.BorderColor = UIColor.Red.CGColor;
Layer.CornerRadius = 4;
Layer.MasksToBounds = true;
var gradientLayer = new CAGradientLayer();
gradientLayer.Colors = new[] {UIColor.Green.CGColor, UIColor.Red.CGColor};
gradientLayer.Frame = bounds;
Layer.AddSublayer(gradientLayer);
var maskOfGradientLayer = new CAShapeLayer();
var path = UIBezierPath.FromRoundedRect(circleFrame, 30);
path.UsesEvenOddFillRule = true;
maskOfGradientLayer.Path = path.CGPath;
maskOfGradientLayer.FillRule = CAShapeLayer.FillRuleEvenOdd;
maskOfGradientLayer.FillColor = UIColor.Black.CGColor;
maskOfGradientLayer.Frame = bounds;
gradientLayer.Mask = maskOfGradientLayer;
var maskOfMaskLayer = new CALayer();
maskOfMaskLayer.Frame = bounds;
var image = UIImage.FromBundle("Turn");
var reversedImage = GetReverseImage(image, bounds, imageFrame);
maskOfMaskLayer.Contents = reversedImage.CGImage;
Layer.Mask = maskOfMaskLayer;
}
private static UIImage GetReverseImage(UIImage image, CGRect rect, CGRect cropFrame)
{
UIGraphics.BeginImageContextWithOptions(rect.Size, false, 1);
UIColor.Black.SetColor();
UIGraphics.RectFill(rect);
image.Draw(cropFrame, CGBlendMode.DestinationOut, 1);
var newImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return newImage;
}
}
我深入研究了 Core Animation 并且在图层蒙版方面遇到了一些问题
出于研究原因,我尝试制作一个复杂的 UI 透明层
此视图已并放入ViewController
public class TestView : UIView
{
public TestView()
{
Layer.Delegate = this;
Frame = new CGRect(100f,200f, 100f, 100f);
}
public override void LayoutSublayersOfLayer(CALayer layer)
{
base.LayoutSublayersOfLayer(layer);
var bounds = Bounds;
var circleFrame = new CGRect(20, 20, 60, 60);
var imageFrame = new CGRect(30, 30, 40, 40);
Layer.BorderWidth = 5;
Layer.BorderColor = UIColor.Red.CGColor;
Layer.CornerRadius = 4;
var gradientLayer = new CAGradientLayer();
gradientLayer.Colors = new[] { UIColor.Green.CGColor, UIColor.Red.CGColor };
gradientLayer.Frame = bounds;
Layer.AddSublayer(gradientLayer);
var maskOfGradientLayer = new CAShapeLayer();
var path = UIBezierPath.FromRoundedRect(circleFrame, 30);
path.UsesEvenOddFillRule = true;
maskOfGradientLayer.Path = path.CGPath;
maskOfGradientLayer.FillRule = CAShapeLayer.FillRuleEvenOdd;
maskOfGradientLayer.FillColor = UIColor.Black.CGColor;
maskOfGradientLayer.Frame = bounds;
gradientLayer.Mask = maskOfGradientLayer;
var maskOfMaskLayer = new CAShapeLayer();
maskOfMaskLayer.Frame = imageFrame;
maskOfMaskLayer.FillColor = UIColor.Black.CGColor;
maskOfMaskLayer.Contents = Bundles.ImageOff.CGImage;
Layer.AddSublayer(maskOfMaskLayer);
}
}
我有,这正是我想要的。
不过我也想把圆形做成透明的而不是黑色。
我试过这样做maskOfGradientLayer.Mask = maskOfMaskLayer.
但是这样maskOfMaskLayer
什么都不做!它不像面具必须做的那样工作。
我该怎么办?
But I also want can to make transparent in circle instead black color.
解决方案探索版:
你也可以用UIBezierPath画你想要的,设置为maskOfMaskLayer
:
var maskOfMaskLayer = new CAShapeLayer();
maskOfMaskLayer.Frame = imageFrame;
maskOfMaskLayer.FillColor = UIColor.Black.CGColor;
maskOfMaskLayer.Contents = Bundles.ImageOff.CGImage;
Layer.AddSublayer(maskOfMaskLayer);
上行代码替换为:
UIBezierPath offCirclePath = new UIBezierPath();
// draw an arc
offCirclePath.AddArc(new CGPoint(50, 50), circleFrame.Width / 3, (nfloat)(1.75 * Math.PI), (nfloat)(1.25 * Math.PI), true);
//draw a line
offCirclePath.MoveTo(new CGPoint(50, 30));
offCirclePath.AddLineTo(new CGPoint(50, 45));
//set to maskOfMaskLayer
var maskOfMaskLayer = new CAShapeLayer();
maskOfMaskLayer.FillColor = UIColor.Clear.CGColor;
maskOfMaskLayer.Path = offCirclePath.CGPath;
maskOfMaskLayer.LineWidth = 5;
maskOfMaskLayer.StrokeColor = UIColor.White.CGColor;
maskOfMaskLayer.LineCap = new NSString("round");
Layer.AddSublayer(maskOfMaskLayer);
其他代码未更改。
But I from starts thought about setting any custom image.
方案二:(方向错误)
我测试过CAShapeLayer
不能有这个从图片变色的功能。 CAShapeLayer Class
但是,我发现 UIImageView
Can do that.There 是 it.This 的 TintColor
属性 属性 来自 UiView。UIView.TintColor Property。
var maskOfMaskLayer = new CAShapeLayer();
maskOfMaskLayer.Frame = imageFrame;
maskOfMaskLayer.FillColor = UIColor.Black.CGColor;
maskOfMaskLayer.Contents = Bundles.ImageOff.CGImage;
Layer.AddSublayer(maskOfMaskLayer);
更改为:
UIImageView imageView = new UIImageView();
imageView.Frame = imageFrame;
imageView.Image = Bundles.ImageOff;
imageView.TintColor = UIColor.White;
AddSubview(imageView);
正确解:
抱歉误解了真正想要的效果,更新如下:
Layer.Mask = maskOfMaskLayer;
如果你用AddSublayer
只是把你的图像覆盖在Layer上,Layer.Mask
是相反的效果,它只显示覆盖部分的背景,其余区域将被覆盖白色.CALayer.Mask
所有需要做的就是通过 Core Graphics 反转图像颜色,任何颜色透明,透明任何颜色。在这种情况下,黑色就足够了
public static UIImage GetRevertImage(UIImage image, CGRect rect, CGRect cropFrame)
{
UIGraphics.BeginImageContextWithOptions(rect.Size, false, 1);
UIColor.Black.SetColor();
UIGraphics.RectFill(rect);
image.Draw(cropFrame, CGBlendMode.DestinationOut, 1);
var newImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return newImage;
}
并将遮罩层的遮罩设置为父层
Layer.Mask = maskOfMaskLayer;
代码的最终版本:
public class TestView : UIView
{
public TestView()
{
Layer.Delegate = this;
Frame = new CGRect(50f, 50f, 100f, 100f);
}
public override void LayoutSublayersOfLayer(CALayer layer)
{
base.LayoutSublayersOfLayer(layer);
var bounds = Bounds;
var circleFrame = new CGRect(20, 20, 60, 60);
var imageFrame = new CGRect(30, 30, 40, 40);
Layer.BorderWidth = 5;
Layer.BorderColor = UIColor.Red.CGColor;
Layer.CornerRadius = 4;
Layer.MasksToBounds = true;
var gradientLayer = new CAGradientLayer();
gradientLayer.Colors = new[] {UIColor.Green.CGColor, UIColor.Red.CGColor};
gradientLayer.Frame = bounds;
Layer.AddSublayer(gradientLayer);
var maskOfGradientLayer = new CAShapeLayer();
var path = UIBezierPath.FromRoundedRect(circleFrame, 30);
path.UsesEvenOddFillRule = true;
maskOfGradientLayer.Path = path.CGPath;
maskOfGradientLayer.FillRule = CAShapeLayer.FillRuleEvenOdd;
maskOfGradientLayer.FillColor = UIColor.Black.CGColor;
maskOfGradientLayer.Frame = bounds;
gradientLayer.Mask = maskOfGradientLayer;
var maskOfMaskLayer = new CALayer();
maskOfMaskLayer.Frame = bounds;
var image = UIImage.FromBundle("Turn");
var reversedImage = GetReverseImage(image, bounds, imageFrame);
maskOfMaskLayer.Contents = reversedImage.CGImage;
Layer.Mask = maskOfMaskLayer;
}
private static UIImage GetReverseImage(UIImage image, CGRect rect, CGRect cropFrame)
{
UIGraphics.BeginImageContextWithOptions(rect.Size, false, 1);
UIColor.Black.SetColor();
UIGraphics.RectFill(rect);
image.Draw(cropFrame, CGBlendMode.DestinationOut, 1);
var newImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return newImage;
}
}