CGGradient เป็นออบเจกต์ Core Graphics ที่แสดงถึงการเปลี่ยนผ่านที่ราบรื่นระหว่างสีสองสีขึ้นไป แตกต่างจากการวาดเกรเดียนต์ผ่านลูปด้วยการเปลี่ยนสี CGGradient ใช้การคำนวณแบบเร่งด้วยฮาร์ดแวร์และรองรับสองประเภท: เชิงเส้น (แนวแกน) และแนวรัศมี ตามเอกสารของ Apple (2026) CGGradient ใช้สำหรับสร้างการเติมที่สมจริง เอฟเฟกต์พื้นหลัง และจำลองแหล่งกำเนิดแสงในส่วนติดต่อ iOS และ macOS
ประเด็นสำคัญ
CGGradient เป็นออบเจกต์ที่ไม่เปลี่ยนรูปใน Core Graphics ซึ่งห่อหุ้มชุดของสีและกฎสำหรับการผสมผสานตามการเปลี่ยนผ่านแบบเกรเดียนต์ ภายใน CGGradient จัดเก็บอาร์เรย์ของ CGColor อาร์เรย์ของตำแหน่ง (locations) ในช่วง [0.0, 1.0] และการอ้างอิงไปยัง CGColorSpace ซึ่งสีจะถูกตีความ แต่ละสีเชื่อมโยงกับตำแหน่งบนสเกลเกรเดียนต์: ตำแหน่ง 0.0 สอดคล้องกับจุดเริ่มต้น 1.0 กับจุดสิ้นสุดของการเปลี่ยนผ่าน
เมื่อสร้าง CGGradient ผ่านฟังก์ชัน CGGradientCreateWithColors Core Graphics จะคำนวณค่าสีกลางล่วงหน้า เกรเดียนต์สามารถมีจำนวนจุดหยุดสี (color stops) ได้ตามต้องการ ทำให้สามารถเปลี่ยนผ่านหลายสีที่ซับซ้อนได้ จำนวนสีต้องมีอย่างน้อยสองสี และแต่ละสีต้องสอดคล้องกับตำแหน่งในอาร์เรย์ locations
สถาปัตยกรรมของ CGGradient แตกต่างจาก API ระดับสูงกว่าเช่น CAGradientLayer จาก Core Animation ตรงที่ทำงานโดยตรงในบริบท Core Graphics ซึ่งให้การควบคุมอย่างสมบูรณ์เหนือกระบวนการวาดและความสามารถในการรวมเกรเดียนต์กับการดำเนินการ Quartz 2D อื่น ๆ — มาสก์ตัด เงา และการแปลง
Core Graphics รองรับเกรเดียนต์สองประเภท: เชิงเส้น (แนวแกน) และแนวรัศมี เกรเดียนต์เชิงเส้นสร้างด้วยฟังก์ชัน CGGradientCreateWithColors และวาดด้วย CGContextDrawLinearGradient เกรเดียนต์แนวรัศมีต้องการโครงสร้าง CGGradient เดียวกันแต่วาดด้วย CGContextDrawRadialGradient
| ประเภท | ฟังก์ชันการวาด | พารามิเตอร์ | การใช้งาน |
|---|---|---|---|
| เชิงเส้น | CGContextDrawLinearGradient | startPoint, endPoint, options | พื้นหลัง ปุ่ม แถบความคืบหน้า |
| แนวรัศมี | CGContextDrawRadialGradient | startCenter, startRadius, endCenter, endRadius, options | ประกายแสง แหล่งกำเนิดแสง เงา |
เกรเดียนต์เชิงเส้น ขยายการเปลี่ยนสีตามเส้นตรงจากจุดเริ่มต้น startPoint ไปยังจุดสิ้นสุด endPoint สีจะถูกประมาณค่าระหว่างสองจุดนี้ และพฤติกรรมที่เกินจากจุดเหล่านี้ถูกควบคุมโดยตัวเลือกการขยาย เกรเดียนต์เชิงเส้นเหมาะสำหรับการสร้างพื้นหลังที่เรียบเนียน จำลองพื้นผิวโลหะ และการเปลี่ยนสีในองค์ประกอบส่วนติดต่อ
เกรเดียนต์แนวรัศมี สร้างการเปลี่ยนสีจากวงกลมหนึ่งไปยังอีกวงกลมหนึ่ง แต่ละวงกลมกำหนดโดยจุดศูนย์กลาง (startCenter / endCenter) และรัศมี (startRadius / endRadius) สีจะถูกประมาณค่าจากวงกลมด้านในไปยังวงกลมด้านนอก กรณีพิเศษคือเมื่อรัศมีเริ่มต้นเป็น 0: เกรเดียนต์แผ่ออกจากจุดเดียว เกรเดียนต์แนวรัศมีใช้สำหรับจำลองแหล่งกำเนิดแสง เลนส์ วัตถุท้องฟ้า และเอฟเฟกต์สปอตไลต์
CGGradient สร้างด้วยฟังก์ชันพื้นฐานเพียงฟังก์ชันเดียว — CGGradientCreateWithColors ฟังก์ชันรับ CGColorSpace อาร์เรย์ของ CGColor (CFArray) และอาร์เรย์ของ CGFloat locations ถ้า locations เป็น NULL สีจะถูกกระจายอย่างเท่าเทียมกันตามสเกลเกรเดียนต์ ถ้ามีการระบุ locations จำนวนของมันต้องตรงกับจำนวนสี
อาร์เรย์ locations มีค่าตั้งแต่ 0.0 ถึง 1.0 ซึ่งกำหนดจุดหยุดสำหรับแต่ละสี ค่าต้องเพิ่มขึ้นอย่างซ้ำซาก ถ้าค่าแรกมากกว่า 0.0 สีจากจุดเริ่มต้นถึงตำแหน่งนี้จะถูกประมาณภายนอกจากสีที่ตำแหน่ง 0.0 ในทำนองเดียวกันสำหรับค่าสุดท้ายที่น้อยกว่า 1.0 พฤติกรรมนี้ถูกควบคุมโดยตัวเลือกการขยายในระหว่างการวาด
เมื่อเลือก สี สำหรับเกรเดียนต์ สิ่งสำคัญคือต้องพิจารณาพื้นที่สี สีทั้งหมดใน CGGradient เดียวกันต้องอยู่ใน CGColorSpace เดียวกัน — Core Graphics ประมาณค่าส่วนประกอบในพื้นที่นั้น ถ้าสีถูกสร้างขึ้นในพื้นที่ต่างกัน จะต้องแปลงเป็นพื้นที่ร่วมก่อนผ่าน CGColorCreateCopyByMatchingToColorSpace
Core Graphics มีสองฟังก์ชันสำหรับวาดเกรเดียนต์: CGContextDrawLinearGradient สำหรับเชิงเส้นและ CGContextDrawRadialGradient สำหรับแนวรัศมี ทั้งสองฟังก์ชันรับบริบทกราฟิก ออบเจกต์ CGGradient ตัวเลือกการขยาย และพารามิเตอร์เรขาคณิตเฉพาะประเภท การวาดดำเนินการโดยคำนึงถึงมาสก์ตัดปัจจุบันและการแปลงบริบท
ตัวเลือกการขยาย ควบคุมพฤติกรรมของเกรเดียนต์ที่เกินช่วงตำแหน่ง 0.0–1.0 ค่าคงที่ kCGGradientDrawsBeforeStartLocation เติมพื้นที่ก่อนตำแหน่งเริ่มต้นด้วยสีของจุดหยุดแรก kCGGradientDrawsAfterEndLocation เติมด้วยสีของจุดหยุดสุดท้าย ตัวเลือกเหล่านี้สามารถรวมกันผ่านบิตมาสก์ สำหรับเกรเดียนต์แนวรัศมี ตัวเลือกจะใช้กับพื้นที่ที่เกินรัศมีเริ่มต้นและสิ้นสุด
เกรเดียนต์ถูก วาด ในระบบพิกัดของบริบทกราฟิกปัจจุบัน โดยคำนึงถึงการแปลง (CTM — Current Transformation Matrix) การใช้ CGContextTranslateCTM, CGContextScaleCTM หรือ CGContextRotateCTM ก่อนเรียกฟังก์ชันวาดจะเปลี่ยนตำแหน่งและสเกลของเกรเดียนต์ ซึ่งช่วยให้สามารถใช้ CGGradient เดียวซ้ำสำหรับพื้นที่ต่างกันโดยไม่ต้องสร้างออบเจกต์ใหม่
Core Graphics มีกลไกเพิ่มเติมหลายอย่างสำหรับควบคุมเกรเดียนต์: การลดรอยหยัก (antialiasing) การมาสก์ผ่านมาสก์ตัด (clipping mask) และการรวมกับเอฟเฟกต์ความโปร่งใส การลดรอยหยักเปิดใช้งานโดยค่าเริ่มต้นในบริบทกราฟิกและควบคุมผ่าน CGContextSetShouldAntialias
มาสก์ตัด ช่วยให้จำกัดพื้นที่วาดเกรเดียนต์ให้เป็นรูปร่างตามต้องการ ก่อนเรียก CGContextDrawLinearGradient ต้องกำหนดเส้นทางผ่าน CGContextBeginPath, CGContextAddPath และ CGContextClip เกรเดียนต์จะถูกวาดเฉพาะภายในพื้นที่ที่ถูกจำกัดโดยเส้นทางนี้ ซึ่งใช้อย่างแพร่หลายสำหรับสร้างไอคอนเกรเดียนต์ ปุ่ม และแถบความคืบหน้า
การขยายเกรเดียนต์ เป็นอีกพารามิเตอร์สำคัญ เมื่อใช้ kCGGradientDrawsBeforeStartLocation Core Graphics จะประมาณภายนอกสีของจุดหยุดแรกทั่วทั้งพื้นที่ก่อน startPoint โดยไม่มีตัวเลือกนี้ พื้นที่นอกเกรเดียนต์จะไม่ถูกเติม (โปร่งใส) การรวมทั้งสองตัวเลือกช่วยให้มั่นใจว่าสี่เหลี่ยมผืนผ้าทั้งหมดของบริบทกราฟิกจะถูกเติมด้วยเกรเดียนต์ แม้ว่า startPoint และ endPoint จะอยู่ภายใน
มาดู ตัวอย่างเชิงปฏิบัติ ของการสร้างและวาดเกรเดียนต์ใน iOS โดยใช้ CGGradient และ Core Graphics
ตัวอย่างนี้สร้าง เกรเดียนต์เชิงเส้น ด้วยสามสี (น้ำเงิน เขียว แดง) และวาดตามแนวทแยงของ UIView อาร์เรย์ locations กระจายสีอย่างไม่เท่ากัน: น้ำเงินจาก 0.0 ถึง 0.3 เขียวที่ 0.6 แดงจาก 0.6 ถึง 1.0
func drawLinearGradient(in ctx: CGContext,
rect: CGRect) {
let colors = [
UIColor.blue.cgColor,
UIColor.green.cgColor,
UIColor.red.cgColor
] as CFArray
let locations: [CGFloat] = [0.0, 0.6, 1.0]
let space = CGColorSpaceCreateDeviceRGB()
guard let gradient = CGGradientCreateWithColors(
space, colors, locations
) else { return }
let start = CGPoint(x: 0, y: 0)
let end = CGPoint(x: rect.width,
y: rect.height)
ctx.drawLinearGradient(gradient,
start: start, end: end,
options: [.drawsBeforeStartLocation,
.drawsAfterEndLocation])
}
ตัวอย่างนี้วาด เกรเดียนต์แนวรัศมี ที่จำลองเอฟเฟกต์เรืองแสง จุดเริ่มต้นที่มีรัศมีเป็นศูนย์กำหนดจุดศูนย์กลางการเรืองแสง และวงกลมด้านนอกกำหนดขอบเขตการจางหาย เอฟเฟกต์นี้ใช้สำหรับเน้นองค์ประกอบส่วนติดต่อหรือตัวบ่งชี้กิจกรรม
func drawRadialGlow(in ctx: CGContext,
center: CGPoint) {
let colors = [
UIColor.white.cgColor,
UIColor.orange.cgColor,
UIColor.clear.cgColor
] as CFArray
let locations: [CGFloat] = [0.0, 0.4, 1.0]
let gradient = CGGradientCreateWithColors(
CGColorSpaceCreateDeviceRGB(), colors, locations)
ctx.drawRadialGradient(gradient,
startCenter: center, startRadius: 0,
endCenter: center, endRadius: 100,
options: [.drawsBeforeStartLocation,
.drawsAfterEndLocation])
}
ในตัวอย่างนี้ เกรเดียนต์ ถูกจำกัดให้อยู่ในพื้นที่วงกลมผ่านเส้นทางตัด ก่อนวาดเกรเดียนต์ จะกำหนดเส้นทางวงกลมซึ่งกลายเป็นมาสก์บริบทปัจจุบัน เกรเดียนต์เติมเฉพาะพื้นที่ภายในวงกลม สร้างเอฟเฟกต์ไอคอนเกรเดียนต์
func drawGradientInCircle(in ctx: CGContext,
rect: CGRect) {
// Creating circular clip path
let circlePath = CGMutablePath()
circlePath.addEllipse(in: rect)
ctx.addPath(circlePath)
ctx.clip()
// Drawing gradient inside clip mask
let colors = [UIColor.magenta.cgColor,
UIColor.cyan.cgColor]
let gradient = CGGradientCreateWithColors(
CGColorSpaceCreateDeviceRGB(),
colors as CFArray, nil)
ctx.drawLinearGradient(gradient,
start: CGPoint(x: 0, y: 0),
end: CGPoint(x: rect.width,
y: rect.height),
options: [.drawsBeforeStartLocation])
}
คำถามที่พบบ่อย
CGGradient เป็นออบเจกต์ Core Graphics ระดับต่ำสำหรับวาดในบริบทกราฟิก CAGradientLayer เป็นเลเยอร์ Core Animation ระดับสูงพร้อมแอนิเมชันอัตโนมัติและการเร่งด้วยฮาร์ดแวร์ CAGradientLayer ใช้ง่ายกว่ากับ UIKit แต่ CGGradient ให้การควบคุมอย่างสมบูรณ์และความเข้ากันได้กับ CGContext ใด ๆ
ขั้นต่ำ คือ 2 สี ขีดจำกัดบนถูกจำกัดโดยหน่วยความจำที่มีเท่านั้น เนื่องจาก Core Graphics จัดเก็บอาร์เรย์ของสีและตารางการประมาณค่าที่คำนวณล่วงหน้า ในทางปฏิบัติ มากกว่า 10–15 สีในเกรเดียนต์เดียวนั้นไม่จำเป็น — การเปลี่ยนทางสายตาจะแยกไม่ออกจากที่ราบรื่น
ใช้ CGColor ที่มีช่องอัลฟาน้อยกว่า 1.0 ในอาร์เรย์สี ตัวอย่างเช่น สีที่มีความโปร่งใสสร้างเป็น UIColor(red: 0, green: 0, blue: 1, alpha: 0.5).cgColor Core Graphics ประมาณค่าช่องอัลฟาเช่นเดียวกับส่วนประกอบสี สร้างการเปลี่ยนความโปร่งใสที่ราบรื่น
ใช่ CGGradient เป็นส่วนหนึ่งของ Core Graphics ที่มีอยู่บนทั้งสองแพลตฟอร์ม: iOS และ macOS บน macOS เกรเดียนต์ถูกวาดใน NSView ใด ๆ โดยการแทนที่ drawRect ฟังก์ชันทั้งหมด CGGradientCreateWithColors, CGContextDrawLinearGradient และ CGContextDrawRadialGradient เหมือนกันบนทั้งสองแพลตฟอร์ม
ในการหมุนเกรเดียนต์ ให้ใช้ การแปลง กับบริบทกราฟิกก่อนวาด: CGContextRotateCTM(ctx, angle) จุดเริ่มต้นและสิ้นสุดของเกรเดียนต์ถูกระบุในระบบพิกัดท้องถิ่นของบริบทหลังการแปลง หรือคุณสามารถคำนวณพิกัดที่หมุนของจุดโดยตรงโดยไม่เปลี่ยน CTM
สรุป
CGContextDrawLinearGradientCGContextDrawRadialGradientเราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ