围绕 CAShape 层绘制矩形
Draw rectangle around CAShape Layer
我是 Swift 的新手,也是 Core Animation 的新手。我想像这样在 CAShapeLayer 周围创建矩形框 image,但我不知道。
具体来说,我正在通过 PocketSVG 解析 SVG 图像并将其 UIBezierPath 转换为 CAShapeLayer然后我将这些图层添加到 UI Image View 作为 sublayer.
这是我将 Path 转换为 CaShape Layer.
的代码
fileprivate func createLayer(path: SVGBezierPath) -> CAShapeLayer {
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
if let any = path.svgAttributes["stroke"] {
shapeLayer.strokeColor = (any as! CGColor)
}
if let any = path.svgAttributes["fill"] {
shapeLayer.fillColor = (any as! CGColor)
}
return shapeLayer
}
下面是代码,我在其中添加图层到 UIImage View (backgroundIV)
for path in paths {
path.apply(.init(scaleX: scale, y: scale))
let layer = createLayer(path: path)
layer.frame = self.backgroundIV.bounds
self.backgroundIV.layer.addSublayer(layer)
}
我还添加了 TapGesture, RotateGesture, ScaleGesture 和 PanGesture 到 CA Shape Layers,下面是代码。
@objc func rotateLayer(_ sender: UIRotationGestureRecognizer) {
selectedLayer?.setAffineTransform(CGAffineTransform(rotationAngle: sender.rotation))
}
@objc func selectLayer(_ sender: UITapGestureRecognizer) {
let point = sender.location(in: self.backgroundIV)
guard let layers = self.backgroundIV.layer.sublayers
else { return }
var hitLayers: [CAShapeLayer] = []
selectedLayer?.lineWidth = CGFloat(0)
for subLayer in layers {
if let thisLayer = subLayer as? CAShapeLayer,
let pth = thisLayer.path {
let layerPoint: CGPoint = thisLayer.convert(point, from: self.backgroundIV.layer)
if pth.contains(layerPoint) {
hitLayers.append(thisLayer)
}
}
}
selectedLayer = hitLayers.last
selectedLayer?.strokeColor = UIColor.red.cgColor
selectedLayer?.lineWidth = CGFloat(3)
selectedLayerRect = CGRect(origin: point, size: CGSize(width: 100, height: 100))
showPopupMenu()
}
@objc func moveLayer(_ recognizer: UIPanGestureRecognizer) {
let p = recognizer.location(in: self.backgroundIV)
selectedLayer?.position = p
}
@objc func scaleLayer(_ sender: UIPinchGestureRecognizer) {
selectedLayer?.transform = CATransform3DMakeScale(sender.scale, sender.scale, 1)
}
在 SelectLayer 方法的最后几行中,我通过增加描边宽度和颜色来突出显示 selected 层。
selectedLayer?.strokeColor = UIColor.red.cgColor
selectedLayer?.lineWidth = CGFloat(3)
当我取消 select 图层时,我只是将其 lineWidth 值设置为 0,这不是一个好的做法。
有什么方法可以像这样创建矩形框 image?
如果您想在图层的框架周围画一个框,那很容易。只需设置 aLayer.borderWidth=1
和 aLayer.borderColor=UIColor.someColor.cgColor
.
系统会在图层周围添加边框。
但是,如果您图层的框架比它们包含的路径大,您的矩形可能会比您想要的大。
试试这个..
希望对您有所帮助...
import UIKit
class ViewController : UIViewController {
let containerView: UIView = {
let view = UIView()
view.backgroundColor = .clear
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
containerView.frame = CGRect(x: view.frame.width/2 - 100, y: view.frame.height/2 - 100, width: 200, height: 200)
view.addSubview(containerView)
drawRectangle()
}
private func drawRectangle() {
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 200, y: 0))
path.addLine(to: CGPoint(x: 200, y: 200))
path.addLine(to: CGPoint(x: 0, y: 200))
path.addLine(to: CGPoint(x: 0, y: 0))
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.fillColor = UIColor.black.cgColor
shapeLayer.lineWidth = 3
containerView.layer.addSublayer(shapeLayer)
}
}
如果我没理解错的话,你的问题是“如何绘制虚线轮廓”?
如果是这样,您可以在形状图层上设置 .lineDashPattern
。
例如:
selectedLayer?.strokeColor = UIColor.red.cgColor
selectedLayer?.lineWidth = 3.0
// set the dash pattern for the stroke
selectedLayer?.lineDashPattern = [10, 10]
这是我问题的答案
var selectedLayer: CAShapeLayer! {
didSet {
guard let layer = selectedLayer else {return}
box.frame = layer.path?.boundingBox ?? CGRect()
box.borderWidth = layer.contentsScale * 3
box.borderColor = UIColor.red.cgColor
self.updateControlView()
layer.addSublayer(box)
}
willSet {
self.controlView.isHidden = true
box.removeFromSuperlayer()
}
}
Output
我是 Swift 的新手,也是 Core Animation 的新手。我想像这样在 CAShapeLayer 周围创建矩形框 image,但我不知道。
具体来说,我正在通过 PocketSVG 解析 SVG 图像并将其 UIBezierPath 转换为 CAShapeLayer然后我将这些图层添加到 UI Image View 作为 sublayer.
这是我将 Path 转换为 CaShape Layer.
的代码fileprivate func createLayer(path: SVGBezierPath) -> CAShapeLayer {
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
if let any = path.svgAttributes["stroke"] {
shapeLayer.strokeColor = (any as! CGColor)
}
if let any = path.svgAttributes["fill"] {
shapeLayer.fillColor = (any as! CGColor)
}
return shapeLayer
}
下面是代码,我在其中添加图层到 UIImage View (backgroundIV)
for path in paths {
path.apply(.init(scaleX: scale, y: scale))
let layer = createLayer(path: path)
layer.frame = self.backgroundIV.bounds
self.backgroundIV.layer.addSublayer(layer)
}
我还添加了 TapGesture, RotateGesture, ScaleGesture 和 PanGesture 到 CA Shape Layers,下面是代码。
@objc func rotateLayer(_ sender: UIRotationGestureRecognizer) {
selectedLayer?.setAffineTransform(CGAffineTransform(rotationAngle: sender.rotation))
}
@objc func selectLayer(_ sender: UITapGestureRecognizer) {
let point = sender.location(in: self.backgroundIV)
guard let layers = self.backgroundIV.layer.sublayers
else { return }
var hitLayers: [CAShapeLayer] = []
selectedLayer?.lineWidth = CGFloat(0)
for subLayer in layers {
if let thisLayer = subLayer as? CAShapeLayer,
let pth = thisLayer.path {
let layerPoint: CGPoint = thisLayer.convert(point, from: self.backgroundIV.layer)
if pth.contains(layerPoint) {
hitLayers.append(thisLayer)
}
}
}
selectedLayer = hitLayers.last
selectedLayer?.strokeColor = UIColor.red.cgColor
selectedLayer?.lineWidth = CGFloat(3)
selectedLayerRect = CGRect(origin: point, size: CGSize(width: 100, height: 100))
showPopupMenu()
}
@objc func moveLayer(_ recognizer: UIPanGestureRecognizer) {
let p = recognizer.location(in: self.backgroundIV)
selectedLayer?.position = p
}
@objc func scaleLayer(_ sender: UIPinchGestureRecognizer) {
selectedLayer?.transform = CATransform3DMakeScale(sender.scale, sender.scale, 1)
}
在 SelectLayer 方法的最后几行中,我通过增加描边宽度和颜色来突出显示 selected 层。
selectedLayer?.strokeColor = UIColor.red.cgColor
selectedLayer?.lineWidth = CGFloat(3)
当我取消 select 图层时,我只是将其 lineWidth 值设置为 0,这不是一个好的做法。
有什么方法可以像这样创建矩形框 image?
如果您想在图层的框架周围画一个框,那很容易。只需设置 aLayer.borderWidth=1
和 aLayer.borderColor=UIColor.someColor.cgColor
.
系统会在图层周围添加边框。
但是,如果您图层的框架比它们包含的路径大,您的矩形可能会比您想要的大。
试试这个..
希望对您有所帮助...
import UIKit
class ViewController : UIViewController {
let containerView: UIView = {
let view = UIView()
view.backgroundColor = .clear
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
containerView.frame = CGRect(x: view.frame.width/2 - 100, y: view.frame.height/2 - 100, width: 200, height: 200)
view.addSubview(containerView)
drawRectangle()
}
private func drawRectangle() {
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 200, y: 0))
path.addLine(to: CGPoint(x: 200, y: 200))
path.addLine(to: CGPoint(x: 0, y: 200))
path.addLine(to: CGPoint(x: 0, y: 0))
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.fillColor = UIColor.black.cgColor
shapeLayer.lineWidth = 3
containerView.layer.addSublayer(shapeLayer)
}
}
如果我没理解错的话,你的问题是“如何绘制虚线轮廓”?
如果是这样,您可以在形状图层上设置 .lineDashPattern
。
例如:
selectedLayer?.strokeColor = UIColor.red.cgColor
selectedLayer?.lineWidth = 3.0
// set the dash pattern for the stroke
selectedLayer?.lineDashPattern = [10, 10]
这是我问题的答案
var selectedLayer: CAShapeLayer! {
didSet {
guard let layer = selectedLayer else {return}
box.frame = layer.path?.boundingBox ?? CGRect()
box.borderWidth = layer.contentsScale * 3
box.borderColor = UIColor.red.cgColor
self.updateControlView()
layer.addSublayer(box)
}
willSet {
self.controlView.isHidden = true
box.removeFromSuperlayer()
}
}
Output