CAShapeLayer — ay isang subclass ng CALayer na idinisenyo para sa hardware rendering ng mga vector contour sa GPU. Hindi tulad ng base CALayer na gumagana sa mga raster image sa pamamagitan ng contents, nire-render ng CAShapeLayer ang mga arbitrary na hugis na tinukoy sa pamamagitan ng CGPath nang hindi lumilikha ng hiwalay na offscreen buffer. Ayon sa Apple QuartzCore Documentation, 2025, gumagamit ang CAShapeLayer ng hardware acceleration para sa pagpapakinis ng mga gilid at sinusuportahan ang animation ng path, strokeStart at strokeEnd. Ito ang karaniwang tool para sa paggawa ng mga icon, indicator ng progreso, at mask sa iOS.
Mga Pangunahing Punto
CAShapeLayer — ay isang espesyalisadong layer para sa rendering ng vector graphics, na ipinakilala sa iOS 3.0. Hindi tulad ng CALayer na nag-iimbak ng raster image, nag-iimbak ang CAShapeLayer ng mathematical na paglalarawan ng contour — CGPath — at nire-render ito nang direkta sa GPU. Ito ay nagpapahintulot sa pag-scale ng hugis nang walang pagkawala ng kalidad at pag-animate ng mga katangian nito nang hindi nire-render muli ang nilalaman.
Sa arkitektura, minamana ng CAShapeLayer ang lahat ng kakayahan ng CALayer: mga anino, hangganan, pagbabago, mask. Ngunit nagdaragdag ito ng mga tiyak na katangian para sa pagtatrabaho sa mga contour: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, miterLimit, strokeStart, strokeEnd at fillRule. Ang bawat isa sa mga katangiang ito ay maaaring i-animate sa pamamagitan ng CABasicAnimation.
Ayon sa Apple Documentation, gumagamit ang CAShapeLayer ng hardware acceleration sa pag-render. Hindi tulad ng pagguhit sa pamamagitan ng Core Graphics sa drawRect:, kung saan nire-render ng CPU ang contour sa isang raster context, nagpapadala ang CAShapeLayer ng mga command nang direkta sa GPU sa pamamagitan ng Metal. Resulta — mas mataas na pagganap, lalo na sa panahon ng animation.
Ang CAShapeLayer ay lalong kapaki-pakinabang para sa mga elemento ng interface na nagbabago ng hugis bilang tugon sa mga aksyon ng user: mga indicator ng progreso, mga graph, mga icon ng tab-bar, mga mask para sa animation ng paglitaw ng nilalaman.
Ang proseso ng rendering ng CAShapeLayer ay naiiba sa base CALayer. Sa halip na mag-imbak ng raster buffer na may mga pixel, nagpapadala ang CAShapeLayer sa GPU ng vertex description ng contour — isang set ng mga punto, Bezier curve at segment. Niraraster ng GPU ang contour na ito sa isang pass, na inilalapat ang kulay ng fill at stroke sa yugto ng fragment shader.
Ang pamamaraang ito ay nagbibigay ng dalawang pakinabang: pag-scale nang walang pagkawala ng kalidad (mananatiling matalas ang vector graphics sa anumang resolution) at mahusay na animation — kapag nagbago ang path, muling kinakalkula ng GPU ang mga nabagong pixel lamang, hindi ang buong screen.
path — ang pangunahing katangian ng CAShapeLayer na tumatanggap ng CGPath. Ang contour ay maaaring maglaman ng mga linya, arko, Bezier curve at parihaba. Ginagawa sa pamamagitan ng UIBezierPath sa Swift o CGPath sa Core Graphics. Halimbawa: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath ay lumilikha ng bilugang parihaba.
Ang katangiang lineDashPattern ay nagpapahintulot sa paggawa ng mga putol-putol na linya. Tumatanggap ng array ng mga numero: [6, 3] ay nangangahulugang 6 na punto ng linya at 3 punto ng espasyo. lineDashPhase ay nagtatakda ng paglipat ng pattern at maaaring i-animate para sa epekto ng gumagalaw na putol-putol na linya.
Ang pagpili sa pagitan ng CAShapeLayer at base CALayer ay depende sa uri ng nilalaman. Kung ang elemento ay isang parihabang lugar na may background, hangganan at anino — sapat na ang CALayer. Kung ang elemento ay may arbitrary na hugis, nangangailangan ng animation ng contour o pag-scale nang walang pagkawala ng kalidad — mas gusto ang CAShapeLayer.
Nagkakaiba rin ang pagganap. Ang CALayer na may cornerRadius at masksToBounds ay lumilikha ng offscreen buffer para sa pagputol ng nilalaman, na nagdaragdag ng 2–5 ms bawat frame. Ang CAShapeLayer ay hindi nangangailangan ng offscreen buffer — ang pagputol ay ginagawa sa antas ng vertex shader. Para sa mga elementong may kumplikadong mask, ang CAShapeLayer ay maaaring 2–3 beses na mas mabilis.
Ang pagsasama ng CAShapeLayer sa iba pang mga layer ay isang karaniwang pattern. Halimbawa, ang CAGradientLayer ay gumagamit ng CAShapeLayer bilang mask upang lumikha ng hugis na may gradient fill. Ang pamamaraang ito ay nagbibigay ng parehong kalidad ng vector at gradient fill nang walang pagkawala ng pagganap.
Animation ng path — isa sa pinakamakapangyarihang kakayahan ng CAShapeLayer. Kung ang parehong contour (simula at katapusan) ay may parehong bilang ng mga control point at segment, ang Core Animation ay nagsasagawa ng maayos na interpolation sa pagitan ng mga ito. Resulta — epekto ng pagbabago ng isang hugis patungo sa isa pa.
Kondisyon ng compatibility ng path: ang simula at katapusang UIBezierPath ay dapat magkaroon ng parehong istraktura — ang bilang ng mga tawag sa moveTo, addLine, addCurve at addQuadCurve ay dapat magtugma. Kung magkaiba ang istraktura, ang animation ay magiging instant, walang interpolation.
Ayon sa Apple WWDC 2024, ang kombinasyon ng strokeStart at strokeEnd ay ang pinakamadalas na ginagamit na pattern ng animation ng CAShapeLayer. Ang animation ng strokeEnd mula 0.0 hanggang 1.0 ay lumilikha ng epekto ng pagguhit ng contour mula simula hanggang dulo. Ito ay ginagamit sa mga indicator ng paglo-load, animation ng paglitaw ng mga graph, at custom na transition sa pagitan ng mga screen.
Upang lumikha ng epekto ng pagpintig, i-animate ang strokeEnd at opacity nang sabay gamit ang iba't ibang timing function. Para sa epekto ng gumagalaw na putol-putol na linya, i-animate ang lineDashPhase na may fixed lineDashPattern. Ang parehong teknik ay ipinapatupad sa pamamagitan ng CABasicAnimation nang walang partisipasyon ng CPU.
Ang CAShapeLayer ay madalas na ginagamit bilang mask para sa iba pang mga layer. Halimbawa, para sa animation ng paglitaw ng nilalaman: sa simula ang mask.path ay isang parihaba na may zero size, sa katapusan — buong laki. Ang Core Animation ay nag-i-interpolate ng path, at ang nilalaman ay nahahayag nang maayos.
Ang pattern na ito ay ginagamit sa iOS para sa animation ng pagbukas ng mga card, paglitaw ng mga modal window, at transition sa pagitan ng mga view controller. Hindi tulad ng alpha animation, ang animation sa pamamagitan ng CAShapeLayer mask ay nagbibigay ng mas natural na epekto ng paglitaw na may arbitrary na hugis.
Unang halimbawa — paggawa ng circular progress indicator na may strokeEnd animation. Ito ay isang karaniwang UI element na nagpapakita ng mga pangunahing kakayahan ng CAShapeLayer:
func createProgressIndicator(in view: UIView) -> CAShapeLayer {
let circlePath = UIBezierPath(
arcCenter: CGPoint(x: 50, y: 50),
radius: 40,
startAngle: -.pi / 2,
endAngle: 3 * .pi / 2,
clockwise: true
)
let trackLayer = CAShapeLayer()
trackLayer.path = circlePath.cgPath
trackLayer.strokeColor = UIColor.systemGray5.cgColor
trackLayer.fillColor = nil
trackLayer.lineWidth = 8
view.layer.addSublayer(trackLayer)
let progressLayer = CAShapeLayer()
progressLayer.path = circlePath.cgPath
progressLayer.strokeColor = UIColor.systemBlue.cgColor
progressLayer.fillColor = nil
progressLayer.lineWidth = 8
progressLayer.lineCap = .round
progressLayer.strokeEnd = 0
view.layer.addSublayer(progressLayer)
return progressLayer
}
// I-animate sa 75%
progressLayer.animateStrokeEnd(to: 0.75, duration: 1.5)
Pangalawang halimbawa — animation ng pagbabago sa pagitan ng bilog at parisukat. Ang parehong UIBezierPath ay may compatible na istraktura:
let morphLayer = CAShapeLayer()
morphLayer.fillColor = UIColor.systemPurple.cgColor
morphLayer.frame = rect
let circlePath = UIBezierPath(roundedRect: rect, cornerRadius: rect.width / 2)
let squarePath = UIBezierPath(roundedRect: rect, cornerRadius: 0)
morphLayer.path = circlePath.cgPath
let morphAnimation = CABasicAnimation(keyPath: "path")
morphAnimation.toValue = squarePath.cgPath
morphAnimation.duration = 0.6
morphAnimation.autoreverses = true
morphAnimation.repeatCount = .infinity
morphLayer.add(morphAnimation, forKey: "morph")
Pangatlong halimbawa — mask na may CAShapeLayer para sa animation ng paglitaw ng nilalaman. Ang mask ay lumalawak mula sa gitna patungo sa mga gilid:
func revealContent(_ view: UIView) {
let maskLayer = CAShapeLayer()
let size = view.bounds.size.width * 1.5
let center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
let initialPath = UIBezierPath(arcCenter: center, radius: 0, startAngle: 0, endAngle: .pi * 2, clockwise: true)
let finalPath = UIBezierPath(arcCenter: center, radius: size, startAngle: 0, endAngle: .pi * 2, clockwise: true)
maskLayer.path = initialPath.cgPath
view.layer.mask = maskLayer
let animation = CABasicAnimation(keyPath: "path")
animation.toValue = finalPath.cgPath
animation.duration = 0.4
animation.timingFunction = CAMediaTimingFunction(name: .easeOut)
maskLayer.add(animation, forKey: "reveal")
maskLayer.path = finalPath.cgPath
}
Mga Madalas Itanong
drawRect ay gumagamit ng CPU para sa rendering sa isang raster context — ito ay mabagal para sa mga animation. Nire-render ng CAShapeLayer ang contour sa GPU, na nagbibigay ng 60 FPS sa animation ng path, strokeEnd at mga pagbabago. Bukod dito, ang CAShapeLayer ay hindi nangangailangan ng re-rendering kapag nagbago ang laki — ang hugis ay naka-scale nang vector.
Ang maayos na animation ng path ay nangangailangan ng parehong istraktura ng simula at katapusang UIBezierPath. Ang bilang ng mga tawag sa moveTo, addLine, addCurve ay dapat magtugma. Gumamit ng UIBezierPath na may parehong bilang ng mga segment para sa simula at katapusang hugis.
Itakda ang lineDashPattern — isang array ng mga numero na nagpapalit-palit ng haba ng linya at espasyo. Halimbawa, [8, 4] ay lumilikha ng mga linya na 8pt na may mga espasyo na 4pt. Para sa gumagalaw na putol-putol na linya, i-animate ang lineDashPhase sa pamamagitan ng CABasicAnimation na may linear timing function.
Oo, ito ay isa sa mga pangunahing senaryo. Italaga ang CAShapeLayer sa property na mask ng anumang CALayer, kabilang ang CAGradientLayer at iba pang subclass. Ang animation ng path ng mask ay lumilikha ng epekto ng maayos na paglitaw ng nilalaman sa pamamagitan ng isang hugis na may arbitrary na anyo.
Lumikha ng CAGradientLayer at itakda ang mask nito = CAShapeLayer na may nais na path. Ang gradient ay makikita lamang sa loob ng contour ng mask. Pinagsasama ng pattern na ito ang mga bentahe ng vector shape ng CAShapeLayer at gradient fill ng CAGradientLayer.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din