Upgrade to Pro — share decks privately, control downloads, hide ads and more …

네이티브 차트 개발 여정

kakao
November 01, 2024

네이티브 차트 개발 여정

#Android #iOS #Chart

유동적인 데이터를 시각화하는 차트를 개발하며, 라이브러리를 사용하지 않고 모바일 환경에서 직접 차트를 구현한 경험을 공유합니다. 복잡하고 다양한 커스터마이징을 위해 라이브러리를 배제한 이유와 선택 사항들, 그리고 문제 해결 과정에 대해 다룹니다. 각 단계별로 직면했던 과제와 이를 극복한 방법을 설명하며, 보다 유연하고 맞춤화된 차트를 만드는 데 필요한 내용을 설명합니다.

발표자 : apeach.hye, las.dh
(apeach) 카카오헬스케어에서 파스타 서비스의 iOS 개발을 담당하고 있습니다.
(las) 카카오헬스케어에서 파스타 서비스의 안드로이드 개발을 담당하고 있습니다.

kakao

November 01, 2024
Tweet

More Decks by kakao

Other Decks in Programming

Transcript

  1. ׮নೠ࢚ࣁझಖ tആ׼੉হ૑݅࠙੉ղח੉য઱ࣁਃu j t࠙੉࢚ڄযઉ੓ਵݶۄੋ੉یߓ҃Ր য઱ࣁਃu tզ૞ࢶఖೞݶചݶ੄ਤ஖ীզ૞ࢶ ੉য়ب۾झ௼܀೧઱ࣁਃu tՐযઉ੓חҔఠ஖ೞݶҗѢ࠙੉ղч ࢶఖ೧઱ࣁਃu tࣻ૒ഛ੢ػ࢚కীࢲӝ۾ই੉௑ࢶఖೞ

    ݶର౟ࣻ૒୷ࣗೞݶࢲӒਤ஖۽झ௼܀ೞ ݶࢲইېܻझ౟ীࢲӝ۾ࢶఖ೧઱ࣁਃu tজఃݶഅ੤दр੉ചݶ੄ਤ஖ীয় ب۾಴द೧઱ࣁਃu tആ׼੉ࣃࢲ߹୭؀ߧਤܳֈਵݶ୭؀ं ੗݅ఀ݅಴दೞҊr֫਺sਵ۽ࠁৈ઱ࣁਃu tഛ؀୷ࣗೡٸदр੄ডࣻী೧׼ೞח दр݅಴द೧઱ࣁਃu
  2. tആ׼੉হ૑݅࠙੉ղח੉য઱ࣁਃu j t࠙੉࢚ڄযઉ੓ਵݶۄੋ੉یߓ҃Ր য઱ࣁਃu tզ૞ࢶఖೞݶചݶ੄ਤ஖ীզ૞ࢶ ੉য়ب۾झ௼܀೧઱ࣁਃu tՐযઉ੓חҔఠ஖ೞݶҗѢ࠙੉ղч ࢶఖ೧઱ࣁਃu tࣻ૒ഛ੢ػ࢚కীࢲӝ۾ই੉௑ࢶఖೞ ݶର౟ࣻ૒୷ࣗೞݶࢲӒਤ஖۽झ௼܀ೞ

    ݶࢲইېܻझ౟ীࢲӝ۾ࢶఖ೧઱ࣁਃu tজఃݶഅ੤दр੉ചݶ੄ਤ஖ীয় ب۾಴द೧઱ࣁਃu tആ׼੉ࣃࢲ߹୭؀ߧਤܳֈਵݶ୭؀ं ੗݅ఀ݅಴दೞҊr֫਺sਵ۽ࠁৈ઱ࣁਃu tഛ؀୷ࣗೡٸदр੄ডࣻী೧׼ೞח दр݅಴द೧઱ࣁਃu ࣻ஖ীٮ࢚ܻܲ࢝࠙ ౠ੿ߧਤ݅ߓ࢚҃࢝੸ਊ ۄੋՐӣ ߓ҃Րӣ झ௼܀ ܄೐ۨझ ഛ؀࢚కীࢲ੄߄٘ېӒ١੄ੋఠۑ࣌ ۄੋ৻ࠁ੿੼಴द߂ੋఠۑ࣌ j
  3. tആ׼੉হ૑݅࠙੉ղח੉য઱ࣁਃu j t࠙੉࢚ڄযઉ੓ਵݶۄੋ੉یߓ҃Ր য઱ࣁਃu tզ૞ࢶఖೞݶചݶ੄ਤ஖ীզ૞ࢶ ੉য়ب۾झ௼܀೧઱ࣁਃu tՐযઉ੓חҔఠ஖ೞݶҗѢ࠙੉ղч ࢶఖ೧઱ࣁਃu tࣻ૒ഛ੢ػ࢚కীࢲӝ۾ই੉௑ࢶఖೞ ݶର౟ࣻ૒୷ࣗೞݶࢲӒਤ஖۽झ௼܀ೞ

    ݶࢲইېܻझ౟ীࢲӝ۾ࢶఖ೧઱ࣁਃu tজఃݶഅ੤दр੉ചݶ੄ਤ஖ীয় ب۾಴द೧઱ࣁਃu tആ׼੉ࣃࢲ߹୭؀ߧਤܳֈਵݶ୭؀ं ੗݅ఀ݅಴दೞҊr֫਺sਵ۽ࠁৈ઱ࣁਃu tഛ؀୷ࣗೡٸदр੄ডࣻী೧׼ೞח दр݅಴द೧઱ࣁਃu /BUJWF۽ҳഅೞ੗
  4. J04

  5. -JOFӒܻӝ struct ChartPoint { let offset: CGPoint // ആ׼ч, ആ׼੉

    ஏ੿ػ दр let glucoseValue: Glucose let date: Date } ղੌয়੹द
  6. -JOFӒܻӝ let path = UIBezierPath() var isFirstPoint: Bool = true

    pointList.forEach { point in // ୐ߣ૩ ನੋ౟݅ move if isFirstPoint { path.move(to: point.offset) isFirstPoint = false } else { path.addLine(to: point.offset) } }
  7. -JOFӒܻӝ let path = UIBezierPath() var isFirstPoint: Bool = true

    pointList.forEach { point in // ୐ߣ૩ ನੋ౟݅ move if isFirstPoint { path.move(to: point.offset) isFirstPoint = false } else { path.addLine(to: point.offset) } }
  8. $($POUFYU GlucoseRange.forEach { type in let yValue = type.yValue context.saveGState()

    // clippingPath ୊ܻ ... preYValue = yValue context.restoreGState() }
  9. $($POUFYU GlucoseRange.forEach { type in let yValue = type.yValue context.saveGState()

    // clippingPath ୊ܻ ... preYValue = yValue context.restoreGState() }
  10. $(#MFOE.PEF /* Set the blend mode of `context' to `mode'.

    */ @available(iOS 2.0, *) public func setBlendMode(_ mode: CGBlendMode)
  11. $(#MFOE.PEF  33FTVMU  44PVSDF  %%FTUJOBUJPO  BBMQIB case

    clear = 16 /* R = 0 */ case copy = 17 /* R = S */ case sourceIn = 18 /* R = S*Da */ case sourceOut = 19 /* R = S*(1 - Da) */ case sourceAtop = 20 /* R = S*Da + D*(1 - Sa) */ case destinationOver = 21 /* R = S*(1 - Da) + D */ case destinationIn = 22 /* R = D*Sa */ case destinationOut = 23 /* R = D*(1 - Sa) */ case destinationAtop = 24 /* R = S*(1 - Da) + D*Sa */ …
  12. $(#MFOE.PEF // নଃ Ӓۄؘ੉࣌ draw // R = S*Da +

    D*(1 - Sa) context.setBlendMode(.sourceAtop)
  13. 7JFX1PSU  ୭؀рѺਵ۽୷ࣗ೮ਸٸ दр    दр  ആ׼ؘ੉ఠࣻ

     दрীѐY୭؀ѐ  ୭ࣗрѺਵ۽ഛ؀೮ਸٸ दр  ആ׼ؘ੉ఠࣻ୭؀ѐ
  14. -JOFର౟Ӓܻӝ ESBX-JOF؀नীESBX1BUIࢎਊ fun drawLine( color: Color, start: Offset, end: Offset,

    strokeWidth: Float ... ) fun drawPath( path: Path, color: Color, alpha: Float = 1.0f, style: DrawStyle = Fill, ... )
  15. ࠶۾ё୓ JOEFY -B[Z3PX੄*UFN*OEFY TUBSU&OE3BOHF दрߧਤ ನੋ౟ ӝ۾ ఋ੐ۄੋؘ੉ఠ੄4VC-JTU data class

    Block( val index: Int, val startEndRange: OpenEndRange<Instant>, val pointList: List<Point>, val recordList: List<Record>, val timelineList: List<Point>, )
  16. 1PJOUё୓ Y7BMVF दр Z7BMVF ആ׼ч PGGTFU Ӓ۰૕ਤ஖੷੢ JOEFY п࠶۾ীࢲ੄࠙ױਤਤ஖ class

    Point( override val xValue: Long, override val yValue: Int, override var offset: Offset = Offset.Zero, override var index: Long = 0L, ) : Data
  17. 4IBEFS#SVTI۽ೠߣী଻਋ӝ *NBHF#JUNBQਵ۽߸ജ class BitmapCanvas(width: Int, height: Int) { val bitmap:

    Bitmap = Bitmap.createBitmap( width, height, Bitmap.Config.ARGB_8888 ) val imageBitmap: ImageBitmap get() = bitmap.asImageBitmap() val width: Float get() = bitmap.width.toFloat() val height: Float get() = bitmap.height.toFloat() }
  18. 4IBEFS#SVTI۽ೠߣী଻਋ӝ #JUNBQী૒੽Ӓܻח ੷ࣻળ$BOWBT ৔৉଻਋ӝ ࠳۞एࢤࢿ val canvas = Canvas(bitmapCanvas.bitmap) positionList.forEach

    { position -> val paint = Paint().apply { color = position.areaColor.toArgb() } canvas.drawRect( 0f, position.top, chartWidth, position.bottom, paint ) } return ShaderBrush(ImageShader(bitmapCanvas.imageBitmap))
  19. 2"