├── .clang-format ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md └── workflows │ ├── android.yml │ ├── ios.yml │ └── mirror.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── CMakeLists.txt ├── CNAME ├── CONTRIBUTING.md ├── F2.podspec ├── LEGAL.md ├── LICENSE ├── LICENSE.md ├── README.md ├── README_cn.md ├── android └── f2native │ ├── .gitignore │ ├── build.gradle │ └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── antgroup │ │ └── antv │ │ └── f2 │ │ ├── F2InstrumentedTest.java │ │ └── F2TestProxy.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── antgroup │ │ └── antv │ │ └── f2 │ │ ├── F2AndroidCanvasContext.java │ │ ├── F2AndroidCanvasView.java │ │ ├── F2BridgeRailing.java │ │ ├── F2CSUtils.java │ │ ├── F2CanvasView.java │ │ ├── F2Chart.java │ │ ├── F2ChartBridge.java │ │ ├── F2ChartBridgeListener.java │ │ ├── F2CommonUtils.java │ │ ├── F2Config.java │ │ ├── F2Constants.java │ │ ├── F2DetectManager.java │ │ ├── F2Event.java │ │ ├── F2Function.java │ │ ├── F2Geom.java │ │ ├── F2Guide.java │ │ ├── F2Log.java │ │ ├── F2Util.java │ │ ├── NativeChartProxy.java │ │ ├── RequestAnimationFrameHandle.java │ │ └── base │ │ └── F2BaseCanvasView.java │ └── res │ └── values │ └── strings.xml ├── build.gradle ├── core ├── CMakeLists.txt ├── Core.h ├── android │ ├── BitmapCanvasContext.cpp │ ├── BitmapCanvasContext.h │ ├── BridgeRailingAndroid.cpp │ ├── BridgeRailingAndroid.h │ ├── CanvasImage.cpp │ ├── F2NativeJNI.cpp │ ├── F2NativeJNI.h │ ├── JNIUtil.cpp │ ├── JNIUtil.h │ ├── JavaChartBridgeCallBack.cpp │ ├── JavaChartBridgeCallBack.h │ ├── JavaF2Function.h │ ├── JavaRef.cpp │ └── JavaRef.h ├── bridge │ ├── AbstractBridgeRailing.h │ ├── ChartBridge.cpp │ └── ChartBridge.h ├── graphics │ ├── XChart.cpp │ ├── XChart.h │ ├── adjust │ │ ├── Dodge.h │ │ └── Stack.h │ ├── animate │ │ ├── Animator.h │ │ ├── GeomAnimate.cpp │ │ ├── GeomAnimate.h │ │ ├── TimeLine.cpp │ │ └── TimeLine.h │ ├── axis │ │ ├── AxisController.cpp │ │ └── AxisController.h │ ├── canvas │ │ ├── Canvas.cpp │ │ ├── Canvas.h │ │ ├── CanvasColorParser.cpp │ │ ├── CanvasColorParser.h │ │ ├── CanvasContext.h │ │ ├── CanvasFillStrokeStyle.h │ │ ├── CanvasFontParser.cpp │ │ ├── CanvasFontParser.h │ │ ├── CanvasImage.h │ │ ├── Cartesian.h │ │ ├── Container.h │ │ ├── Coord.h │ │ └── Polar.h │ ├── event │ │ └── EventController.h │ ├── func │ │ ├── Command.h │ │ └── Func.h │ ├── geom │ │ ├── Area.cpp │ │ ├── Area.h │ │ ├── Candle.cpp │ │ ├── Candle.h │ │ ├── Geom.cpp │ │ ├── Geom.h │ │ ├── Interval.cpp │ │ ├── Interval.h │ │ ├── Line.cpp │ │ ├── Line.h │ │ ├── Path.h │ │ ├── Point.cpp │ │ ├── Point.h │ │ ├── attr │ │ │ └── AttrBase.h │ │ └── shape │ │ │ ├── Area.h │ │ │ ├── Candle.h │ │ │ ├── GeomShapeBase.h │ │ │ ├── GeomShapeFactory.cpp │ │ │ ├── GeomShapeFactory.h │ │ │ ├── Interval.h │ │ │ ├── Line.h │ │ │ └── Point.h │ ├── global.h │ ├── guide │ │ ├── Background.cpp │ │ ├── Background.h │ │ ├── Flag.cpp │ │ ├── Flag.h │ │ ├── GuideBase.cpp │ │ ├── GuideBase.h │ │ ├── GuideController.cpp │ │ ├── GuideController.h │ │ ├── Image.cpp │ │ ├── Image.h │ │ ├── Line.cpp │ │ ├── Line.h │ │ ├── Point.cpp │ │ ├── Point.h │ │ ├── Text.cpp │ │ └── Text.h │ ├── interaction │ │ ├── InteractionBase.h │ │ ├── InteractionContext.cpp │ │ ├── InteractionContext.h │ │ ├── Pan.cpp │ │ ├── Pan.h │ │ ├── Pinch.cpp │ │ └── Pinch.h │ ├── legend │ │ ├── LegendController.cpp │ │ └── LegendController.h │ ├── scale │ │ ├── Category.h │ │ ├── Identity.h │ │ ├── KLineCat.h │ │ ├── Scale.cpp │ │ ├── Scale.h │ │ ├── ScaleController.cpp │ │ ├── ScaleController.h │ │ ├── TimeCategory.h │ │ └── continuous │ │ │ ├── Linear.cpp │ │ │ ├── Linear.h │ │ │ └── TimeSharingLinear.h │ ├── shape │ │ ├── Area.cpp │ │ ├── Area.h │ │ ├── Circle.cpp │ │ ├── Circle.h │ │ ├── Element.cpp │ │ ├── Element.h │ │ ├── Group.cpp │ │ ├── Group.h │ │ ├── Image.cpp │ │ ├── Image.h │ │ ├── Line.cpp │ │ ├── Line.h │ │ ├── Marker.cpp │ │ ├── Marker.h │ │ ├── Polygon.cpp │ │ ├── Polygon.h │ │ ├── Polyline.cpp │ │ ├── Polyline.h │ │ ├── Rect.cpp │ │ ├── Rect.h │ │ ├── Shape.cpp │ │ ├── Shape.h │ │ ├── Text.cpp │ │ └── Text.h │ ├── tooltip │ │ ├── ToolTip.h │ │ ├── TooltipController.cpp │ │ └── TooltipController.h │ └── util │ │ ├── BBox.h │ │ ├── Color.cpp │ │ ├── Color.h │ │ ├── Matrix.h │ │ ├── Path.h │ │ ├── Point.h │ │ ├── Vector2d.h │ │ ├── json.cpp │ │ ├── json.h │ │ ├── json_data.h │ │ └── json_util.h ├── ios │ ├── BridgeRailingIOS.h │ ├── BridgeRailingIOS.mm │ ├── CanvasImage.mm │ ├── CoreGraphicsContext.h │ ├── CoreGraphicsContext.mm │ ├── F2Logger.h │ └── F2Logger.mm ├── nlohmann │ └── json.hpp ├── utils │ ├── StringUtil.h │ ├── Tracer.cpp │ ├── Tracer.h │ ├── common.cpp │ ├── common.h │ └── xtime.h └── webassembly │ ├── CanvasImage.cpp │ ├── WebCanvasContext.cpp │ ├── WebCanvasContext.h │ └── XChart+WebAssembly.cpp ├── demos ├── android │ ├── demos-kotlin │ │ ├── build.gradle │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ └── gradle-wrapper.jar │ │ ├── gradlew │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── androidTest │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── antgroup │ │ │ │ └── antv │ │ │ │ └── samples │ │ │ │ └── ExampleInstrumentedTest.java │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── assets │ │ │ │ ├── mockData_1688.json │ │ │ │ ├── mockData_basePie.json │ │ │ │ ├── mockData_klineDay.json │ │ │ │ ├── mockData_line_kline.json │ │ │ │ ├── mockData_multiAreasChart.json │ │ │ │ ├── mockData_multiAxiesLine.json │ │ │ │ ├── mockData_multiIntervalsChart.json │ │ │ │ ├── mockData_multilines.json │ │ │ │ ├── mockData_radarArea.json │ │ │ │ ├── mockData_sectionInterval.json │ │ │ │ ├── mockData_singleAreaChart.json │ │ │ │ ├── mockData_singleAreaChart_2.json │ │ │ │ ├── mockData_singleIntervalChart.json │ │ │ │ ├── mockData_singleIntervalChart_2.json │ │ │ │ ├── mockData_singleIntervalChart_under_zero.json │ │ │ │ ├── mockData_singleLineChart.json │ │ │ │ ├── mockData_singleLineChart_timeSharing_tooltip.json │ │ │ │ ├── mockData_singlePointChart.json │ │ │ │ ├── mockData_trendChart.json │ │ │ │ ├── mockData_trendChart_flags.json │ │ │ │ ├── mock_cube_data.json │ │ │ │ ├── mock_cube_data2.json │ │ │ │ └── wallet.png │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── antgroup │ │ │ │ │ └── antv │ │ │ │ │ └── f2 │ │ │ │ │ └── kotlinsamples │ │ │ │ │ ├── BridgeActivity.kt │ │ │ │ │ ├── BridgeControl.kt │ │ │ │ │ ├── ChartListActivity.kt │ │ │ │ │ ├── ChartModel.kt │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ ├── SampleActivity.kt │ │ │ │ │ ├── SampleActivityHorizontal.kt │ │ │ │ │ ├── Utils.kt │ │ │ │ │ └── charts │ │ │ │ │ ├── CandleChart_klineDay.kt │ │ │ │ │ ├── CirclePieChart.kt │ │ │ │ │ ├── MKTrendChart.kt │ │ │ │ │ ├── MultiAreasChart.kt │ │ │ │ │ ├── MultiIntervalChart.kt │ │ │ │ │ ├── MultiIntervalChart_under_zero.kt │ │ │ │ │ ├── MultiLinesChart_1.kt │ │ │ │ │ ├── PieChart.kt │ │ │ │ │ ├── RadarAreaChart.kt │ │ │ │ │ ├── SectionIntervalChart.kt │ │ │ │ │ ├── SingleAreaChart_1.kt │ │ │ │ │ ├── SingleAreaChart_2.kt │ │ │ │ │ ├── SingleIntervalChart_1.kt │ │ │ │ │ ├── SingleIntervalChart_2.kt │ │ │ │ │ ├── SingleIntervalChart_3.kt │ │ │ │ │ ├── SingleLineChart_1.kt │ │ │ │ │ ├── SingleLineChart_1688.kt │ │ │ │ │ ├── SingleLineChart_2.kt │ │ │ │ │ ├── SingleLineChart_KLine.kt │ │ │ │ │ ├── SingleLineChart_TimeSharing_ToolTip.kt │ │ │ │ │ └── SinglePointChart_1.kt │ │ │ ├── jniLibs │ │ │ │ ├── arm64-v8a │ │ │ │ │ └── libc++_shared.so │ │ │ │ └── armeabi-v7a │ │ │ │ │ └── libc++_shared.so │ │ │ └── res │ │ │ │ ├── drawable-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── layout │ │ │ │ ├── activity_bridge.xml │ │ │ │ ├── activity_main.xml │ │ │ │ ├── activity_sample.xml │ │ │ │ ├── activity_sample_horizontal.xml │ │ │ │ ├── activity_stock_time_sharing.xml │ │ │ │ ├── layout_chart_canvasview.xml │ │ │ │ └── layout_chart_item.xml │ │ │ │ ├── menu │ │ │ │ └── menu.xml │ │ │ │ └── values │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── antgroup │ │ │ └── antv │ │ │ └── samples │ │ │ └── ExampleUnitTest.kt │ └── demos │ │ ├── build.gradle │ │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.jar │ │ ├── gradlew │ │ ├── proguard-rules.pro │ │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── antgroup │ │ │ └── antv │ │ │ └── samples │ │ │ └── ExampleInstrumentedTest.java │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ │ ├── mockData_1688.json │ │ │ ├── mockData_basePie.json │ │ │ ├── mockData_klineDay.json │ │ │ ├── mockData_line_kline.json │ │ │ ├── mockData_multiAreasChart.json │ │ │ ├── mockData_multiAxiesLine.json │ │ │ ├── mockData_multiIntervalsChart.json │ │ │ ├── mockData_multilines.json │ │ │ ├── mockData_radarArea.json │ │ │ ├── mockData_sectionInterval.json │ │ │ ├── mockData_singleAreaChart.json │ │ │ ├── mockData_singleAreaChart_2.json │ │ │ ├── mockData_singleIntervalChart.json │ │ │ ├── mockData_singleIntervalChart_2.json │ │ │ ├── mockData_singleIntervalChart_under_zero.json │ │ │ ├── mockData_singleLineChart.json │ │ │ ├── mockData_singleLineChart_timeSharing_tooltip.json │ │ │ ├── mockData_singlePointChart.json │ │ │ ├── mockData_trendChart.json │ │ │ ├── mockData_trendChart_flags.json │ │ │ ├── mock_cube_data.json │ │ │ ├── mock_cube_data2.json │ │ │ └── wallet.png │ │ ├── java │ │ │ └── com │ │ │ │ └── antgroup │ │ │ │ └── antv │ │ │ │ └── f2 │ │ │ │ └── samples │ │ │ │ ├── BridgeActivity.java │ │ │ │ ├── BridgeControl.java │ │ │ │ ├── ChartListActivity.java │ │ │ │ ├── ChartModel.java │ │ │ │ ├── MainActivity.java │ │ │ │ ├── SampleActivity.java │ │ │ │ ├── SampleActivityHorizontal.java │ │ │ │ ├── Utils.java │ │ │ │ └── charts │ │ │ │ ├── CandleChart_klineDay.java │ │ │ │ ├── CirclePieChart.java │ │ │ │ ├── MKTrendChart.java │ │ │ │ ├── MultiAreasChart.java │ │ │ │ ├── MultiIntervalChart.java │ │ │ │ ├── MultiIntervalChart_under_zero.java │ │ │ │ ├── MultiLinesChart_1.java │ │ │ │ ├── PieChart.java │ │ │ │ ├── RadarAreaChart.java │ │ │ │ ├── SectionIntervalChart.java │ │ │ │ ├── SingleAreaChart_1.java │ │ │ │ ├── SingleAreaChart_2.java │ │ │ │ ├── SingleIntervalChart_1.java │ │ │ │ ├── SingleIntervalChart_2.java │ │ │ │ ├── SingleIntervalChart_3.java │ │ │ │ ├── SingleLineChart_1.java │ │ │ │ ├── SingleLineChart_1688.java │ │ │ │ ├── SingleLineChart_2.java │ │ │ │ ├── SingleLineChart_KLine.java │ │ │ │ ├── SingleLineChart_TimeSharing_ToolTip.java │ │ │ │ └── SinglePointChart_1.java │ │ ├── jniLibs │ │ │ ├── arm64-v8a │ │ │ │ └── libc++_shared.so │ │ │ └── armeabi-v7a │ │ │ │ └── libc++_shared.so │ │ └── res │ │ │ ├── drawable-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── layout │ │ │ ├── activity_bridge.xml │ │ │ ├── activity_main.xml │ │ │ ├── activity_sample.xml │ │ │ ├── activity_sample_horizontal.xml │ │ │ ├── activity_stock_time_sharing.xml │ │ │ ├── layout_chart_canvasview.xml │ │ │ └── layout_chart_item.xml │ │ │ ├── menu │ │ │ └── menu.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── antgroup │ │ └── antv │ │ └── samples │ │ └── ExampleUnitTest.java ├── ios │ ├── Demos-Swift │ │ ├── Demos-Swift.xcodeproj │ │ │ └── project.pbxproj │ │ ├── Demos-Swift │ │ │ ├── AppDelegate.swift │ │ │ ├── Assets.xcassets │ │ │ │ ├── AccentColor.colorset │ │ │ │ │ └── Contents.json │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ ├── 128x128.png │ │ │ │ │ ├── 16x16.png │ │ │ │ │ ├── 180x180 1.png │ │ │ │ │ ├── 180x180.png │ │ │ │ │ ├── 256x256.png │ │ │ │ │ ├── 32x32.png │ │ │ │ │ ├── 512x512.png │ │ │ │ │ ├── 64x64.png │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Base.lproj │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── Main.storyboard │ │ │ ├── ChartListViewController.swift │ │ │ ├── DemoViewController.swift │ │ │ ├── Info.plist │ │ │ ├── Res │ │ │ │ ├── mockData_baseArea.json │ │ │ │ ├── mockData_baseInterval.json │ │ │ │ ├── mockData_baseInterval2.json │ │ │ │ ├── mockData_baseLine.json │ │ │ │ ├── mockData_basePie.json │ │ │ │ ├── mockData_klineDay.json │ │ │ │ ├── mockData_marketMoving.json │ │ │ │ ├── mockData_multiArea.json │ │ │ │ ├── mockData_multiAxiesLine.json │ │ │ │ ├── mockData_multiInterval.json │ │ │ │ ├── mockData_multiLines.json │ │ │ │ ├── mockData_radarArea.json │ │ │ │ ├── mockData_setionInterval.json │ │ │ │ ├── mockData_singleAreaChart_2.json │ │ │ │ ├── mockData_singleIntervalChart_under_zero.json │ │ │ │ ├── mockData_singlePointChart.json │ │ │ │ └── mockData_timeSharing.json │ │ │ ├── SceneDelegate.swift │ │ │ ├── ViewController.swift │ │ │ └── Views │ │ │ │ ├── BaseAreaChart.swift │ │ │ │ ├── BaseAreaChart2.swift │ │ │ │ ├── BaseAreaChart3.swift │ │ │ │ ├── BaseBarChart.swift │ │ │ │ ├── BaseBarChart2.swift │ │ │ │ ├── BaseLineChart.swift │ │ │ │ ├── BaseLineChart2.swift │ │ │ │ ├── BasePieChart.swift │ │ │ │ ├── BasePointChart.swift │ │ │ │ ├── CandleChart.swift │ │ │ │ ├── ContrastLineChart.swift │ │ │ │ ├── GroupBarChart.swift │ │ │ │ ├── GroupBarChart2.swift │ │ │ │ ├── GroupStackBarChart.swift │ │ │ │ ├── HistogramBarChart.swift │ │ │ │ ├── RadarAreaChart.swift │ │ │ │ └── StackedAreaChart.swift │ │ └── Podfile │ └── Demos │ │ ├── Demos.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Demos.xcscheme │ │ ├── Demos │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── 128x128.png │ │ │ │ ├── 16x16.png │ │ │ │ ├── 180x180.png │ │ │ │ ├── 256x256.png │ │ │ │ ├── 32x32.png │ │ │ │ ├── 512x512.png │ │ │ │ ├── 64x64.png │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ │ └── LaunchScreen.storyboard │ │ ├── BugFixViewController.h │ │ ├── BugFixViewController.m │ │ ├── ChartListViewController.h │ │ ├── ChartListViewController.m │ │ ├── DemoViewController.h │ │ ├── DemoViewController.m │ │ ├── Info.plist │ │ ├── Res │ │ │ ├── bugfix │ │ │ │ ├── fund_chart.json │ │ │ │ ├── indicator_chart.json │ │ │ │ ├── kline_trend.json │ │ │ │ ├── market_trend.json │ │ │ │ ├── minute_trend_indicator.json │ │ │ │ ├── minute_trend_price.json │ │ │ │ ├── mockData_marketMovingBugfix1.json │ │ │ │ └── mockData_timeSharingBugfix1.json │ │ │ ├── mockData_baseArea.json │ │ │ ├── mockData_baseInterval.json │ │ │ ├── mockData_baseLine.json │ │ │ ├── mockData_basePie.json │ │ │ ├── mockData_klineDay.json │ │ │ ├── mockData_marketMoving.json │ │ │ ├── mockData_multiArea.json │ │ │ ├── mockData_multiAxiesLine.json │ │ │ ├── mockData_multiInterval.json │ │ │ ├── mockData_multiLines.json │ │ │ ├── mockData_radarArea.json │ │ │ ├── mockData_setionInterval.json │ │ │ ├── mockData_singleAreaChart_2.json │ │ │ ├── mockData_singleIntervalChart_under_zero.json │ │ │ ├── mockData_singlePointChart.json │ │ │ └── mockData_timeSharing.json │ │ ├── ViewController.h │ │ ├── ViewController.m │ │ ├── en.lproj │ │ │ └── Localizable.strings │ │ ├── main.m │ │ ├── views │ │ │ ├── BaseAreaChart.h │ │ │ ├── BaseAreaChart.m │ │ │ ├── BaseAreaChart2.h │ │ │ ├── BaseAreaChart2.m │ │ │ ├── BaseAreaChart3.h │ │ │ ├── BaseAreaChart3.m │ │ │ ├── BaseBarChart.h │ │ │ ├── BaseBarChart.m │ │ │ ├── BaseBarChart2.h │ │ │ ├── BaseBarChart2.m │ │ │ ├── BaseGuideChart.h │ │ │ ├── BaseGuideChart.m │ │ │ ├── BaseLineChart.h │ │ │ ├── BaseLineChart.m │ │ │ ├── BaseLineChart2.h │ │ │ ├── BaseLineChart2.m │ │ │ ├── BasePieChart.h │ │ │ ├── BasePieChart.m │ │ │ ├── BasePointChart.h │ │ │ ├── BasePointChart.m │ │ │ ├── CandleChart.h │ │ │ ├── CandleChart.m │ │ │ ├── ContrastLineChart.h │ │ │ ├── ContrastLineChart.m │ │ │ ├── CyclicPieChart.h │ │ │ ├── CyclicPieChart.m │ │ │ ├── GroupBarChart.h │ │ │ ├── GroupBarChart.m │ │ │ ├── GroupBarChart2.h │ │ │ ├── GroupBarChart2.m │ │ │ ├── GroupStackBarChart.h │ │ │ ├── GroupStackBarChart.m │ │ │ ├── HistogramBarChart.h │ │ │ ├── HistogramBarChart.m │ │ │ ├── MarketMovingChart.h │ │ │ ├── MarketMovingChart.m │ │ │ ├── RadarAreaChart.h │ │ │ ├── RadarAreaChart.m │ │ │ ├── StackedAreaChart.h │ │ │ ├── StackedAreaChart.m │ │ │ ├── StripChart.h │ │ │ ├── StripChart.m │ │ │ ├── TimeSharingChart.h │ │ │ ├── TimeSharingChart.m │ │ │ └── bugfix │ │ │ │ ├── KLineTrendBugFix1.h │ │ │ │ ├── KLineTrendBugFix1.m │ │ │ │ ├── MarketMovingBugFix1.h │ │ │ │ ├── MarketMovingBugFix1.m │ │ │ │ ├── TimeSharingBugFix1.h │ │ │ │ └── TimeSharingBugFix1.m │ │ ├── zh-HK.lproj │ │ │ └── LaunchScreen.strings │ │ └── zh-Hans.lproj │ │ │ ├── LaunchScreen.strings │ │ │ └── Localizable.strings │ │ ├── F2Native.entitlements │ │ └── Podfile ├── videos │ └── ios_demo.mp4 └── webassembly │ ├── f2wasm.js │ ├── f2wasm.wasm │ ├── index.html │ └── run.sh ├── docs ├── api │ ├── API.en.md │ ├── API.zh.md │ ├── F2Area.en.md │ ├── F2Area.zh.md │ ├── F2Axis.en.md │ ├── F2Axis.zh.md │ ├── F2CanvasView.en.md │ ├── F2CanvasView.zh.md │ ├── F2Chart.en.md │ ├── F2Chart.zh.md │ ├── F2Guide.en.md │ ├── F2Guide.zh.md │ ├── F2Interval.en.md │ ├── F2Interval.zh.md │ ├── F2Legend.en.md │ ├── F2Legend.zh.md │ ├── F2Line.en.md │ ├── F2Line.zh.md │ ├── F2Scale.en.md │ └── F2Scale.zh.md ├── examples │ ├── area │ │ ├── area.en.md │ │ ├── area.zh.md │ │ ├── stackedArea.en.md │ │ └── stackedArea.zh.md │ ├── bar.en.md │ ├── bar.zh.md │ ├── column │ │ ├── column.en.md │ │ ├── column.zh.md │ │ ├── dodgeColumn.en.md │ │ └── dodgeColumn.zh.md │ ├── line │ │ ├── line.en.md │ │ ├── line.zh.md │ │ ├── multiLine.en.md │ │ └── multiLine.zh.md │ ├── pie.en.md │ └── pie.zh.md └── tutorial │ ├── getting-started.en.md │ ├── getting-started.zh.md │ └── manual │ ├── attribute.en.md │ ├── attribute.zh.md │ ├── coordinate.en.md │ ├── coordinate.zh.md │ ├── data.en.md │ ├── data.zh.md │ ├── geometry.en.md │ ├── geometry.zh.md │ ├── grammar.en.md │ ├── grammar.zh.md │ ├── scale.en.md │ ├── scale.zh.md │ ├── understanding.en.md │ └── understanding.zh.md ├── externals.d.ts ├── gatsby-browser.js ├── gatsby-config.js ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── ios ├── F2.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ ├── F2.xcscheme │ │ └── F2Tests.xcscheme ├── F2 │ ├── F2-Prefix.pch │ ├── F2.h │ ├── F2Callback.h │ ├── F2Callback.mm │ ├── F2CanvasContext.h │ ├── F2CanvasContext.mm │ ├── F2CanvasView.h │ ├── F2CanvasView.mm │ ├── F2Chart.h │ ├── F2Chart.mm │ ├── F2Coordinate.h │ ├── F2Coordinate.mm │ ├── F2Geom.h │ ├── F2Geom.mm │ ├── F2GestureListener.h │ ├── F2GestureListener.m │ ├── F2Guide.h │ ├── F2Guide.mm │ ├── F2Utils.h │ └── F2Utils.m ├── F2Tests │ ├── F2CanvasTests.mm │ ├── F2ChartBridgeTests.mm │ ├── F2ChartTests.mm │ ├── F2ScalesTests.mm │ ├── F2TestUtil.h │ ├── F2TestUtil.m │ ├── F2UtilsTests.mm │ └── Info.plist └── Info.plist ├── package-lock.json ├── package.json ├── settings.gradle ├── site ├── locale.json └── pages │ ├── index.en.tsx │ └── index.zh.tsx ├── tests ├── CMakeLists.txt ├── e2e │ ├── BaseInterval.h │ ├── Baseline.h │ ├── F2PixelMatch.h │ ├── F2PixelMatch.mm │ ├── MarketMoving.h │ └── pixelmatch.hpp ├── main.cpp ├── res │ ├── badcase.jpg │ ├── black.png │ ├── chart_bridge.json │ ├── e2e │ │ ├── baseInterval.jpeg │ │ ├── baseLine.jpeg │ │ ├── chartBridge.jpeg │ │ └── marketMoving.jpeg │ ├── kline_day.json │ ├── kline_minutes_5.json │ ├── kline_minutes_60.json │ ├── mockData_baseInterval.json │ ├── mockData_baseLine.json │ ├── mockData_marketTrend.json │ ├── red.png │ ├── transparent.png │ ├── white&black.png │ ├── white&red.png │ └── white.png ├── run.sh └── unit │ ├── XChart.h │ ├── bridge │ └── ChartBridge.h │ ├── canvas │ ├── CanvasColorParser.h │ ├── CanvasFontParser.h │ ├── Cartesian.h │ └── Polar.h │ ├── scale │ ├── Category.h │ ├── KLineCat.h │ ├── Linear.h │ ├── ScaleController.h │ └── TimeSharingLinear.h │ └── utils │ ├── Point.h │ ├── StringUtils.h │ ├── Vector2d.h │ ├── XTime.h │ └── json.h └── webassembly └── CMakeLists.txt /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android Tests 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: macos-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | - name: set up JDK 11 17 | uses: actions/setup-java@v3 18 | with: 19 | java-version: '11' 20 | ndk-version: 22.1.7171670 21 | distribution: 'temurin' 22 | cache: gradle 23 | 24 | - name: Grant execute permission for gradlew 25 | run: chmod +x gradlew 26 | - name: Build with Gradle 27 | run: ./gradlew android:f2native:connectedAndroidTest 28 | -------------------------------------------------------------------------------- /.github/workflows/ios.yml: -------------------------------------------------------------------------------- 1 | name: iOS Tests 2 | 3 | on: 4 | push: 5 | branches: [ "master", "2.x" ] 6 | pull_request: 7 | branches: [ "master", "2.x" ] 8 | 9 | jobs: 10 | build: 11 | name: Build and Test default scheme using any available iPhone simulator 12 | runs-on: macos-latest 13 | 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v3 17 | - name: Run Tests 18 | run: | 19 | cd ios 20 | ls 21 | xcodebuild test -project F2.xcodeproj -scheme F2Tests -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 12,OS=15.2' 22 | -------------------------------------------------------------------------------- /.github/workflows/mirror.yml: -------------------------------------------------------------------------------- 1 | name: 🤖 Sync to Gitee Mirror 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: 🔁 Sync to Gitee 10 | uses: wearerequired/git-mirror-action@master 11 | env: 12 | # 注意在 Settings->Secrets 配置 GITEE_RSA_PRIVATE_KEY 13 | SSH_PRIVATE_KEY: ${{ secrets.GITEE_RSA_PRIVATE_KEY }} 14 | with: 15 | # 注意替换为你的 GitHub 源仓库地址 16 | source-repo: https://github.com/antvis/F2Native.git 17 | # 注意替换为你的 Gitee 目标仓库地址 18 | destination-repo: git@gitee.com:antv-f2native/antv-f2native.git 19 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .cache 2 | package.json 3 | package-lock.json 4 | public 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": true, 4 | "singleQuote": true, 5 | "tabWidth": 2 6 | } 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | add_subdirectory(core) 4 | 5 | #如何只在debug的时候增加 6 | #add_subdirectory(tests) -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | f2native.antv.vision -------------------------------------------------------------------------------- /LEGAL.md: -------------------------------------------------------------------------------- 1 | Legal Disclaimer 2 | 3 | Within this source code, the comments in Chinese shall be the original, governing version. Any comment in other languages are for reference only. In the event of any conflict between the Chinese language version comments and other language version comments, the Chinese language version shall prevail. 4 | 5 | 法律免责声明 6 | 7 | 关于代码注释部分,中文注释为官方版本,其它语言注释仅做参考。中文注释可能与其它语言注释存在不一致,当中文注释与其它语言注释存在不一致时,请以中文注释为准。 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 AntV team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/LICENSE.md -------------------------------------------------------------------------------- /android/f2native/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /android/f2native/src/androidTest/java/com/antgroup/antv/f2/F2InstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class F2InstrumentedTest { 20 | @Test 21 | public void runAllTest() { 22 | if(BuildConfig.DEBUG) { 23 | System.loadLibrary("f2tests"); 24 | F2TestProxy test = new F2TestProxy(); 25 | 26 | //所有c++的单测都在JNI的runTest中 27 | assertEquals(test.runTest(), 1); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /android/f2native/src/androidTest/java/com/antgroup/antv/f2/F2TestProxy.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2; 2 | 3 | public class F2TestProxy { 4 | public native int runTest(); 5 | } 6 | -------------------------------------------------------------------------------- /android/f2native/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /android/f2native/src/main/java/com/antgroup/antv/f2/F2CSUtils.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2; 2 | 3 | 4 | /** 5 | * finanacechart 仓库sync.js脚本自动替换当前类 6 | */ 7 | public class F2CSUtils { 8 | 9 | public static void showUseNativeCanvasToast(String content) { 10 | } 11 | 12 | // 是否开启白屏检测开关 13 | public static boolean isDetectEnable() { 14 | // kF2NativeReleaseProductDetKey 15 | return true; 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /android/f2native/src/main/java/com/antgroup/antv/f2/F2ChartBridgeListener.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2; 2 | 3 | /** 4 | * cube bridge中invokeMethod调用的callback 5 | * author by luna 6 | * date on 2022/5/28 7 | */ 8 | 9 | public abstract class F2ChartBridgeListener { 10 | 11 | private String methodName; 12 | private String bizId; 13 | 14 | public F2ChartBridgeListener(String methodName, String bizId) { 15 | this.methodName = methodName; 16 | this.bizId = bizId; 17 | } 18 | 19 | public String getMethodName() { 20 | return methodName; 21 | } 22 | 23 | public String getBizId() { 24 | return bizId; 25 | } 26 | 27 | public abstract void onResult(String methodName, String bizId, String result); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /android/f2native/src/main/java/com/antgroup/antv/f2/F2Constants.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2; 2 | 3 | /** 4 | * @author qingyuan.yl 5 | * @date 2020-09-22 6 | */ 7 | public class F2Constants { 8 | 9 | public static final int CODE_SUCCESS = 0; 10 | public static final int CODE_FAIL_UNKNOWN = -1; 11 | public static final int CODE_INIT_EGL_FAIL = 1; 12 | public static final int CODE_INIT_CANVAS_CONTEXT_FAIL = 2; 13 | public static final int CODE_CREATE_CANVAS_2D_CONTEXT_FAIL = 3; 14 | public static final int CODE_RESUME_CANVAS_FAIL = 4; 15 | 16 | public static boolean isSuccessCode(int code) { 17 | return code == CODE_SUCCESS; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /android/f2native/src/main/java/com/antgroup/antv/f2/F2DetectManager.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2; 2 | 3 | 4 | import android.graphics.Bitmap; 5 | 6 | /** 7 | * 用于检测白屏 8 | */ 9 | public class F2DetectManager { 10 | 11 | public void sendRenderDetectEvent(Bitmap snapshotBitmap, String appId, String bizType, long renderDuration, boolean renderSuccess, 12 | int renderCmdCount, boolean drawSuccess, 13 | int width, int height, double ratio, String chartId) { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /android/f2native/src/main/java/com/antgroup/antv/f2/F2Event.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2; 2 | 3 | 4 | /** 5 | * finanacechart 仓库脚本自动替换当前类 6 | * 7 | * @author qingyuan.yl 8 | */ 9 | public class F2Event { 10 | 11 | // native canvas init调用 12 | public static void eventPage(String appId, String bizType, String desc) { 13 | } 14 | 15 | /** 16 | * native canvas绘制调用 17 | * 18 | * @param renderDuration c++渲染是时长 19 | * @param renderSuccess c++渲染是否成功 20 | * @param renderCmdCount c++侧渲染的指令 21 | * @param drawSuccess native侧上屏是否成功 22 | * @param bitmapBytes 白屏的二进制图片,非白屏的时候为null 23 | * @param detectDuration 截屏&分析白屏的时间消耗 24 | * @param desc chartId+扩展描述 25 | */ 26 | public static void eventDetectRender(String appId, String bizType, long renderDuration, boolean renderSuccess, 27 | int renderCmdCount, boolean drawSuccess, byte[] bitmapBytes, long detectDuration, 28 | int width, int height, double ratio, String desc) { 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /android/f2native/src/main/java/com/antgroup/antv/f2/F2Function.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * @author qingyuan.yl 7 | * @date 2020/12/1 8 | */ 9 | public abstract class F2Function { 10 | 11 | protected String functionId = null; 12 | 13 | public F2Function() { 14 | this.functionId = UUID.randomUUID().toString(); 15 | } 16 | 17 | final void bindChart(F2Chart chart) { 18 | chart.bindChart(functionId, this); 19 | } 20 | 21 | public abstract F2Config execute(String param); 22 | } 23 | -------------------------------------------------------------------------------- /android/f2native/src/main/java/com/antgroup/antv/f2/F2Log.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * @author qingyuan.yl 7 | * @date 2020-09-18 8 | */ 9 | public final class F2Log { 10 | 11 | private static final String TAG = "F2Native"; 12 | 13 | public static void i(String traceId, String content) { 14 | Log.i(TAG + "[" + threadName() + "]|" + traceId, content); 15 | } 16 | 17 | public static void w(String traceId, String content) { 18 | Log.w(TAG + "[" + threadName() + "]|" + traceId, content); 19 | } 20 | 21 | public static void e(String traceId, String content) { 22 | Log.e(TAG + "[" + threadName() + "]|" + traceId, content); 23 | } 24 | 25 | public static void e(String traceId, String msg, Throwable t) { 26 | Log.e(TAG + "[" + threadName() + "]|" + traceId, msg, t); 27 | } 28 | 29 | private static String threadName() { 30 | return Thread.currentThread().getName(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /android/f2native/src/main/java/com/antgroup/antv/f2/base/F2BaseCanvasView.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2.base; 2 | 3 | import android.view.View; 4 | 5 | import com.antgroup.antv.f2.F2CanvasView; 6 | import com.antgroup.antv.f2.F2Config; 7 | 8 | /** 9 | * 业务层调用F2CanvasView的接口,antg和native canvas子类分别实现 10 | */ 11 | public interface F2BaseCanvasView { 12 | 13 | // 单位是px 14 | void init(int widthPixel, int heightPixel, F2Config config); 15 | 16 | View getView(); 17 | 18 | void setAdapter(F2CanvasView.Adapter adapter); 19 | 20 | void setOnCanvasTouchListener(F2CanvasView.OnCanvasTouchListener onCanvasTouchListener); 21 | 22 | void initCanvasContext(); 23 | 24 | void initCanvasContext(F2Config config); 25 | 26 | long getNativeCanvas(); 27 | 28 | boolean swapBuffer(); 29 | 30 | void destroy(); 31 | 32 | void postCanvasDraw(); 33 | 34 | boolean hasAdapter(); 35 | 36 | void sendRenderDetectEvent(long renderDuration, boolean renderSuccess, int renderCmdCount, 37 | boolean drawSuccess, String chartId); 38 | 39 | boolean isDrawSuccess(); 40 | 41 | boolean hadOOM(); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /android/f2native/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | f2native 3 | 4 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = "1.4.31" 5 | repositories { 6 | google() 7 | jcenter() 8 | 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.5.3' 12 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | } 15 | } 16 | 17 | allprojects { 18 | project.ext.meta = [:] 19 | repositories { 20 | google() 21 | jcenter() 22 | maven { url 'https://jitpack.io' } 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | 30 | rootProject.extensions.sdks = [ 31 | 'Gradle' : '3.0.1', 32 | 'CompileSDK' : 28, 33 | 'BuildTool' : '28.0.3', 34 | 'MinSDK' : 18, 35 | 'TargetSDK' : 28, 36 | 'JUnit' : '4.12', 37 | 'Support' : '26.0.2', 38 | 'ABIs' : ["armeabi-v7a","arm64-v8a"], 39 | 'EXCLUDE_CPP_SHARED' : false 40 | ] 41 | -------------------------------------------------------------------------------- /core/android/CanvasImage.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // CanvasImage.cpp 3 | // F2 4 | // 5 | // Created by weiqing.twq on 2022/1/17. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #if defined(ANDROID) 10 | 11 | #include "graphics/canvas/CanvasImage.h" 12 | 13 | using namespace xg; 14 | using namespace xg::canvas; 15 | 16 | CanvasImage::~CanvasImage() { 17 | if (image_) { 18 | image_ = nullptr; 19 | } 20 | } 21 | 22 | void CanvasImage::OnLoad(std::function finished) { 23 | //通过JNI方法调用Java下载 24 | } 25 | 26 | float CanvasImage::GetWidth() { 27 | return 0; 28 | } 29 | 30 | float CanvasImage::GetHeight() { 31 | return 0; 32 | } 33 | 34 | #endif //ANDROID 35 | -------------------------------------------------------------------------------- /core/android/F2NativeJNI.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "JNIUtil.h" 6 | 7 | #ifndef XG_F2_NATIVE_ANDROID_JNI_H 8 | #define XG_F2_NATIVE_ANDROID_JNI_H 9 | 10 | #define CODE_SUCCESS 0 11 | #define CODE_FAIL_UNKNOWN -1 12 | #define CODE_INIT_EGL_FAIL 1 13 | #define CODE_INIT_CANVAS_CONTEXT_FAIL 2 14 | #define CODE_CREATE_CANVAS_2D_CONTEXT_FAIL 3 15 | #define CODE_RESUME_CANVAS_FAIL 4 16 | 17 | #define LOG_BUFFER_SIZE 2048 18 | 19 | namespace xg { 20 | namespace jni { 21 | 22 | void InnerLog(int level, std::string traceId, const char *fmt, ...); 23 | 24 | } // namespace jni 25 | } // namespace xg 26 | 27 | #define F2_LOG_INFO 1 28 | #define F2_LOG_WARN 2 29 | #define F2_LOG_ERROR 3 30 | 31 | #define F2_LOG_I(traceId, ...) ((void)xg::jni::InnerLog(F2_LOG_INFO, traceId, __VA_ARGS__)) 32 | #define F2_LOG_W(traceId, ...) ((void)xg::jni::InnerLog(F2_LOG_WARN, traceId, __VA_ARGS__)) 33 | #define F2_LOG_E(traceId, ...) ((void)xg::jni::InnerLog(F2_LOG_ERROR, traceId, __VA_ARGS__)) 34 | 35 | #endif // XG_F2_NATIVE_ANDROID_JNI_H 36 | -------------------------------------------------------------------------------- /core/android/JNIUtil.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "JavaRef.h" 5 | 6 | #ifndef XG_F2_NATIVE_ANDROID_JNI_UTILS_H 7 | #define XG_F2_NATIVE_ANDROID_JNI_UTILS_H 8 | 9 | namespace xg { 10 | namespace jni { 11 | void InitJavaVM(JavaVM *vm); 12 | 13 | JavaVM *GetJVM(); 14 | 15 | JNIEnv *GetJniEnv(); 16 | 17 | JNIEnv *GetJniEnvSafe(); 18 | 19 | JNIEnv *AttachCurrentThread(); 20 | 21 | void DetachFromVM(); 22 | 23 | ScopedJavaLocalRef StringToJavaString(JNIEnv *env, const std::string &str); 24 | 25 | ScopedJavaLocalRef VectorToJFloatArray(JNIEnv *env, const std::vector ¶ms); 26 | 27 | ScopedJavaLocalRef VectorToJIntArray(JNIEnv *env, const std::vector ¶ms); 28 | 29 | bool HasException(JNIEnv *env); 30 | 31 | bool ClearException(JNIEnv *env); 32 | 33 | std::string JavaStringToString(JNIEnv *env, jstring string); 34 | 35 | jstring StringToJString(JNIEnv *env, const std::string &u8_string); 36 | 37 | void native_clog(int level, const char *tag, const char *msg); 38 | 39 | // std::string GetJavaExceptionInfo(JNIEnv *env, jthrowable java_throwable); 40 | } // namespace jni 41 | } // namespace xg 42 | 43 | #endif // XG_F2_NATIVE_ANDROID_JNI_UTILS_H 44 | -------------------------------------------------------------------------------- /core/android/JavaChartBridgeCallBack.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by luna on 2022/5/27. 3 | // 4 | 5 | #ifndef CHART_NATIVE_CORE_JAVACHARTBRIDGECALLBACK_H 6 | #define CHART_NATIVE_CORE_JAVACHARTBRIDGECALLBACK_H 7 | 8 | #include 9 | #include 10 | #include "JavaRef.h" 11 | 12 | namespace xg { 13 | namespace bridge { 14 | class JavaChartBridgeCallBack { 15 | public: 16 | /** 17 | * nativeBridgeObject 传入Android层的F2ChartBridge对象 18 | */ 19 | JavaChartBridgeCallBack(jobject nativeBridgeObject); 20 | 21 | ~JavaChartBridgeCallBack(); 22 | 23 | /** 24 | * chartbridge callback的函数,反射调用Android层的函数 25 | * @param message callback的数据 26 | */ 27 | void BridgeCallback(const std::string &message); 28 | 29 | private: 30 | /** 31 | * load class 32 | */ 33 | bool InitClass(JNIEnv *env); 34 | 35 | JNIEnv *env_ = nullptr; 36 | jmethodID invokeCallbackMethod_ = nullptr; 37 | // 用于反射callback 38 | xg::jni::ScopedJavaGlobalRef *nativeBridgeObject_ = nullptr; 39 | 40 | }; 41 | } 42 | } 43 | 44 | 45 | #endif //CHART_NATIVE_CORE_JAVACHARTBRIDGECALLBACK_H 46 | -------------------------------------------------------------------------------- /core/graphics/animate/TimeLine.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_ANIMATE_TIMELINE_H 2 | #define XG_GRAPHICS_ANIMATE_TIMELINE_H 3 | 4 | #include "Animator.h" 5 | 6 | namespace xg { 7 | class XChart; 8 | namespace animate { 9 | class TimeLine { 10 | public: 11 | TimeLine(XChart *chart) : chart_(chart) {} 12 | 13 | void Play(); 14 | 15 | void Stop(); 16 | 17 | void Clear() { playing_ = false; } 18 | 19 | void PushAnim(AnimInfo &&animInfo); 20 | 21 | ~TimeLine(); 22 | 23 | protected: 24 | void OnUpdate(); 25 | 26 | private: 27 | void frameLoop(); 28 | 29 | private: 30 | XChart *chart_; 31 | bool playing_ = false; 32 | std::vector animInfos_; 33 | long long time_; 34 | }; 35 | } // namespace animate 36 | } // namespace xg 37 | 38 | #endif // XG_GRAPHICS_ANIMATE_TIMELINE_H 39 | -------------------------------------------------------------------------------- /core/graphics/canvas/Canvas.cpp: -------------------------------------------------------------------------------- 1 | #include "Canvas.h" 2 | 3 | using namespace xg; 4 | 5 | void canvas::Canvas::Draw(canvas::CanvasContext &context) { 6 | if (this->IsDestroyed()) { 7 | return; 8 | } 9 | 10 | context.ClearRect(origin.x, origin.y, size.width, size.height); 11 | 12 | this->DrawInner(context); 13 | } 14 | -------------------------------------------------------------------------------- /core/graphics/canvas/Canvas.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_CANVAS_H 2 | #define XG_GRAPHICS_CANVAS_H 3 | 4 | #include "CanvasContext.h" 5 | #include "../shape/Group.h" 6 | 7 | namespace xg { 8 | namespace canvas { 9 | 10 | class Canvas : public shape::Group { 11 | public: 12 | Canvas() : Group() {} 13 | 14 | void ChangeSize(double x, double y, double width, double height) { 15 | origin = {x, y}; 16 | size = {width, height}; 17 | } 18 | 19 | void Draw(canvas::CanvasContext &context); 20 | 21 | void Destroy() override { 22 | Group::Destroy(); 23 | } 24 | 25 | private: 26 | util::Point origin{0, 0}; 27 | util::Size size{0, 0}; 28 | }; 29 | } // namespace canvas 30 | } // namespace xg 31 | 32 | #endif // XG_GRAPHICS_CANVAS_H 33 | -------------------------------------------------------------------------------- /core/graphics/canvas/CanvasColorParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by ruize on 2022/1/7. 3 | // 4 | 5 | #ifndef XG_GRAPHICS_CANVAS_CANVASCOLORPARSER_H 6 | #define XG_GRAPHICS_CANVAS_CANVASCOLORPARSER_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace xg { 14 | 15 | namespace canvas { 16 | 17 | struct CanvasColor { 18 | float r = 0; 19 | float g = 0; 20 | float b = 0; 21 | float a = 0; 22 | }; 23 | 24 | class CanvasColorParser { 25 | 26 | public: 27 | /* 28 | *入口解析函数 29 | *支持解析#RRGGBBAA,#RGB,字符串(white,red),rgba(1, 1, 1, 1), rgb(1, 1, 1), hsl(0, 100%, 50%),hsla(120,100%,50%,0.3 30 | */ 31 | static bool Parse(const std::string &str, CanvasColor &output); 32 | 33 | /* 34 | * 解析成安卓平台的ARGB格式 35 | */ 36 | static int RGBAToHex(const CanvasColor &color); 37 | private: 38 | static void InitColorMapIfEmpty(); 39 | 40 | private: 41 | static std::unordered_map colorMap; 42 | static std::mutex global_mutex; 43 | static std::string hex_digit; 44 | }; 45 | 46 | } // namespace canvas 47 | } // namespace xg 48 | 49 | #endif // XG_GRAPHICS_CANVAS_CANVASCOLORPARSER_H 50 | -------------------------------------------------------------------------------- /core/graphics/canvas/CanvasImage.h: -------------------------------------------------------------------------------- 1 | // 2 | // CanvasImage.hpp 3 | // F2 4 | // 5 | // Created by weiqing.twq on 2022/1/17. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #ifndef XG_GRAPHICS_CANVAS_CANVASIMAGE_H 10 | #define XG_GRAPHICS_CANVAS_CANVASIMAGE_H 11 | 12 | #include 13 | #include 14 | 15 | namespace xg { 16 | namespace canvas { 17 | 18 | class CanvasImage { 19 | public: 20 | CanvasImage() = delete; 21 | CanvasImage(const std::string &url) : url_(url){}; 22 | ~CanvasImage(); 23 | 24 | void OnLoad(std::function finished); 25 | 26 | inline void *GetImage() { return image_; } 27 | 28 | float GetWidth(); 29 | 30 | float GetHeight(); 31 | 32 | inline const std::string &GetURL() { return url_; } 33 | 34 | inline bool IsValid() const { return image_ != nullptr; } 35 | 36 | private: 37 | //在ios上是CGImageRef 38 | void *image_ = nullptr; 39 | //在ios上是一个下载器 40 | void *downloader_ = nullptr; 41 | //图片的url地址 42 | std::string url_; 43 | }; 44 | 45 | } // namespace canvas 46 | } // namespace xg 47 | 48 | #endif /* XG_GRAPHICS_CANVAS_CANVASIMAGE_H */ 49 | -------------------------------------------------------------------------------- /core/graphics/func/Command.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_FUNC_COMMAND_H 2 | #define XG_GRAPHICS_FUNC_COMMAND_H 3 | 4 | namespace xg { 5 | namespace func { 6 | struct Command { 7 | virtual void run() {} 8 | 9 | virtual ~Command() {} 10 | }; 11 | 12 | template struct CommandImpl : Command { 13 | CommandImpl(Function _func) : func(_func) {} 14 | virtual void run() override { func(); } 15 | Function func; 16 | }; 17 | 18 | template Command *CreateCommand(Function f) { return new CommandImpl(f); } 19 | 20 | } // namespace func 21 | } // namespace xg 22 | 23 | #endif // XG_GRAPHICS_FUNC_COMMAND_H 24 | -------------------------------------------------------------------------------- /core/graphics/geom/Area.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_GEOM_AREA_H 2 | #define XG_GRAPHICS_GEOM_AREA_H 3 | 4 | #include "Geom.h" 5 | 6 | namespace xg { 7 | class XChart; 8 | namespace geom { 9 | 10 | class Area : public AbstractGeom { 11 | public: 12 | Area(Group *_container, utils::Tracer *tracer) : AbstractGeom(_container, tracer) { 13 | type_ = "area"; 14 | shapeType_ = "area"; 15 | sortable_ = true; 16 | generatePoints_ = true; 17 | } 18 | 19 | void BeforeMapping(XChart &chart, XDataGroup &dataArray) override; 20 | 21 | private: 22 | nlohmann::json CreateShapePointsCfg(XChart &chart, XData &data); 23 | 24 | nlohmann::json GetAreaPoints(XChart &chart, XData &data, nlohmann::json &cfg); 25 | }; 26 | } // namespace geom 27 | } // namespace xg 28 | 29 | #endif /* XG_GRAPHICS_GEOM_AREA_H */ 30 | -------------------------------------------------------------------------------- /core/graphics/geom/Candle.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_GEOM_CANDLE_H 2 | #define XG_GRAPHICS_GEOM_CANDLE_H 3 | 4 | #include "Geom.h" 5 | #include "../util/json.h" 6 | 7 | namespace xg { 8 | namespace geom { 9 | 10 | class Candle : public AbstractGeom { 11 | public: 12 | Candle(Group *_container, utils::Tracer *tracer) : AbstractGeom(_container, tracer) { 13 | type_ = "candle"; 14 | generatePoints_ = true; 15 | this->styleConfig_ = { 16 | {"lineWidth", 1}, // lineWidth 17 | {"fill", {"#1CAA3D", "#808080", "#F4333C"}}, // or {"strock", {"#1CAA3D", "#808080", "#F4333C"}}, colors: [down, equal, up] 18 | }; 19 | } 20 | 21 | nlohmann::json CreateShapePointsCfg(XChart &chart, XData &item, size_t index); 22 | 23 | void BeforeMapping(XChart &chart, XDataGroup &dataArray) override; 24 | 25 | void Draw(XChart &chart, const XDataArray &groupData, std::size_t start, std::size_t end) const override; 26 | 27 | private: 28 | nlohmann::json getRectPoints(nlohmann::json &cfg); 29 | nlohmann::json getLinePoints(nlohmann::json &cfg); 30 | }; 31 | } // namespace geom 32 | } // namespace xg 33 | 34 | #endif /* XG_GRAPHICS_GEOM_CANDLE_H */ 35 | -------------------------------------------------------------------------------- /core/graphics/geom/Interval.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_GEOM_INTERVAL_H 2 | #define XG_GRAPHICS_GEOM_INTERVAL_H 3 | 4 | #include "Geom.h" 5 | #include "../util/json.h" 6 | 7 | namespace xg { 8 | namespace geom { 9 | 10 | class Interval : public AbstractGeom { 11 | public: 12 | Interval(Group *_container, utils::Tracer *tracer) : AbstractGeom(_container, tracer) { 13 | type_ = "interval"; 14 | generatePoints_ = true; 15 | nlohmann::json defaultCfg ={{"lineWidth", 1}, {"stroke", "#ffffff"}, {"widthRatio", 0.5}}; 16 | if(this->styleConfig_.is_object()) { 17 | this->styleConfig_.merge_patch(defaultCfg); 18 | } 19 | } 20 | 21 | float GetDefaultWidthRatio(XChart &chart); 22 | 23 | nlohmann::json CreateShapePointsCfg(XChart &chart, XData &item, size_t index); // {x, y, y0, size} 24 | 25 | void BeforeMapping(XChart &chart, XDataGroup &dataArray) override; 26 | 27 | nlohmann::json getRectPoints(nlohmann::json &cfg); 28 | 29 | virtual void Draw(XChart &chart, const XDataArray &groupData, std::size_t start, std::size_t end) const override; 30 | 31 | Interval &Tag(const std::string &json = "{}"); 32 | 33 | private: 34 | nlohmann::json tagConfig_; 35 | }; 36 | } // namespace geom 37 | } // namespace xg 38 | 39 | #endif /* XG_GRAPHICS_GEOM_INTERVAL_H */ 40 | -------------------------------------------------------------------------------- /core/graphics/geom/Line.cpp: -------------------------------------------------------------------------------- 1 | #include "Line.h" 2 | #include "../XChart.h" 3 | 4 | using namespace xg; 5 | 6 | void geom::Line::BeforeMapping(XChart &chart, XDataGroup &dataArray) { 7 | if(!styleConfig_.is_object() || styleConfig_.empty()) 8 | return; 9 | 10 | auto &xScale = chart.GetScale(GetXScaleField()); 11 | 12 | for(std::size_t index = 0; index < dataArray.size(); ++index) { 13 | 14 | auto &groupData = dataArray[index]; 15 | std::size_t start = 0, end = groupData.size() - 1; 16 | if(scale::IsCategory(xScale.GetType())) { 17 | start = fmax(start, xScale.min); 18 | end = fmin(end, xScale.max); 19 | } 20 | 21 | for(std::size_t position = start; position <= end; ++position) { 22 | auto &item = groupData[position]; 23 | item._style = styleConfig_; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /core/graphics/geom/Line.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_GEOM_LINE_H 2 | #define XG_GRAPHICS_GEOM_LINE_H 3 | 4 | #include "Geom.h" 5 | 6 | namespace xg { 7 | namespace geom { 8 | 9 | class Line : public AbstractGeom { 10 | public: 11 | Line(Group *_container, utils::Tracer *tracer) : AbstractGeom(_container, tracer) { 12 | type_ = "line"; 13 | sortable_ = true; 14 | } 15 | 16 | void BeforeMapping(XChart &chart, XDataGroup &dataArray) override; 17 | }; 18 | } // namespace geom 19 | } // namespace xg 20 | 21 | #endif /* XG_GRAPHICS_GEOM_LINE_H */ 22 | -------------------------------------------------------------------------------- /core/graphics/geom/Path.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_GEOM_PATH_H 2 | #define XG_GRAPHICS_GEOM_PATH_H 3 | 4 | #include "Geom.h" 5 | 6 | namespace xg { 7 | namespace geom { 8 | 9 | class Path : public AbstractGeom { 10 | public: 11 | Path(Group *_container, utils::Tracer *tracer) : AbstractGeom(_container, tracer) { 12 | type_ = "path"; 13 | shapeType_ = "line"; 14 | } 15 | }; 16 | } // namespace geom 17 | } // namespace xg 18 | 19 | #endif /* XG_GRAPHICS_GEOM_PATH_H */ 20 | -------------------------------------------------------------------------------- /core/graphics/geom/Point.cpp: -------------------------------------------------------------------------------- 1 | #include "Point.h" 2 | #include "../XChart.h" 3 | 4 | using namespace xg; 5 | 6 | void geom::Point::BeforeMapping(XChart &chart, XDataGroup &dataArray) { 7 | auto &xScale = chart.GetScale(GetXScaleField()); 8 | for(std::size_t index = 0; index < dataArray.size(); ++index) { 9 | 10 | auto &groupData = dataArray[index]; 11 | 12 | std::size_t start = 0, end = groupData.size() - 1; 13 | if(scale::IsCategory(xScale.GetType())) { 14 | start = fmax(start, xScale.min); 15 | end = fmin(end, xScale.max); 16 | } 17 | 18 | for(std::size_t position = start; position <= end; ++position) { 19 | auto &item = groupData[position]; 20 | item._style = this->styleConfig_; 21 | } 22 | } 23 | } 24 | 25 | void geom::Point::Draw(XChart &chart, const XDataArray &groupData, std::size_t start, std::size_t end) const { 26 | for(std::size_t i = start; i <= end; ++i) { 27 | auto &item = groupData[i]; 28 | chart.geomShapeFactory_->DrawGeomShape(chart, type_, shapeType_, item, i, i + 1, *this->container_, this->connectNulls_); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /core/graphics/geom/Point.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_GEOM_POINT_H 2 | #define XG_GRAPHICS_GEOM_POINT_H 3 | 4 | #include "Geom.h" 5 | 6 | namespace xg { 7 | class XChart; 8 | 9 | namespace geom { 10 | class Point : public AbstractGeom { 11 | public: 12 | Point(Group *_container, utils::Tracer *tracer) : AbstractGeom(_container, tracer) { 13 | type_ = "point"; 14 | sortable_ = true; 15 | this->styleConfig_ = {}; 16 | } 17 | 18 | void BeforeMapping(XChart &chart, XDataGroup &dataArray) override; 19 | 20 | void Draw(XChart &chart, const XDataArray &groupData, std::size_t start, std::size_t end) const override; 21 | }; 22 | } // namespace geom 23 | } // namespace xg 24 | 25 | #endif // XG_GRAPHICS_GEOM_POINT_H 26 | -------------------------------------------------------------------------------- /core/graphics/global.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_GLOBAL_H 2 | #define XG_GRAPHICS_GLOBAL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #if defined(__APPLE__) 9 | #include 10 | #endif 11 | 12 | #define GLOBAL_SIZES \ 13 | std::vector { 4.f, 10.f } 14 | #define GLOBAL_LINE_DASH \ 15 | std::vector { 4, 4 } 16 | #define SNAP_COUNT_ARRAY \ 17 | std::vector { 1, 1.2, 1.5, 2, 2.2, 2.4, 2.5, 3, 4, 5, 6, 7.5, 8, 10 } 18 | 19 | namespace xg { 20 | //默认颜色 21 | constexpr const char *GLOBAL_COLORS[] = {"#1890FF", "#2FC25B", "#FACC14", "#223273", 22 | "#8543E0", "#13C2C2", "#3436C7", "#F04864"}; 23 | //默认刻度数量 24 | constexpr int DEFAULT_COUNT = 5; 25 | 26 | //默认透明度 27 | constexpr float DEFAULT_OPACITY = NAN; 28 | 29 | #if TARGET_OS_MACCATALYST == 1 30 | constexpr float DEFAULT_FONTSIZE = 17.f; 31 | #else 32 | constexpr float DEFAULT_FONTSIZE = 10.f; 33 | #endif 34 | 35 | } // namespace xg 36 | 37 | #endif // XG_GRAPHICS_GLOBAL_H 38 | -------------------------------------------------------------------------------- /core/graphics/guide/Background.cpp: -------------------------------------------------------------------------------- 1 | #include "Background.h" 2 | #include "../XChart.h" 3 | 4 | void xg::guide::Background::Render(XChart &chart, shape::Group *container, canvas::CanvasContext &context, const std::vector &dangerRects) { 5 | const std::string &xField = chart.GetXScaleField(); 6 | std::vector yFields = chart.getYScaleFields(); 7 | const std::string yField = yFields[0]; 8 | 9 | util::Point leftBottom = this->GetPosition(chart, json::Get(this->config_, "leftBottom"), xField, yField); 10 | util::Point rightTop = this->GetPosition(chart, json::Get(this->config_, "rightTop"), xField, yField); 11 | 12 | std::string color = json::Get(this->config_, "color"); 13 | util::Point p = {leftBottom.x, rightTop.y}; 14 | 15 | auto rect = xg::make_unique(p, util::Size{fabs(rightTop.x - leftBottom.x), fabs(rightTop.y - leftBottom.y)}); 16 | rect->SetFillColor(color); 17 | container->AddElement(std::move(rect)); 18 | } 19 | -------------------------------------------------------------------------------- /core/graphics/guide/Background.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef XG_GRAPHICS_GUIDE_BACKGROUND_H 3 | #define XG_GRAPHICS_GUIDE_BACKGROUND_H 4 | 5 | #include "GuideBase.h" 6 | 7 | namespace xg { 8 | namespace guide { 9 | 10 | class Background : public GuideBase { 11 | public: 12 | Background(nlohmann::json config = {}) : GuideBase("background", MergeDefaultCfg(config)) {} 13 | 14 | void Render(XChart &chart, shape::Group *container, canvas::CanvasContext &context, const std::vector &dangerRects) override; 15 | util::BBox GetBBox() override { return bbox_; } 16 | 17 | protected: 18 | static nlohmann::json MergeDefaultCfg(const nlohmann::json &cfg) { 19 | nlohmann::json defaultCfg = {{"color", "#1CAA3DB2"}}; 20 | if(cfg.is_object()) { 21 | defaultCfg.merge_patch(cfg); 22 | } 23 | return defaultCfg; 24 | } 25 | }; 26 | 27 | } // namespace guide 28 | } // namespace xg 29 | 30 | #endif // XG_GRAPHICS_GUIDE_BACKGROUND_H 31 | -------------------------------------------------------------------------------- /core/graphics/guide/GuideBase.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_GUIDE_BASE_H 2 | #define XG_GRAPHICS_GUIDE_BASE_H 3 | 4 | #include "../canvas/CanvasContext.h" 5 | #include "../shape/Group.h" 6 | #include "../util/BBox.h" 7 | #include "../util/Point.h" 8 | #include "../../nlohmann/json.hpp" 9 | 10 | namespace xg { 11 | class XChart; 12 | 13 | namespace guide { 14 | 15 | class GuideBase { 16 | public: 17 | GuideBase(std::string type, nlohmann::json config = {}) : type_(type), config_(config) {} 18 | virtual ~GuideBase() {} 19 | virtual void 20 | Render(XChart &chart, shape::Group *container, canvas::CanvasContext &context, const std::vector &dangerRects) = 0; 21 | 22 | virtual util::BBox GetBBox() { return bbox_; } 23 | 24 | std::string GetType() const noexcept { return this->type_; } 25 | 26 | //是否绘制在最顶层 27 | bool isTop() const noexcept { 28 | if (config_.contains("top")) { 29 | return config_["top"].get(); 30 | } 31 | return true; 32 | } 33 | 34 | virtual util::Point GetPosition(XChart &chart, const nlohmann::json &position, const std::string &xField, const std::string &yField); 35 | 36 | protected: 37 | std::string type_ = ""; 38 | nlohmann::json config_; 39 | util::BBox bbox_; 40 | }; 41 | } // namespace guide 42 | } // namespace xg 43 | 44 | #endif // XG_GRAPHICS_GUIDE_BASE_H 45 | -------------------------------------------------------------------------------- /core/graphics/guide/Image.h: -------------------------------------------------------------------------------- 1 | // 2 | // Image.hpp 3 | // F2 4 | // 5 | // Created by weiqing.twq on 2021/9/1. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #ifndef XG_GRAPHICS_GUIDE_IMAGE_H 10 | #define XG_GRAPHICS_GUIDE_IMAGE_H 11 | 12 | #include "GuideBase.h" 13 | 14 | namespace xg { 15 | namespace guide { 16 | 17 | class Image : public GuideBase { 18 | public: 19 | Image(const nlohmann::json &config = {}) : GuideBase("image", MergeDefaultCfg(config)) {} 20 | 21 | void Render(XChart &chart, shape::Group *container, canvas::CanvasContext &context, const std::vector &dangerRects) override; 22 | 23 | util::BBox GetBBox() override { return bbox_; } 24 | 25 | protected: 26 | static nlohmann::json MergeDefaultCfg(const nlohmann::json &config) { 27 | nlohmann::json defaultCfg = { 28 | {"margin", {0, 0}}// margin: left & top 29 | }; 30 | if(config.is_object()) { 31 | defaultCfg.merge_patch(config); 32 | } 33 | return defaultCfg; 34 | } 35 | }; 36 | 37 | } // namespace guide 38 | } // namespace xg 39 | 40 | 41 | 42 | #endif /* Image_h */ 43 | -------------------------------------------------------------------------------- /core/graphics/guide/Line.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_GUIDE_LINE_H 2 | #define XG_GRAPHICS_GUIDE_LINE_H 3 | 4 | #include "GuideBase.h" 5 | 6 | namespace xg { 7 | namespace guide { 8 | 9 | class Line : public GuideBase { 10 | public: 11 | Line(nlohmann::json cfg = {}) : GuideBase("line", MergeDefaultCfg(cfg)) {} 12 | 13 | void Render(XChart &chart, shape::Group *container, canvas::CanvasContext &context, const std::vector &dangerRects) override; 14 | 15 | util::BBox GetBBox() override { return bbox_; } 16 | 17 | protected: 18 | static nlohmann::json MergeDefaultCfg(const nlohmann::json &config) { 19 | nlohmann::json defaultCfg = { 20 | {"color", "#1890FF"}, {"lineWidth", 1.f}, {"orientation", "horizontal"} // [horizontal, vertical, crossed] 21 | }; 22 | if(config.is_object()) { 23 | defaultCfg.merge_patch(config); 24 | } 25 | return defaultCfg; 26 | } 27 | }; 28 | } // namespace guide 29 | } // namespace xg 30 | 31 | #endif // XG_GRAPHICS_GUIDE_LINE_H 32 | -------------------------------------------------------------------------------- /core/graphics/guide/Point.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Circle.cpp 3 | // F2 4 | // 5 | // Created by weiqing.twq on 2021/9/9. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #include "Point.h" 10 | #include "../XChart.h" 11 | #include "../global.h" 12 | #include "../shape/Circle.h" 13 | 14 | using namespace xg; 15 | 16 | void guide::Point::Render(XChart &chart, shape::Group *container, canvas::CanvasContext &context, const std::vector &dangerRects) { 17 | const std::string &xField = chart.GetXScaleField(); 18 | std::vector yFields = chart.getYScaleFields(); 19 | const std::string &yField = yFields[0]; 20 | 21 | util::Point position = this->GetPosition(chart, json::GetArray(this->config_, "position"), xField, yField); 22 | double offsetX = json::GetNumber(config_, "offsetX"); 23 | double offsetY = json::GetNumber(config_, "offsetY"); 24 | double size = json::GetNumber(config_, "size") * context.GetDevicePixelRatio(); 25 | const std::string &color = json::GetString(config_, "fill"); 26 | 27 | position.x = position.x + offsetX * context.GetDevicePixelRatio(); 28 | position.y = position.y + offsetY * context.GetDevicePixelRatio(); 29 | 30 | auto circle = xg::make_unique(position, size, color); 31 | bbox_ = circle->GetBBox(context); 32 | container->AddElement(std::move(circle)); 33 | } 34 | -------------------------------------------------------------------------------- /core/graphics/guide/Point.h: -------------------------------------------------------------------------------- 1 | // 2 | // Circle.hpp 3 | // F2 4 | // 5 | // Created by weiqing.twq on 2021/9/9. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #ifndef XG_GRAPHICS_GUIDE_POINT_H 10 | #define XG_GRAPHICS_GUIDE_POINT_H 11 | 12 | #include "GuideBase.h" 13 | 14 | namespace xg { 15 | namespace guide { 16 | 17 | class Point : public GuideBase { 18 | public: 19 | Point(const nlohmann::json &config = {}) : GuideBase("point", MergeDefaultCfg(config)) {} 20 | 21 | void Render(XChart &chart, shape::Group *container, canvas::CanvasContext &context, const std::vector &dangerRects) override; 22 | 23 | util::BBox GetBBox() override { return bbox_; } 24 | 25 | protected: 26 | static nlohmann::json MergeDefaultCfg(const nlohmann::json &config) { 27 | nlohmann::json defaultCfg = { 28 | {"size", 3}, {"shape", "circle"}, {"fill", GLOBAL_COLORS[0]}, {"offsetX", 0}, {"offsetY", 0}, 29 | }; 30 | if(config.is_object()) { 31 | defaultCfg.merge_patch(config); 32 | } 33 | return defaultCfg; 34 | } 35 | }; 36 | } // namespace guide 37 | } 38 | 39 | #endif /* XG_GRAPHICS_GUIDE_POINT_H */ 40 | -------------------------------------------------------------------------------- /core/graphics/guide/Text.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_GUIDE_TEXT_H 2 | #define XG_GRAPHICS_GUIDE_TEXT_H 3 | 4 | #include "GuideBase.h" 5 | 6 | namespace xg { 7 | namespace guide { 8 | class Text : public GuideBase { 9 | public: 10 | Text(nlohmann::json config = {}) : GuideBase("text", MergeDefaultCfg(config)) {} 11 | 12 | void Render(XChart &chart, shape::Group *container, canvas::CanvasContext &context, const std::vector &dangerRects) override; 13 | 14 | util::BBox GetBBox() override { return bbox_; } 15 | 16 | protected: 17 | static nlohmann::json MergeDefaultCfg(const nlohmann::json &config) { 18 | nlohmann::json defaultCfg = { 19 | {"textColor", "#808080"}, {"textSize", DEFAULT_FONTSIZE}, {"content", ""}, {"margin", {0, 0}}, // margin: left & top 20 | {"textAlign", "start"}, {"textBaseline", "bottom"}, 21 | }; 22 | if(config.is_object()) { 23 | defaultCfg.merge_patch(config); 24 | } 25 | return defaultCfg; 26 | } 27 | }; 28 | } // namespace guide 29 | } // namespace xg 30 | 31 | #endif // XG_GRAPHICS_GUIDE_TEXT_H 32 | -------------------------------------------------------------------------------- /core/graphics/interaction/InteractionBase.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_EVENT_INTERACTION_BASE_H 2 | #define XG_GRAPHICS_EVENT_INTERACTION_BASE_H 3 | 4 | namespace xg { 5 | class XChart; 6 | namespace interaction { 7 | class InteractionBase { 8 | public: 9 | InteractionBase(XChart *chart) : chart_(chart) {} 10 | 11 | virtual ~InteractionBase() { chart_ = nullptr; } 12 | 13 | protected: 14 | XChart *chart_ = nullptr; 15 | }; 16 | } // namespace interaction 17 | } // namespace xg 18 | 19 | #endif // XG_GRAPHICS_EVENT_INTERACTION_BASE_H 20 | -------------------------------------------------------------------------------- /core/graphics/interaction/Pan.cpp: -------------------------------------------------------------------------------- 1 | #include "Pan.h" 2 | #include "../XChart.h" 3 | 4 | using namespace xg; 5 | 6 | interaction::Pan::Pan(XChart *chart) : InteractionBase(chart) { 7 | this->chart_->eventController_->AddCallback("panstart", XG_MEMBER_CALLBACK_1(interaction::Pan::OnPanStart)); 8 | this->chart_->eventController_->AddCallback("pan", XG_MEMBER_CALLBACK_1(interaction::Pan::OnPan)); 9 | this->chart_->eventController_->AddCallback("panend", XG_MEMBER_CALLBACK_1(interaction::Pan::onPanEnd)); 10 | } 11 | 12 | bool interaction::Pan::OnPanStart(event::Event &event) { 13 | this->chart_->interactionContext_->Start(); 14 | return false; 15 | } 16 | 17 | bool interaction::Pan::OnPan(event::Event &event) { 18 | // this->chart_->GetLogTracer()->trace("onPan type: %s direction: %s", event.eventType.data(), event.direction.data()); 19 | if(event.direction == "none" || event.direction == "up" || event.direction == "down") { 20 | return false; 21 | } 22 | 23 | // double coordWidth = this->chart_->coord_->GetWidth(); 24 | // double ratio = event.deltaX / coordWidth; 25 | return this->chart_->interactionContext_->DoMove(event.deltaX, event.deltaY); 26 | } 27 | 28 | bool interaction::Pan::onPanEnd(event::Event &event) { 29 | this->chart_->interactionContext_->UpdateTicks(); 30 | return false; 31 | } 32 | -------------------------------------------------------------------------------- /core/graphics/interaction/Pan.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_EVENT_INTERACTION_PAN_H 2 | #define XG_GRAPHICS_EVENT_INTERACTION_PAN_H 3 | 4 | #include "InteractionBase.h" 5 | #include "../event/EventController.h" 6 | 7 | namespace xg { 8 | class XChart; 9 | namespace interaction { 10 | 11 | class Pan : public InteractionBase { 12 | public: 13 | Pan(XChart *chart); 14 | 15 | bool OnPanStart(event::Event &event); 16 | 17 | bool OnPan(event::Event &event); 18 | 19 | bool onPanEnd(event::Event &event); 20 | }; 21 | } // namespace interaction 22 | } // namespace xg 23 | 24 | #endif // XG_GRAPHICS_EVENT_INTERACTION_PAN_H 25 | -------------------------------------------------------------------------------- /core/graphics/interaction/Pinch.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_EVENT_INTERACTION_PINCH_H 2 | #define XG_GRAPHICS_EVENT_INTERACTION_PINCH_H 3 | 4 | #include "InteractionBase.h" 5 | #include "../event/EventController.h" 6 | 7 | namespace xg { 8 | class XChart; 9 | namespace interaction { 10 | 11 | class Pinch : public InteractionBase { 12 | public: 13 | Pinch(XChart *chart); 14 | 15 | bool OnPinchStart(event::Event &event); 16 | 17 | bool OnPinch(event::Event &event); 18 | 19 | bool onPinchEnd(event::Event &event); 20 | }; 21 | } // namespace interaction 22 | } // namespace xg 23 | 24 | #endif // XG_GRAPHICS_EVENT_INTERACTION_PINCH_H 25 | -------------------------------------------------------------------------------- /core/graphics/scale/Identity.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_SCALE_IDENTITY_H 2 | #define XG_GRAPHICS_SCALE_IDENTITY_H 3 | 4 | #include "Scale.h" 5 | 6 | namespace xg { 7 | namespace scale { 8 | /** 9 | * 常量度量 10 | */ 11 | class Identity : public AbstractScale { 12 | public: 13 | Identity(const std::string &_field, const nlohmann::json &_values) : AbstractScale(_field, _values, {}) { 14 | this->ticks = this->CalculateTicks(); 15 | } 16 | 17 | ScaleType GetType() const noexcept override { return ScaleType::Identity; } 18 | 19 | void Change(const nlohmann::json &cfg = {}) override {} 20 | 21 | double Scale(const nlohmann::json &key) override { 22 | if(values.size() > 0 && key.is_number() && values[0] == key) { 23 | return key; 24 | } 25 | return this->rangeMin; 26 | } 27 | 28 | nlohmann::json Invert(double key) override { 29 | if(values.size() > 0) { 30 | return values[0]; 31 | } 32 | nlohmann::json ret; 33 | return ret; 34 | } 35 | 36 | protected: 37 | nlohmann::json CalculateTicks() override { return values; } 38 | }; 39 | } // namespace scale 40 | } // namespace xg 41 | 42 | #endif // XG_GRAPHICS_SCALE_IDENTITY_H 43 | -------------------------------------------------------------------------------- /core/graphics/scale/TimeCategory.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_SCALE_TIME_CAT_H 2 | #define XG_GRAPHICS_SCALE_TIME_CAT_H 3 | 4 | #include 5 | #include "../scale/Category.h" 6 | 7 | namespace xg { 8 | namespace scale { 9 | class TimeCategory : public Category { 10 | public: 11 | TimeCategory(const std::string &_field, 12 | const nlohmann::json &_values, 13 | const nlohmann::json &config, 14 | std::string mask = "HH::mm") 15 | : Category(_field, _values, config), mask(mask) {} 16 | 17 | ScaleType GetType() const noexcept override { return ScaleType::TimeCat; } 18 | 19 | std::string GetTickText(const nlohmann::json &item, XChart *chart) override { 20 | if(item.is_string()) { 21 | return item.get(); 22 | } else if(item.is_number()) { 23 | struct tm *p; 24 | time_t t; 25 | t = item.get(); 26 | p = gmtime(&t); 27 | char s[100]; 28 | strftime(s, 100, "%H:%M", p); 29 | return std::string(s); 30 | } else { 31 | return ""; 32 | } 33 | } 34 | 35 | protected: 36 | std::string mask; 37 | }; 38 | } // namespace scale 39 | } // namespace xg 40 | 41 | #endif // XG_GRAPHICS_SCALE_TIME_CAT_H 42 | -------------------------------------------------------------------------------- /core/graphics/scale/continuous/Linear.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Linear.cpp 3 | // F2 4 | // 5 | // Created by weiqing.twq on 2022/6/1. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #include "Linear.h" 10 | #include "../../XChart.h" 11 | 12 | using namespace xg::scale; 13 | 14 | std::string Linear::GetTickText(const nlohmann::json &item, XChart *chart) { 15 | if(!this->tickCallbackId.empty() && chart) { 16 | nlohmann::json content{{"content", item.dump()}}; 17 | auto rst = xg::json::ParseString((chart->InvokeFunction(this->tickCallbackId, content.dump()))); 18 | if(rst.is_object() && rst.contains("content")) { 19 | return rst["content"]; 20 | } 21 | } 22 | 23 | // 处理 TickText 数值精度 24 | if(item.is_string()) { 25 | return item.get(); 26 | } else if(item.is_number_integer()) { 27 | return std::to_string(item.get()); 28 | } else if(item.is_number_float()) { 29 | float val = item.get(); 30 | if(fabs(val) < XG_EPS) { 31 | return "0"; 32 | } 33 | std::stringstream ss; 34 | ss << std::fixed << std::setprecision(precision) << val; 35 | return ss.str(); 36 | } else { 37 | return ""; // TODO get Tick text from callback 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /core/graphics/shape/Area.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_SHAPE_AREA_H 2 | #define XG_GRAPHICS_SHAPE_AREA_H 3 | 4 | #include "Shape.h" 5 | 6 | namespace xg { 7 | namespace shape { 8 | 9 | class Area : public Shape { 10 | public: 11 | Area(const vector &topPoints, const vector &bottomPoints, const bool smooth); 12 | 13 | BBox CalculateBox(canvas::CanvasContext &context) const override; 14 | 15 | protected: 16 | void CreatePath(canvas::CanvasContext &context) const override; 17 | 18 | public: 19 | vector topPoints_; 20 | vector bottomPoints_; 21 | vector mergePoints_; 22 | bool smooth_ = false; 23 | }; 24 | 25 | } // namespace shape 26 | } // namespace xg 27 | 28 | #endif /* XG_GRAPHICS_SHAPE_AREA_H */ 29 | -------------------------------------------------------------------------------- /core/graphics/shape/Circle.cpp: -------------------------------------------------------------------------------- 1 | #include "Circle.h" 2 | 3 | void xg::shape::Circle::CreatePath(canvas::CanvasContext &context) const { 4 | context.BeginPath(); 5 | context.Arc(point_.x, point_.y, radius_, 0.0, 2 * M_PI); 6 | context.ClosePath(); 7 | } 8 | 9 | BBox xg::shape::Circle::CalculateBox(canvas::CanvasContext &context) const { 10 | BBox bbox; 11 | bbox.minX = point_.x - radius_; 12 | bbox.maxX = point_.x + radius_; 13 | bbox.minY = point_.y - radius_; 14 | bbox.maxY = point_.y + radius_; 15 | bbox.x = point_.x; 16 | bbox.y = point_.y; 17 | return bbox; 18 | } 19 | -------------------------------------------------------------------------------- /core/graphics/shape/Circle.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_SHAPE_CIRCLE_H 2 | #define XG_GRAPHICS_SHAPE_CIRCLE_H 3 | 4 | #include "Shape.h" 5 | 6 | namespace xg { 7 | namespace shape { 8 | 9 | class Circle : public Shape { 10 | public: 11 | Circle(const util::Point ¢er, const float radius) : radius_(radius) { 12 | type_ = "circle"; 13 | point_ = center; 14 | } 15 | 16 | Circle(const util::Point ¢er, const float radius, const std::string &fill) : radius_(radius) { 17 | type_ = "circle"; 18 | point_ = center; 19 | 20 | SetFillColor(fill); 21 | } 22 | 23 | BBox CalculateBox(canvas::CanvasContext &context) const override; 24 | 25 | protected: 26 | void CreatePath(canvas::CanvasContext &context) const override; 27 | 28 | public: 29 | float radius_; 30 | }; 31 | 32 | } // namespace shape 33 | } // namespace xg 34 | 35 | #endif /* XG_GRAPHICS_SHAPE_CIRCLE_H */ 36 | -------------------------------------------------------------------------------- /core/graphics/shape/Line.cpp: -------------------------------------------------------------------------------- 1 | #include "Line.h" 2 | 3 | xg::shape::Line::Line(const Point &pt1, const Point &pt2) { 4 | p1_ = pt1; 5 | p2_ = pt2; 6 | type_ = "line"; 7 | } 8 | 9 | xg::shape::Line::Line(const Point &pt1, const Point &pt2, const float lineWidth, const string &strokeColor) : Shape() { 10 | p1_ = pt1; 11 | p2_ = pt2; 12 | lineWidth_ = lineWidth; 13 | strokeStyle_ = canvas::CanvasFillStrokeStyle(strokeColor); 14 | type_ = "line"; 15 | } 16 | 17 | void xg::shape::Line::CreatePath(canvas::CanvasContext &context) const { 18 | context.BeginPath(); 19 | context.MoveTo(p1_.x + this->point_.x, p1_.y + this->point_.y); 20 | context.LineTo(p2_.x + this->point_.x, p2_.y + this->point_.y); 21 | } 22 | 23 | BBox xg::shape::Line::CalculateBox(canvas::CanvasContext &context) const { 24 | return BBoxUtil::GetBBoxFromLine(p1_.x + this->point_.x, p1_.y + this->point_.y, p2_.x + this->point_.x, 25 | p2_.y + this->point_.y, lineWidth_); 26 | } 27 | -------------------------------------------------------------------------------- /core/graphics/shape/Line.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_SHAPE_LINE_H 2 | #define XG_GRAPHICS_SHAPE_LINE_H 3 | 4 | #include "Shape.h" 5 | 6 | namespace xg { 7 | namespace shape { 8 | 9 | class Line : public Shape { 10 | public: 11 | Line(const util::Point &, const util::Point &); 12 | Line(const util::Point &, const util::Point &, const float lineWidth, const string &strokeColor); 13 | 14 | BBox CalculateBox(canvas::CanvasContext &context) const override; 15 | 16 | protected: 17 | void CreatePath(canvas::CanvasContext &context) const override; 18 | 19 | public: 20 | util::Point p1_, p2_; 21 | }; 22 | 23 | } // namespace shape 24 | } // namespace xg 25 | 26 | #endif /* XG_GRAPHICS_SHAPE_LINE_H */ 27 | -------------------------------------------------------------------------------- /core/graphics/shape/Marker.cpp: -------------------------------------------------------------------------------- 1 | #include "Marker.h" 2 | 3 | void xg::shape::Marker::CreatePath(canvas::CanvasContext &context) const { 4 | context.BeginPath(); 5 | if(symbol_ == "circle") { 6 | context.Arc(point_.x, point_.y, radius_, 0.0, 2 * M_PI, false); 7 | } 8 | if(symbol_ == "square") { 9 | context.MoveTo(point_.x - radius_, point_.y - radius_); 10 | context.LineTo(point_.x + radius_, point_.y - radius_); 11 | context.LineTo(point_.x + radius_, point_.y + radius_); 12 | context.LineTo(point_.x - radius_, point_.y + radius_); 13 | } 14 | context.ClosePath(); 15 | } 16 | 17 | BBox xg::shape::Marker::CalculateBox(canvas::CanvasContext &context) const { 18 | BBox bbox; 19 | bbox.minX = point_.x - radius_; 20 | bbox.maxX = point_.x + radius_; 21 | bbox.minY = point_.y - radius_; 22 | bbox.maxY = point_.y + radius_; 23 | bbox.x = point_.x; 24 | bbox.y = point_.y; 25 | return bbox; 26 | } 27 | -------------------------------------------------------------------------------- /core/graphics/shape/Marker.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_SHAPE_MARKER_H 2 | #define XG_GRAPHICS_SHAPE_MARKER_H 3 | 4 | #include "Shape.h" 5 | 6 | namespace xg { 7 | namespace shape { 8 | 9 | class Marker : public Shape { 10 | public: 11 | Marker(const util::Point ¢er, const float radius, const std::string &fill, const std::string &symbol) 12 | : radius_(radius), symbol_(symbol) { 13 | type_ = "marker"; 14 | point_ = center; 15 | SetFillColor(fill); 16 | } 17 | 18 | BBox CalculateBox(canvas::CanvasContext &context) const override; 19 | 20 | protected: 21 | void CreatePath(canvas::CanvasContext &context) const override; 22 | 23 | public: 24 | float radius_; 25 | std::string symbol_ = "circle"; 26 | }; 27 | 28 | } // namespace shape 29 | } // namespace xg 30 | 31 | #endif /* XG_GRAPHICS_SHAPE_MARKER_H */ 32 | -------------------------------------------------------------------------------- /core/graphics/shape/Polyline.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_SHAPE_POLYLINE_H 2 | #define XG_GRAPHICS_SHAPE_POLYLINE_H 3 | 4 | #include "Shape.h" 5 | 6 | using namespace xg::util; 7 | 8 | namespace xg { 9 | namespace shape { 10 | 11 | class Polyline : public Shape { 12 | public: 13 | Polyline(const float lineWidth, const vector &, const bool smooth); 14 | 15 | Polyline(const float lineWidth, const vector &, const std::string &strokeColor, const std::string &fillColor, const bool smooth); 16 | 17 | BBox CalculateBox(canvas::CanvasContext &context) const override; 18 | 19 | void SetDashLine(const std::vector ¶ms) { this->dash_ = params; } 20 | 21 | protected: 22 | void CreatePath(canvas::CanvasContext &context) const override; 23 | 24 | private: 25 | vector points_; 26 | bool smooth_ = false; 27 | 28 | std::vector dash_; 29 | }; 30 | 31 | } // namespace shape 32 | } // namespace xg 33 | 34 | #endif /* XG_GRAPHICS_SHAPE_POLYLINE_H */ 35 | -------------------------------------------------------------------------------- /core/graphics/shape/Shape.cpp: -------------------------------------------------------------------------------- 1 | #include "Shape.h" 2 | 3 | xg::shape::Shape::Shape() : Element() { isShape_ = true; } 4 | 5 | void xg::shape::Shape::DrawInner(canvas::CanvasContext &context) const { 6 | float originOpacity = context.GlobalAlpha(); 7 | //coregraphics context path和fill必须配对 path和stroke必须配对 8 | //在既有fill又有stroke的case 会浪费一点性能 9 | 10 | // fill case 11 | if(HasFill()) { 12 | CreatePath(context); 13 | if(!std::isnan(fillOpacity_)) { 14 | context.SetGlobalAlpha(fillOpacity_); 15 | context.Fill(); 16 | context.SetGlobalAlpha(originOpacity); 17 | } else { 18 | context.Fill(); 19 | } 20 | } 21 | 22 | // stroke case 23 | if(HasStroke() && lineWidth_ > 0) { 24 | CreatePath(context); 25 | if(!std::isnan(strokeOpacity_)) { 26 | context.SetGlobalAlpha(strokeOpacity_); 27 | context.Stroke(); 28 | context.SetGlobalAlpha(originOpacity); 29 | } else { 30 | context.Stroke(); 31 | } 32 | } 33 | } 34 | 35 | const BBox &xg::shape::Shape::GetBBox(canvas::CanvasContext &context) { 36 | if(std::isnan(bbox_.minX)) { 37 | bbox_ = CalculateBox(context); 38 | } 39 | return bbox_; 40 | } 41 | -------------------------------------------------------------------------------- /core/graphics/shape/Shape.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_SHAPE_SHAPE_H 2 | #define XG_GRAPHICS_SHAPE_SHAPE_H 3 | 4 | #include "Element.h" 5 | 6 | namespace xg { 7 | namespace shape { 8 | class Group; 9 | class Shape : public Element { 10 | friend Group; 11 | 12 | public: 13 | Shape(); 14 | 15 | virtual ~Shape() override {} 16 | 17 | /// 获取包围盒,同一个shape只会一算一次 18 | /// @param context 上下文 19 | const BBox &GetBBox(canvas::CanvasContext &context) override; 20 | 21 | /// 包围盒计算,每次都会计算 22 | virtual BBox CalculateBox(canvas::CanvasContext &context) const override { return {0, 0, 0, 0, 0, 0}; } 23 | 24 | // 各元素独立实现,用于更新属性值 25 | virtual void UpdateAttribute(std::string attrName, double val) {} 26 | virtual void UpdateAttribute(std::string attrName, const std::string &val) {} 27 | 28 | protected: 29 | virtual void DrawInner(canvas::CanvasContext &context) const override; 30 | 31 | /// 调用canvas生成绘制指令 32 | /// @param context canvas的context 33 | virtual void CreatePath(canvas::CanvasContext &context) const {}; 34 | }; 35 | 36 | } // namespace shape 37 | } // namespace xg 38 | 39 | #endif /* XG_GRAPHICS_SHAPE_SHAPE_H */ 40 | -------------------------------------------------------------------------------- /core/graphics/util/Color.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_GRAPHICS_UTIL_COLOR_H 2 | #define XG_GRAPHICS_UTIL_COLOR_H 3 | 4 | #include 5 | #include 6 | #include "../../nlohmann/json.hpp" 7 | #include "../canvas/CanvasFillStrokeStyle.h" 8 | #include "../global.h" 9 | 10 | namespace xg { 11 | namespace util { 12 | 13 | canvas::CanvasFillStrokeStyle ColorParser(const nlohmann::json &color); 14 | canvas::CanvasFillStrokeStyle ColorParser(const nlohmann::json &data, const std::string &key); 15 | float OpacityParserString(const std::string &color); 16 | float OpacityParser(const nlohmann::json &color); 17 | float OpacityParser(const nlohmann::json &data, const std::string &key); 18 | 19 | } // namespace util 20 | } // namespace xg 21 | 22 | #endif // XG_GRAPHICS_UTIL_COLOR_H 23 | -------------------------------------------------------------------------------- /core/graphics/util/json_data.h: -------------------------------------------------------------------------------- 1 | // 2 | // json_data.h 3 | // F2 4 | // 5 | // Created by weiqing.twq on 2022/6/1. 6 | // 7 | 8 | #ifndef XG_GRAPHICS_UTIL_JSON_DATA 9 | #define XG_GRAPHICS_UTIL_JSON_DATA 10 | 11 | #include 12 | #include 13 | #include "Point.h" 14 | 15 | namespace xg { 16 | namespace util { 17 | struct XData final { 18 | nlohmann::json::const_pointer data; 19 | double _x = NAN, _y = NAN; 20 | std::vector _y0; 21 | nlohmann::json _style; 22 | std::string _color, _shape, _adjust; 23 | double _size = NAN; 24 | 25 | //for interval and candle 26 | nlohmann::json _points, _tag, _rect, _line, _state; 27 | bool _beforeMapped = false; 28 | 29 | //for adjust 30 | std::vector adjust; 31 | 32 | //for dodge 33 | //index 0 for xfiled, index 1 for yfield 34 | std::vector dodge; 35 | }; 36 | 37 | using XDataArray = std::vector; 38 | using XDataGroup = std::vector>; 39 | } 40 | } 41 | 42 | 43 | #endif /* XG_GRAPHICS_UTIL_JSON_DATA */ 44 | -------------------------------------------------------------------------------- /core/ios/BridgeRailingIOS.h: -------------------------------------------------------------------------------- 1 | // 2 | // F2CommonIOSPlatform.hpp 3 | // F2 4 | // 5 | // Created by weiqing.twq on 2022/6/1. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #if defined(__APPLE__) 10 | 11 | #ifndef XG_BRIDGE_RAILINGIOS 12 | #define XG_BRIDGE_RAILINGIOS 13 | 14 | #include "AbstractBridgeRailing.h" 15 | 16 | namespace xg { 17 | namespace bridge { 18 | 19 | class BridgeRailingIOS final : public AbstractBridgeRailing { 20 | public: 21 | ///传入view,在这里是UIView的指针 22 | BridgeRailingIOS(void *view); 23 | ~BridgeRailingIOS(); 24 | 25 | void PlayAnimation(const std::string ¶ms) override; 26 | 27 | void Swap() override; 28 | 29 | long GetTimezoneOffset(const std::string &timezoneName) override; 30 | 31 | std::string FormatTime(const std::string &value, const std::string &timezoneName, const std::string ×tampFormatter) override; 32 | 33 | inline void SetCanvasContext(void *context) override { context_ = context; } 34 | inline void *GetCanvasContext() override { return context_; } 35 | private: 36 | void *view_ = nullptr; 37 | void *context_ = nullptr; 38 | void *proxy_ = nullptr; 39 | }; 40 | } 41 | } 42 | 43 | #endif /* XG_BRIDGE_RAILINGIOS */ 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /core/ios/F2Logger.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_F2_NATIVE_F2LOGGER_H 2 | #define XG_F2_NATIVE_F2LOGGER_H 3 | 4 | #include 5 | #include 6 | 7 | namespace xg { 8 | namespace ios { 9 | 10 | void InnerLog(int level, const std::string &traceId, const char *fmt, ...); 11 | 12 | } 13 | } 14 | 15 | #define F2_LOG_INFO 1 16 | #define F2_LOG_WARN 2 17 | #define F2_LOG_ERROR 3 18 | 19 | #define F2_LOG_I(traceId, ...) ((void)xg::ios::InnerLog(F2_LOG_INFO, traceId, __VA_ARGS__)) 20 | #define F2_LOG_W(traceId, ...) ((void)xg::ios::InnerLog(F2_LOG_WARN, traceId, __VA_ARGS__)) 21 | #define F2_LOG_E(traceId, ...) ((void)xg::ios::InnerLog(F2_LOG_ERROR, traceId, __VA_ARGS__)) 22 | 23 | #endif /* XG_F2_NATIVE_F2LOGGER_H */ 24 | -------------------------------------------------------------------------------- /core/ios/F2Logger.mm: -------------------------------------------------------------------------------- 1 | #include "F2Logger.h" 2 | #include "../utils/xtime.h" 3 | #if defined(PRODUCT_WALLET) 4 | #include 5 | #endif 6 | 7 | namespace xg { 8 | namespace ios { 9 | 10 | void InnerLog(int level, const std::string &traceId, const char *fmt, ...) { 11 | std::string _tag = "F2Native|" + traceId; 12 | 13 | char msg[2048] = {0}; 14 | va_list args; 15 | va_start(args, fmt); 16 | vsnprintf(msg, 2048, fmt, args); 17 | va_end(args); 18 | 19 | #if defined(PRODUCT_WALLET) 20 | 21 | #if defined(DEBUG) 22 | printf("%s %.0lf %s\n", _tag.c_str(), CFAbsoluteTimeGetCurrent() * 1000, msg); 23 | #else 24 | NSString *tagStr = [NSString stringWithUTF8String:_tag.c_str()]; 25 | NSString *msgStr = [NSString stringWithUTF8String:msg]; 26 | APLogInfo(tagStr, @"%@", msgStr); 27 | #endif 28 | 29 | #else 30 | printf("%s %.0lld %s\n", _tag.c_str(), xg::CurrentTimestampAtMM(), msg); 31 | #endif 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /core/utils/StringUtil.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #ifndef XG_UTILS_STRING_H 7 | #define XG_UTILS_STRING_H 8 | 9 | class StringUtil final { 10 | public: 11 | static void Split(const std::string &s, std::vector &sv, const char delim = ' ') { 12 | sv.clear(); 13 | std::istringstream iss(s); 14 | std::string temp; 15 | 16 | while(std::getline(iss, temp, delim)) { 17 | sv.emplace_back(std::move(temp)); 18 | } 19 | return; 20 | } 21 | 22 | static std::vector ParseFields(const std::string &field) { 23 | if(field.find('*') != field.npos) { 24 | std::vector v; 25 | StringUtil::Split(field, v, '*'); 26 | return v; 27 | } else { 28 | return {field}; 29 | } 30 | } 31 | }; 32 | 33 | #endif /* XG_UTILS_STRING_H */ 34 | -------------------------------------------------------------------------------- /core/utils/Tracer.cpp: -------------------------------------------------------------------------------- 1 | #include "Tracer.h" 2 | #include 3 | 4 | #if defined(__APPLE__) 5 | #include 6 | #endif 7 | 8 | void utils::Tracer::trace(const char *fmt, ...) { 9 | char buffer[4096] = {0}; 10 | 11 | va_list args; 12 | va_start(args, fmt); 13 | vsnprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer) - 1, fmt, args); 14 | va_end(args); 15 | 16 | #ifdef ANDROID 17 | F2_LOG_I(this->name_.data(), "%s", buffer); 18 | #elif defined(TARGET_OS_IPHONE) 19 | F2_LOG_I(this->name_.data(), "%s", buffer); 20 | #else 21 | printf("%s %s\n", this->name_.data(), buffer); 22 | #endif 23 | } 24 | -------------------------------------------------------------------------------- /core/utils/Tracer.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if defined(ANDROID) 4 | #include "android/F2NativeJNI.h" 5 | #endif 6 | 7 | #if defined(__APPLE__) 8 | #include "../ios/F2Logger.h" 9 | #endif 10 | 11 | #ifndef X_CHART_UTILS_TRACER_H 12 | #define X_CHART_UTILS_TRACER_H 13 | namespace utils { 14 | class Tracer { 15 | public: 16 | Tracer(const std::string &name) : name_(name) {} 17 | 18 | void trace(const char *fmt, ...); 19 | 20 | private: 21 | std::string name_; 22 | }; 23 | } // namespace utils 24 | 25 | #endif // X_CHART_UTILS_TRACER_H 26 | -------------------------------------------------------------------------------- /core/utils/common.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // common.cpp 3 | // Pods 4 | // 5 | // Created by weiqing.twq on 2022/6/1. 6 | // 7 | 8 | #include "common.h" 9 | 10 | bool xg::IsZero(double val) noexcept { return (fabs(val) < XG_EPS); } 11 | bool xg::IsEqualDeviation (double v1, double v2, double deviation) noexcept { return fabs(v1 - v2) < deviation; } 12 | bool xg::IsEqual(double v1, double v2) noexcept { return IsEqualDeviation(v1, v2, XG_EPS); } 13 | -------------------------------------------------------------------------------- /core/utils/common.h: -------------------------------------------------------------------------------- 1 | #ifndef XG_UTIL_COMMON 2 | #define XG_UTIL_COMMON 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #ifdef DEBUG 11 | #define XG_ASSERT assert 12 | #else 13 | #define XG_ASSERT 14 | #endif 15 | 16 | #define XG_EPS DBL_EPSILON 17 | 18 | namespace xg { 19 | 20 | template std::unique_ptr make_unique(Args &&... args) { 21 | return std::unique_ptr(new T(std::forward(args)...)); 22 | } 23 | 24 | bool IsZero(double val) noexcept; 25 | bool IsEqualDeviation (double v1, double v2, double deviation) noexcept; 26 | bool IsEqual(double v1, double v2) noexcept; 27 | } // namespace xg 28 | 29 | #endif /* XG_UTIL_COMMON */ 30 | -------------------------------------------------------------------------------- /core/webassembly/CanvasImage.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // CanvasImage.cpp 3 | // F2 4 | // 5 | // Created by weiqing.twq on 2022/1/17. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #ifdef __EMSCRIPTEN__ 10 | 11 | #include "graphics/canvas/CanvasImage.h" 12 | 13 | using namespace xg; 14 | using namespace xg::canvas; 15 | 16 | CanvasImage::~CanvasImage() { 17 | if(image_) { 18 | image_ = nullptr; 19 | } 20 | } 21 | 22 | void CanvasImage::OnLoad(std::function finished) { 23 | //通过JNI方法调用Java下载 24 | } 25 | 26 | float CanvasImage::GetWidth() { return 0; } 27 | 28 | float CanvasImage::GetHeight() { return 0; } 29 | 30 | #endif -------------------------------------------------------------------------------- /demos/android/demos-kotlin/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/android/demos-kotlin/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /demos/android/demos-kotlin/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/androidTest/java/com/antgroup/antv/samples/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.samples; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.InstrumentationRegistry; 6 | import androidx.test.runner.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getTargetContext(); 24 | 25 | assertEquals("com.antgroup.antv.f2", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/assets/mockData_1688.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "date": "3.1", 3 | "value": 62 4 | }, { 5 | "date": "3.14", 6 | "value": 62 7 | }, { 8 | "date": "3.19", 9 | "value": 62 10 | }, { 11 | "date": "3.24", 12 | "value": 63 13 | }, { 14 | "date": "3.29", 15 | "value": 62 16 | }, { 17 | "date": "4.03", 18 | "value": 62 19 | }, { 20 | "date": "4.08", 21 | "value": 62 22 | }] -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/assets/mockData_basePie.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name": "芳华", 3 | "percent": 0.4, 4 | "a": "1" 5 | }, { 6 | "name": "妖猫传", 7 | "percent": 0.2, 8 | "a": "1" 9 | }, { 10 | "name": "机器之血", 11 | "percent": 0.18, 12 | "a": "1" 13 | }, { 14 | "name": "心理罪", 15 | "percent": 0.15, 16 | "a": "1" 17 | }, { 18 | "name": "寻梦环游记", 19 | "percent": 0.05, 20 | "a": "1" 21 | }, { 22 | "name": "其他", 23 | "percent": 0.12, 24 | "a": "1" 25 | }] 26 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/assets/mockData_multiIntervalsChart.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name": "London", 3 | "月份": "Jan.", 4 | "月均降雨量": 18.9 5 | }, { 6 | "name": "London", 7 | "月份": "Feb.", 8 | "月均降雨量": 28.8 9 | }, { 10 | "name": "London", 11 | "月份": "Mar.", 12 | "月均降雨量": 39.3 13 | }, { 14 | "name": "London", 15 | "月份": "Apr.", 16 | "月均降雨量": 81.4 17 | }, { 18 | "name": "London", 19 | "月份": "May.", 20 | "月均降雨量": 47 21 | }, { 22 | "name": "London", 23 | "月份": "Jun.", 24 | "月均降雨量": 20.3 25 | }, { 26 | "name": "London", 27 | "月份": "Jul.", 28 | "月均降雨量": 24 29 | }, { 30 | "name": "London", 31 | "月份": "Aug.", 32 | "月均降雨量": 35.6 33 | }, { 34 | "name": "Berlin", 35 | "月份": "Jan.", 36 | "月均降雨量": 12.4 37 | }, { 38 | "name": "Berlin", 39 | "月份": "Feb.", 40 | "月均降雨量": 23.2 41 | }, { 42 | "name": "Berlin", 43 | "月份": "Mar.", 44 | "月均降雨量": 34.5 45 | }, { 46 | "name": "Berlin", 47 | "月份": "Apr.", 48 | "月均降雨量": 99.7 49 | }, { 50 | "name": "Berlin", 51 | "月份": "May.", 52 | "月均降雨量": 52.6 53 | }, { 54 | "name": "Berlin", 55 | "月份": "Jun.", 56 | "月均降雨量": 35.5 57 | }, { 58 | "name": "Berlin", 59 | "月份": "Jul.", 60 | "月均降雨量": 37.4 61 | }, { 62 | "name": "Berlin", 63 | "月份": "Aug.", 64 | "月均降雨量": 42.4 65 | }] -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/assets/mockData_radarArea.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "item": "Design", 3 | "user": "用户 A", 4 | "score": 70 5 | }, { 6 | "item": "Design", 7 | "user": "用户 B", 8 | "score": 30 9 | }, { 10 | "item": "Development", 11 | "user": "用户 A", 12 | "score": 60 13 | }, { 14 | "item": "Development", 15 | "user": "用户 B", 16 | "score": 70 17 | }, { 18 | "item": "Marketing", 19 | "user": "用户 A", 20 | "score": 50 21 | }, { 22 | "item": "Marketing", 23 | "user": "用户 B", 24 | "score": 60 25 | }, { 26 | "item": "Users", 27 | "user": "用户 A", 28 | "score": 40 29 | }, { 30 | "item": "Users", 31 | "user": "用户 B", 32 | "score": 50 33 | }, { 34 | "item": "Test", 35 | "user": "用户 A", 36 | "score": 60 37 | }, { 38 | "item": "Test", 39 | "user": "用户 B", 40 | "score": 70 41 | }, { 42 | "item": "Language", 43 | "user": "用户 A", 44 | "score": 70 45 | }, { 46 | "item": "Language", 47 | "user": "用户 B", 48 | "score": 50 49 | }, { 50 | "item": "Technology", 51 | "user": "用户 A", 52 | "score": 70 53 | }, { 54 | "item": "Technology", 55 | "user": "用户 B", 56 | "score": 40 57 | }, { 58 | "item": "Support", 59 | "user": "用户 A", 60 | "score": 60 61 | }, { 62 | "item": "Support", 63 | "user": "用户 B", 64 | "score": 40 65 | }] 66 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/assets/mockData_sectionInterval.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "x": "分类一", 3 | "y": [ 76, 100 ] 4 | }, { 5 | "x": "分类二", 6 | "y": [ 56, 108 ] 7 | }, { 8 | "x": "分类三", 9 | "y": [ 38, 129 ] 10 | }, { 11 | "x": "分类四", 12 | "y": [ 58, 155 ] 13 | }, { 14 | "x": "分类五", 15 | "y": [ 45, 120 ] 16 | }, { 17 | "x": "分类六", 18 | "y": [ 23, 99 ] 19 | }, { 20 | "x": "分类七", 21 | "y": [ 18, 56 ] 22 | }, { 23 | "x": "分类八", 24 | "y": [ 18, 34 ] 25 | }] 26 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/assets/mockData_singleAreaChart.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "time": "Jan.", 3 | "tem": 1000 4 | }, { 5 | "time": "Feb.", 6 | "tem": 2200 7 | }, { 8 | "time": "Mar.", 9 | "tem": 2000 10 | }, { 11 | "time": "Apr.", 12 | "tem": 2600 13 | }, { 14 | "time": "May.", 15 | "tem": 2000 16 | }, { 17 | "time": "Jun.", 18 | "tem": 2600 19 | }, { 20 | "time": "Jul.", 21 | "tem": 2800 22 | }, { 23 | "time": "Aug.", 24 | "tem": 2000 25 | }] -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/assets/mockData_singleAreaChart_2.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "month": "Jan.", 3 | "value": 6.06 4 | }, { 5 | "month": "Feb.", 6 | "value": 82.2 7 | }, { 8 | "month": "Mar.", 9 | "value": -22.11 10 | }, { 11 | "month": "Apr.", 12 | "value": 21.53 13 | }, { 14 | "month": "May.", 15 | "value": -21.74 16 | }, { 17 | "month": "Jun.", 18 | "value": 73.61 19 | }, { 20 | "month": "Jul.", 21 | "value": 53.75 22 | }, { 23 | "month": "Aug.", 24 | "value": 60.32 25 | }] -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/assets/mockData_singleIntervalChart.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "year": "1950", 3 | "sales": 29 4 | }, { 5 | "year": "1951", 6 | "sales": 30 7 | }, { 8 | "year": "1952", 9 | "sales": 31 10 | }, { 11 | "year": "1953", 12 | "sales": 32 13 | }, { 14 | "year": "1954", 15 | "sales": 33 16 | }, { 17 | "year": "1955", 18 | "sales": 34 19 | }, { 20 | "year": "1956", 21 | "sales": 35 22 | }, { 23 | "year": "1957", 24 | "sales": 36 25 | }, { 26 | "year": "1958", 27 | "sales": 37 28 | }, { 29 | "year": "1959", 30 | "sales": 38 31 | }, { 32 | "year": "1960", 33 | "sales": 29 34 | }] -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/assets/mockData_singleIntervalChart_2.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "genre": "Sports", 3 | "sold": 275 4 | }, { 5 | "genre": "Strategy", 6 | "sold": 115 7 | }, { 8 | "genre": "Action", 9 | "sold": 120 10 | }, { 11 | "genre": "Shooter", 12 | "sold": 350 13 | }, { 14 | "genre": "Other", 15 | "sold": 150 16 | }] -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/assets/mockData_trendChart_flags.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "content": "HIT电池", 3 | "position": [1608687000000, 3365.65] 4 | }, { 5 | "content": "煤炭开采", 6 | "position": [1608688920000, 3366.13] 7 | }, { 8 | "content": "白酒", 9 | "position": [1608690420000, 3376.52] 10 | }, { 11 | "content": "光伏", 12 | "position": [1608691680000, 3375.87] 13 | }, { 14 | "content": "证券", 15 | "position": [1608693420000, 3388.95] 16 | }, { 17 | "content": "航空装备", 18 | "position": [1608700080000, 3389.64] 19 | }, { 20 | "content": "白酒", 21 | "position": [1608702720000, 3371.69] 22 | }, { 23 | "content": "黄酒", 24 | "position": [1608706080000, 3378.72] 25 | }] -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/assets/wallet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/android/demos-kotlin/src/main/assets/wallet.png -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/java/com/antgroup/antv/f2/kotlinsamples/ChartModel.kt: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2.kotlinsamples 2 | 3 | import com.antgroup.antv.f2.F2CanvasView 4 | import java.io.Serializable 5 | 6 | /** 7 | * @author weiqing.tang 8 | * @date 2022-06-20 9 | */ 10 | class ChartModel : Serializable { 11 | @JvmField 12 | var title: String 13 | @JvmField 14 | var adapterClass: Class 15 | var horizontal = false 16 | 17 | constructor(title: String, adapterClass: Class) { 18 | this.title = title 19 | this.adapterClass = adapterClass 20 | } 21 | 22 | constructor( 23 | title: String, 24 | adapterClass: Class, 25 | horizontal: Boolean 26 | ) { 27 | this.title = title 28 | this.adapterClass = adapterClass 29 | this.horizontal = horizontal 30 | } 31 | } -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/java/com/antgroup/antv/f2/kotlinsamples/Utils.kt: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2.kotlinsamples 2 | 3 | import android.content.Context 4 | import java.io.ByteArrayOutputStream 5 | import java.io.IOException 6 | 7 | /** 8 | * @author weiqing.tang 9 | * @date 2022-06-20 10 | */ 11 | object Utils { 12 | @JvmStatic 13 | fun loadAssetFile(context: Context, assetFile: String?): String? { 14 | try { 15 | val `is` = context.assets.open(assetFile) 16 | val buf = ByteArray(1024 * 500) 17 | val output = ByteArrayOutputStream() 18 | var size = 0 19 | while (`is`.read(buf, 0, buf.size).also { size = it } >= 0) { 20 | output.write(buf, 0, size) 21 | } 22 | return String(output.toByteArray()) 23 | } catch (e: IOException) { 24 | } 25 | return null 26 | } 27 | } -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/jniLibs/arm64-v8a/libc++_shared.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/android/demos-kotlin/src/main/jniLibs/arm64-v8a/libc++_shared.so -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/jniLibs/armeabi-v7a/libc++_shared.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/android/demos-kotlin/src/main/jniLibs/armeabi-v7a/libc++_shared.so -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/android/demos-kotlin/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/res/layout/activity_sample.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/res/layout/activity_sample_horizontal.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/res/layout/activity_stock_time_sharing.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/res/layout/layout_chart_canvasview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 19 | 20 | 25 | 26 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/res/layout/layout_chart_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 17 | 18 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/res/menu/menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 4 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | F2Native 3 | BridgeActivity 4 | SampleActivity 5 | ChartListActivity 6 | 7 | 8 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /demos/android/demos-kotlin/src/test/java/com/antgroup/antv/samples/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.samples 2 | 3 | import org.junit.Assert 4 | import org.junit.Test 5 | 6 | /** 7 | * Example local unit test, which will execute on the development machine (host). 8 | * 9 | * @see [Testing documentation](http://d.android.com/tools/testing) 10 | */ 11 | class ExampleUnitTest { 12 | @Test 13 | fun addition_isCorrect() { 14 | Assert.assertEquals(4, (2 + 2).toLong()) 15 | } 16 | } -------------------------------------------------------------------------------- /demos/android/demos/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/android/demos/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /demos/android/demos/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /demos/android/demos/src/androidTest/java/com/antgroup/antv/samples/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.samples; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.InstrumentationRegistry; 6 | import androidx.test.runner.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getTargetContext(); 24 | 25 | assertEquals("com.antgroup.antv.f2", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/assets/mockData_1688.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "date": "3.1", 3 | "value": 62 4 | }, { 5 | "date": "3.14", 6 | "value": 62 7 | }, { 8 | "date": "3.19", 9 | "value": 62 10 | }, { 11 | "date": "3.24", 12 | "value": 63 13 | }, { 14 | "date": "3.29", 15 | "value": 62 16 | }, { 17 | "date": "4.03", 18 | "value": 62 19 | }, { 20 | "date": "4.08", 21 | "value": 62 22 | }] -------------------------------------------------------------------------------- /demos/android/demos/src/main/assets/mockData_basePie.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name": "芳华", 3 | "percent": 0.4, 4 | "a": "1" 5 | }, { 6 | "name": "妖猫传", 7 | "percent": 0.2, 8 | "a": "1" 9 | }, { 10 | "name": "机器之血", 11 | "percent": 0.18, 12 | "a": "1" 13 | }, { 14 | "name": "心理罪", 15 | "percent": 0.15, 16 | "a": "1" 17 | }, { 18 | "name": "寻梦环游记", 19 | "percent": 0.05, 20 | "a": "1" 21 | }, { 22 | "name": "其他", 23 | "percent": 0.12, 24 | "a": "1" 25 | }] 26 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/assets/mockData_multiIntervalsChart.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name": "London", 3 | "月份": "Jan.", 4 | "月均降雨量": 18.9 5 | }, { 6 | "name": "London", 7 | "月份": "Feb.", 8 | "月均降雨量": 28.8 9 | }, { 10 | "name": "London", 11 | "月份": "Mar.", 12 | "月均降雨量": 39.3 13 | }, { 14 | "name": "London", 15 | "月份": "Apr.", 16 | "月均降雨量": 81.4 17 | }, { 18 | "name": "London", 19 | "月份": "May.", 20 | "月均降雨量": 47 21 | }, { 22 | "name": "London", 23 | "月份": "Jun.", 24 | "月均降雨量": 20.3 25 | }, { 26 | "name": "London", 27 | "月份": "Jul.", 28 | "月均降雨量": 24 29 | }, { 30 | "name": "London", 31 | "月份": "Aug.", 32 | "月均降雨量": 35.6 33 | }, { 34 | "name": "Berlin", 35 | "月份": "Jan.", 36 | "月均降雨量": 12.4 37 | }, { 38 | "name": "Berlin", 39 | "月份": "Feb.", 40 | "月均降雨量": 23.2 41 | }, { 42 | "name": "Berlin", 43 | "月份": "Mar.", 44 | "月均降雨量": 34.5 45 | }, { 46 | "name": "Berlin", 47 | "月份": "Apr.", 48 | "月均降雨量": 99.7 49 | }, { 50 | "name": "Berlin", 51 | "月份": "May.", 52 | "月均降雨量": 52.6 53 | }, { 54 | "name": "Berlin", 55 | "月份": "Jun.", 56 | "月均降雨量": 35.5 57 | }, { 58 | "name": "Berlin", 59 | "月份": "Jul.", 60 | "月均降雨量": 37.4 61 | }, { 62 | "name": "Berlin", 63 | "月份": "Aug.", 64 | "月均降雨量": 42.4 65 | }] -------------------------------------------------------------------------------- /demos/android/demos/src/main/assets/mockData_radarArea.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "item": "Design", 3 | "user": "用户 A", 4 | "score": 70 5 | }, { 6 | "item": "Design", 7 | "user": "用户 B", 8 | "score": 30 9 | }, { 10 | "item": "Development", 11 | "user": "用户 A", 12 | "score": 60 13 | }, { 14 | "item": "Development", 15 | "user": "用户 B", 16 | "score": 70 17 | }, { 18 | "item": "Marketing", 19 | "user": "用户 A", 20 | "score": 50 21 | }, { 22 | "item": "Marketing", 23 | "user": "用户 B", 24 | "score": 60 25 | }, { 26 | "item": "Users", 27 | "user": "用户 A", 28 | "score": 40 29 | }, { 30 | "item": "Users", 31 | "user": "用户 B", 32 | "score": 50 33 | }, { 34 | "item": "Test", 35 | "user": "用户 A", 36 | "score": 60 37 | }, { 38 | "item": "Test", 39 | "user": "用户 B", 40 | "score": 70 41 | }, { 42 | "item": "Language", 43 | "user": "用户 A", 44 | "score": 70 45 | }, { 46 | "item": "Language", 47 | "user": "用户 B", 48 | "score": 50 49 | }, { 50 | "item": "Technology", 51 | "user": "用户 A", 52 | "score": 70 53 | }, { 54 | "item": "Technology", 55 | "user": "用户 B", 56 | "score": 40 57 | }, { 58 | "item": "Support", 59 | "user": "用户 A", 60 | "score": 60 61 | }, { 62 | "item": "Support", 63 | "user": "用户 B", 64 | "score": 40 65 | }] 66 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/assets/mockData_sectionInterval.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "x": "分类一", 3 | "y": [ 76, 100 ] 4 | }, { 5 | "x": "分类二", 6 | "y": [ 56, 108 ] 7 | }, { 8 | "x": "分类三", 9 | "y": [ 38, 129 ] 10 | }, { 11 | "x": "分类四", 12 | "y": [ 58, 155 ] 13 | }, { 14 | "x": "分类五", 15 | "y": [ 45, 120 ] 16 | }, { 17 | "x": "分类六", 18 | "y": [ 23, 99 ] 19 | }, { 20 | "x": "分类七", 21 | "y": [ 18, 56 ] 22 | }, { 23 | "x": "分类八", 24 | "y": [ 18, 34 ] 25 | }] 26 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/assets/mockData_singleAreaChart.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "time": "Jan.", 3 | "tem": 1000 4 | }, { 5 | "time": "Feb.", 6 | "tem": 2200 7 | }, { 8 | "time": "Mar.", 9 | "tem": 2000 10 | }, { 11 | "time": "Apr.", 12 | "tem": 2600 13 | }, { 14 | "time": "May.", 15 | "tem": 2000 16 | }, { 17 | "time": "Jun.", 18 | "tem": 2600 19 | }, { 20 | "time": "Jul.", 21 | "tem": 2800 22 | }, { 23 | "time": "Aug.", 24 | "tem": 2000 25 | }] -------------------------------------------------------------------------------- /demos/android/demos/src/main/assets/mockData_singleAreaChart_2.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "month": "Jan.", 3 | "value": 6.06 4 | }, { 5 | "month": "Feb.", 6 | "value": 82.2 7 | }, { 8 | "month": "Mar.", 9 | "value": -22.11 10 | }, { 11 | "month": "Apr.", 12 | "value": 21.53 13 | }, { 14 | "month": "May.", 15 | "value": -21.74 16 | }, { 17 | "month": "Jun.", 18 | "value": 73.61 19 | }, { 20 | "month": "Jul.", 21 | "value": 53.75 22 | }, { 23 | "month": "Aug.", 24 | "value": 60.32 25 | }] -------------------------------------------------------------------------------- /demos/android/demos/src/main/assets/mockData_singleIntervalChart.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "year": "1950", 3 | "sales": 29 4 | }, { 5 | "year": "1951", 6 | "sales": 30 7 | }, { 8 | "year": "1952", 9 | "sales": 31 10 | }, { 11 | "year": "1953", 12 | "sales": 32 13 | }, { 14 | "year": "1954", 15 | "sales": 33 16 | }, { 17 | "year": "1955", 18 | "sales": 34 19 | }, { 20 | "year": "1956", 21 | "sales": 35 22 | }, { 23 | "year": "1957", 24 | "sales": 36 25 | }, { 26 | "year": "1958", 27 | "sales": 37 28 | }, { 29 | "year": "1959", 30 | "sales": 38 31 | }, { 32 | "year": "1960", 33 | "sales": 29 34 | }] -------------------------------------------------------------------------------- /demos/android/demos/src/main/assets/mockData_singleIntervalChart_2.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "genre": "Sports", 3 | "sold": 275 4 | }, { 5 | "genre": "Strategy", 6 | "sold": 115 7 | }, { 8 | "genre": "Action", 9 | "sold": 120 10 | }, { 11 | "genre": "Shooter", 12 | "sold": 350 13 | }, { 14 | "genre": "Other", 15 | "sold": 150 16 | }] -------------------------------------------------------------------------------- /demos/android/demos/src/main/assets/mockData_trendChart_flags.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "content": "HIT电池", 3 | "position": [1608687000000, 3365.65] 4 | }, { 5 | "content": "煤炭开采", 6 | "position": [1608688920000, 3366.13] 7 | }, { 8 | "content": "白酒", 9 | "position": [1608690420000, 3376.52] 10 | }, { 11 | "content": "光伏", 12 | "position": [1608691680000, 3375.87] 13 | }, { 14 | "content": "证券", 15 | "position": [1608693420000, 3388.95] 16 | }, { 17 | "content": "航空装备", 18 | "position": [1608700080000, 3389.64] 19 | }, { 20 | "content": "白酒", 21 | "position": [1608702720000, 3371.69] 22 | }, { 23 | "content": "黄酒", 24 | "position": [1608706080000, 3378.72] 25 | }] -------------------------------------------------------------------------------- /demos/android/demos/src/main/assets/wallet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/android/demos/src/main/assets/wallet.png -------------------------------------------------------------------------------- /demos/android/demos/src/main/java/com/antgroup/antv/f2/samples/ChartModel.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2.samples; 2 | 3 | import com.antgroup.antv.f2.F2CanvasView; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author qingyuan.yl 9 | * @version 10.1.1 10 | * @date 2020-09-25 11 | */ 12 | public class ChartModel implements Serializable { 13 | public String title; 14 | 15 | public Class adapterClass; 16 | 17 | public boolean horizontal = false; 18 | 19 | public ChartModel(String title, Class adapterClass) { 20 | this.title = title; 21 | this.adapterClass = adapterClass; 22 | } 23 | 24 | public ChartModel(String title, Class adapterClass, boolean horizontal) { 25 | this.title = title; 26 | this.adapterClass = adapterClass; 27 | this.horizontal = horizontal; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/java/com/antgroup/antv/f2/samples/Utils.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2.samples; 2 | 3 | import android.content.Context; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | 9 | /** 10 | * @author qingyuan.yl 11 | * @date 2020-09-24 12 | */ 13 | public class Utils { 14 | 15 | public static String loadAssetFile(Context context, String assetFile) { 16 | try { 17 | InputStream is = context.getAssets().open(assetFile); 18 | 19 | byte[] buf = new byte[1024 * 500]; 20 | 21 | ByteArrayOutputStream output = new ByteArrayOutputStream(); 22 | int size = 0; 23 | while ((size = is.read(buf, 0, buf.length)) >= 0) { 24 | output.write(buf, 0, size); 25 | } 26 | 27 | return new String(output.toByteArray()); 28 | } catch (IOException e) { 29 | } 30 | return null; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/java/com/antgroup/antv/f2/samples/charts/MultiIntervalChart.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.f2.samples.charts; 2 | 3 | import com.antgroup.antv.f2.F2CanvasView; 4 | import com.antgroup.antv.f2.F2Chart; 5 | import com.antgroup.antv.f2.samples.Utils; 6 | 7 | /** 8 | * 分组柱状图 9 | * @author qingyuan.yl 10 | * @date 2020-09-27 11 | */ 12 | public class MultiIntervalChart implements F2CanvasView.Adapter { 13 | private F2Chart mChart; 14 | 15 | @Override 16 | public void onCanvasDraw(F2CanvasView canvasView) { 17 | if (mChart == null) { 18 | mChart = F2Chart.create(canvasView.getContext(), "MultiIntervalChart", canvasView.getWidth(), canvasView.getHeight()); 19 | } 20 | 21 | mChart.setCanvas(canvasView); 22 | mChart.padding(10, 0, 0, 0); 23 | mChart.source(Utils.loadAssetFile(canvasView.getContext(), "mockData_multiIntervalsChart.json")); 24 | mChart.interval().position("月份*月均降雨量").color("name").adjust("dodge"); 25 | mChart.setScale("月份", new F2Chart.ScaleConfigBuilder().range(new double[]{0.065, 0.935})); 26 | mChart.render(); 27 | } 28 | 29 | @Override 30 | public void onDestroy() { 31 | if (mChart != null) { 32 | mChart.destroy(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/jniLibs/arm64-v8a/libc++_shared.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/android/demos/src/main/jniLibs/arm64-v8a/libc++_shared.so -------------------------------------------------------------------------------- /demos/android/demos/src/main/jniLibs/armeabi-v7a/libc++_shared.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/android/demos/src/main/jniLibs/armeabi-v7a/libc++_shared.so -------------------------------------------------------------------------------- /demos/android/demos/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/android/demos/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demos/android/demos/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/res/layout/activity_sample.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/res/layout/activity_sample_horizontal.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/res/layout/activity_stock_time_sharing.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/res/layout/layout_chart_canvasview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 19 | 20 | 25 | 26 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/res/layout/layout_chart_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 17 | 18 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/res/menu/menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 4 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | F2Native 3 | BridgeActivity 4 | SampleActivity 5 | ChartListActivity 6 | 7 | 8 | -------------------------------------------------------------------------------- /demos/android/demos/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /demos/android/demos/src/test/java/com/antgroup/antv/samples/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.antgroup.antv.samples; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Demos-Swift 4 | // 5 | // Created by weiqing.twq on 2022/6/1. 6 | // 7 | 8 | import UIKit 9 | 10 | @main 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | // Override point for customization after application launch. 17 | self.window = UIWindow.init(frame: UIScreen.main.bounds) 18 | let viewController = ViewController.init(); 19 | self.window!.rootViewController = UINavigationController.init(rootViewController: viewController) 20 | self.window!.makeKeyAndVisible() 21 | return true 22 | } 23 | 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/128x128.png -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/16x16.png -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/180x180 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/180x180 1.png -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/180x180.png -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/256x256.png -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/32x32.png -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/512x512.png -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/AppIcon.appiconset/64x64.png -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIApplicationSceneManifest 6 | 7 | UIApplicationSupportsMultipleScenes 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Res/mockData_baseArea.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "time": "Jan.", 3 | "tem": 1000 4 | }, { 5 | "time": "Feb.", 6 | "tem": 2200 7 | }, { 8 | "time": "Mar.", 9 | "tem": 2000 10 | }, { 11 | "time": "Apr.", 12 | "tem": 2600 13 | }, { 14 | "time": "May.", 15 | "tem": 2000 16 | }, { 17 | "time": "Jun.", 18 | "tem": 2600 19 | }, { 20 | "time": "Jul.", 21 | "tem": 2800 22 | }, { 23 | "time": "Aug.", 24 | "tem": 2000 25 | }] -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Res/mockData_baseInterval.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "year": "1951 年\n第一季度", 3 | "sales": 38 4 | }, { 5 | "year": "1952 年\n第一季度", 6 | "sales": 52 7 | }, { 8 | "year": "1956 年\n第一季度", 9 | "sales": 61 10 | }, { 11 | "year": "1957 年\n第一季度", 12 | "sales": 145 13 | }, { 14 | "year": "1958 年\n第一季度", 15 | "sales": 48 16 | }, { 17 | "year": "1959 年\n第一季度", 18 | "sales": 38 19 | }, { 20 | "year": "1960 年\n第一季度", 21 | "sales": 38 22 | }, { 23 | "year": "1962 年\n第一季度", 24 | "sales": 38 25 | }] 26 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Res/mockData_baseInterval2.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "genre": "Sports", 3 | "sold": 275 4 | }, { 5 | "genre": "Strategy", 6 | "sold": 115 7 | }, { 8 | "genre": "Action", 9 | "sold": 120 10 | }, { 11 | "genre": "Shooter", 12 | "sold": 350 13 | }, { 14 | "genre": "Other", 15 | "sold": 150 16 | }] 17 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Res/mockData_basePie.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name": "芳华", 3 | "percent": 0.4, 4 | "a": "1" 5 | }, { 6 | "name": "妖猫传", 7 | "percent": 0.2, 8 | "a": "1" 9 | }, { 10 | "name": "机器之血", 11 | "percent": 0.18, 12 | "a": "1" 13 | }, { 14 | "name": "心理罪", 15 | "percent": 0.15, 16 | "a": "1" 17 | }, { 18 | "name": "寻梦环游记", 19 | "percent": 0.05, 20 | "a": "1" 21 | }, { 22 | "name": "其他", 23 | "percent": 0.12, 24 | "a": "1" 25 | }] 26 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Res/mockData_multiInterval.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name": "London", 3 | "month": "Jan.", 4 | "value": 18.9 5 | }, { 6 | "name": "London", 7 | "month": "Feb.", 8 | "value": 28.8 9 | }, { 10 | "name": "London", 11 | "month": "Mar.", 12 | "value": 39.3 13 | }, { 14 | "name": "London", 15 | "month": "Apr.", 16 | "value": 81.4 17 | }, { 18 | "name": "London", 19 | "month": "May.", 20 | "value": 47 21 | }, { 22 | "name": "London", 23 | "month": "Jun.", 24 | "value": 20.3 25 | }, { 26 | "name": "London", 27 | "month": "Jul.", 28 | "value": 24 29 | }, { 30 | "name": "London", 31 | "month": "Aug.", 32 | "value": 35.6 33 | }, { 34 | "name": "Berlin", 35 | "month": "Jan.", 36 | "value": 12.4 37 | }, { 38 | "name": "Berlin", 39 | "month": "Feb.", 40 | "value": 23.2 41 | }, { 42 | "name": "Berlin", 43 | "month": "Mar.", 44 | "value": 34.5 45 | }, { 46 | "name": "Berlin", 47 | "month": "Apr.", 48 | "value": 99.7 49 | }, { 50 | "name": "Berlin", 51 | "month": "May.", 52 | "value": 52.6 53 | }, { 54 | "name": "Berlin", 55 | "month": "Jun.", 56 | "value": 35.5 57 | }, { 58 | "name": "Berlin", 59 | "month": "Jul.", 60 | "value": 37.4 61 | }, { 62 | "name": "Berlin", 63 | "month": "Aug.", 64 | "value": 42.4 65 | }] -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Res/mockData_radarArea.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "item": "Design", 3 | "user": "用户 A", 4 | "score": 70 5 | }, { 6 | "item": "Design", 7 | "user": "用户 B", 8 | "score": 30 9 | }, { 10 | "item": "Development", 11 | "user": "用户 A", 12 | "score": 60 13 | }, { 14 | "item": "Development", 15 | "user": "用户 B", 16 | "score": 70 17 | }, { 18 | "item": "Marketing", 19 | "user": "用户 A", 20 | "score": 50 21 | }, { 22 | "item": "Marketing", 23 | "user": "用户 B", 24 | "score": 60 25 | }, { 26 | "item": "Users", 27 | "user": "用户 A", 28 | "score": 40 29 | }, { 30 | "item": "Users", 31 | "user": "用户 B", 32 | "score": 50 33 | }, { 34 | "item": "Test", 35 | "user": "用户 A", 36 | "score": 60 37 | }, { 38 | "item": "Test", 39 | "user": "用户 B", 40 | "score": 70 41 | }, { 42 | "item": "Language", 43 | "user": "用户 A", 44 | "score": 70 45 | }, { 46 | "item": "Language", 47 | "user": "用户 B", 48 | "score": 50 49 | }, { 50 | "item": "Technology", 51 | "user": "用户 A", 52 | "score": 70 53 | }, { 54 | "item": "Technology", 55 | "user": "用户 B", 56 | "score": 40 57 | }, { 58 | "item": "Support", 59 | "user": "用户 A", 60 | "score": 60 61 | }, { 62 | "item": "Support", 63 | "user": "用户 B", 64 | "score": 40 65 | }] 66 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Res/mockData_setionInterval.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "x": "分类一", 3 | "y": [ 76, 100 ] 4 | }, { 5 | "x": "分类二", 6 | "y": [ 56, 108 ] 7 | }, { 8 | "x": "分类三", 9 | "y": [ 38, 129 ] 10 | }, { 11 | "x": "分类四", 12 | "y": [ 58, 155 ] 13 | }, { 14 | "x": "分类五", 15 | "y": [ 45, 120 ] 16 | }, { 17 | "x": "分类六", 18 | "y": [ 23, 99 ] 19 | }, { 20 | "x": "分类七", 21 | "y": [ 18, 56 ] 22 | }, { 23 | "x": "分类八", 24 | "y": [ 18, 34 ] 25 | }] 26 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Res/mockData_singleAreaChart_2.json: -------------------------------------------------------------------------------- 1 | [{"month":"Jan.","value":6.06},{"month":"Feb.","value":82.2},{"month":"Mar.","value":-22.11},{"month":"Apr.","value":21.53},{"month":"May.","value":-21.74},{"month":"Jun.","value":73.61},{"month":"Jul.","value":53.75},{"month":"Aug.","value":60.32}] -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Res/mockData_singleIntervalChart_under_zero.json: -------------------------------------------------------------------------------- 1 | [{"time":"周一","tem":6.9,"city":"tokyo"},{"time":"周二","tem":9.5,"city":"tokyo"},{"time":"周三","tem":14.5,"city":"tokyo"},{"time":"周四","tem":18.2,"city":"tokyo"},{"time":"周五","tem":21.5,"city":"tokyo"},{"time":"周六","tem":25.2,"city":"tokyo"},{"time":"周日","tem":26.5,"city":"tokyo"},{"time":"周一","tem":-10.8,"city":"newYork"},{"time":"周二","tem":-5.7,"city":"newYork"},{"time":"周三","tem":-11.3,"city":"newYork"},{"time":"周四","tem":-17,"city":"newYork"},{"time":"周五","tem":-22,"city":"newYork"},{"time":"周六","tem":-24.8,"city":"newYork"},{"time":"周日","tem":-24.1,"city":"newYork"},{"time":"周一","tem":2.6,"city":"berlin"},{"time":"周二","tem":3.5,"city":"berlin"},{"time":"周三","tem":8.4,"city":"berlin"},{"time":"周四","tem":13.5,"city":"berlin"},{"time":"周五","tem":17,"city":"berlin"},{"time":"周六","tem":-18.6,"city":"berlin"},{"time":"周日","tem":17.9,"city":"berlin"}] -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Views/BaseAreaChart2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseAreaChart2.swift 3 | // F2Native 4 | // 5 | // Created by Westin on 2024-06-09. 6 | // 7 | 8 | import F2 9 | 10 | class BaseAreaChart2: BaseLineChart { 11 | 12 | override func chartRender() { 13 | guard let jsonPath = Bundle.main.path(forResource: "Res/mockData_singleAreaChart_2", ofType: "json"), 14 | let jsonDataString = try? String(contentsOfFile: jsonPath), 15 | let canvasView = self.canvasView, 16 | let chart = self.chart else { 17 | return 18 | } 19 | let jsonData = F2Utils.toJsonArray(jsonDataString) 20 | chart.clear() 21 | chart.canvas()(canvasView).padding()(20, 10, 20, 0).source()(jsonData) 22 | chart.axis()("tem", ["grid": ["stroke": "#000"]]) 23 | chart.line()().position()("month*value") 24 | chart.area()().position()("month*value").fixedColor()("#1890FF0F") 25 | chart.scale()("value", ["nice": true]) 26 | chart.animate()(true) 27 | chart.render()() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Views/BaseAreaChart3.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseAreaChart3.swift 3 | // F2Native 4 | // 5 | // Created by Westin on 2024-06-09. 6 | // 7 | 8 | import F2 9 | 10 | class BaseAreaChart3: BaseLineChart { 11 | 12 | override func chartRender() { 13 | guard let jsonPath = Bundle.main.path(forResource: "Res/mockData_singleAreaChart_2", ofType: "json"), 14 | let jsonDataString = try? String(contentsOfFile: jsonPath), 15 | let canvasView = self.canvasView, 16 | let chart = self.chart else { 17 | return 18 | } 19 | let jsonData = F2Utils.toJsonArray(jsonDataString) 20 | chart.clear() 21 | chart.canvas()(canvasView).padding()(20, 10, 20, 0).source()(jsonData) 22 | chart.axis()("tem", ["grid": ["stroke": "#000"]]) 23 | chart.line()().position()("month*value") 24 | chart.area()().position()("month*value").fixedColor()("#1890FF0F") 25 | chart.scale()("value", ["nice": true]) 26 | chart.animate()(true) 27 | chart.render()() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Views/BaseBarChart.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseInterval2UIView.swift 3 | // Demos-Swift 4 | // 5 | // Created by weiqing.twq on 2022/6/1. 6 | // 7 | 8 | import Foundation 9 | import F2 10 | 11 | class BaseBarChart: BaseLineChart { 12 | 13 | override func chartRender() { 14 | guard let jsonPath = Bundle.main.path(forResource: "Res/mockData_baseInterval", ofType: "json"), 15 | let jsonDataString = try? String(contentsOfFile: jsonPath), 16 | let canvasView = self.canvasView, 17 | let chart = self.chart else { 18 | return 19 | } 20 | let jsonData = F2Utils.toJsonArray(jsonDataString) 21 | chart.clear() 22 | chart.canvas()(canvasView).padding()(20, 10, 20, 10) 23 | chart.source()(jsonData) 24 | chart.axis()("year", ["grid": false]) 25 | chart.axis()("sales", ["grid": ["type": "dash", "lineWidth": 2, "lineDash": [6, 2]]]) 26 | chart.scale()("year", ["range": [0.1, 0.9]]) 27 | chart.scale()("sales", ["nice": true]) 28 | chart.interval()().position()("year*sales").style()([ 29 | "rounding": [10, 10, 0, 0] // [tl, tr, bl, br] 30 | ]) 31 | chart.tooltip()([:]) 32 | chart.animate()(true) 33 | chart.render()() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Views/BaseBarChart2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseBarChart2.swift 3 | // F2Native 4 | // 5 | // Created by Westin on 2024-06-09. 6 | // 7 | 8 | import F2 9 | 10 | class BaseBarChart2: BaseLineChart { 11 | 12 | override func chartRender() { 13 | let jsonPath = Bundle.main.path(forResource: "Res/mockData_baseInterval2", ofType: "json") 14 | guard let jsonString = try? String.init(contentsOfFile: jsonPath!) else { 15 | return 16 | } 17 | let jsonData = F2Utils.toJsonArray(jsonString) 18 | self.chart!.clear() 19 | self.chart!.canvas()(self.canvasView!) 20 | self.chart!.padding()(10, 20, 10, 0) 21 | self.chart!.source()(jsonData) 22 | self.chart!.interval()().position()("genre*sold").color()("genre", []) 23 | self.chart!.scale()("sold", ["min":0]) 24 | self.chart!.scale()("genre", ["range": [0.1, 0.9]]) 25 | self.chart!.animate()(true) 26 | self.chart!.render()(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Views/BasePieChart.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BasePieChart.swift 3 | // F2Native 4 | // 5 | // Created by weiqing.twq on 2024-06-09. 6 | // 7 | 8 | import F2 9 | 10 | class BasePieChart: BaseLineChart { 11 | 12 | override func chartRender() { 13 | let jsonPath = Bundle.main.path(forResource: "Res/mockData_basePie", ofType: "json") 14 | guard let jsonString = try? String.init(contentsOfFile: jsonPath!) else { 15 | return 16 | } 17 | guard let chart = self.chart else { 18 | return 19 | } 20 | 21 | guard let canvasView = self.canvasView else { 22 | return 23 | } 24 | 25 | let jsonData = F2Utils.toJsonArray(jsonString) 26 | chart.clear() 27 | chart.canvas()(canvasView) 28 | chart.source()(jsonData) 29 | chart.padding()(10, 20, 10, 0) 30 | chart.axis()("percent", ["line": false, "label": false, "grid": false]) 31 | chart.axis()("a", ["line": false, "label": false, "grid": false]) 32 | chart.coord()(["type": "polar", "transposed": true]) 33 | chart.interval()().position()("a*percent").color()("name", []).adjust()("stack").fixedSize()(1).style()(["lineWidth": 1, "stroke": "#ffffff"]) 34 | chart.animate()(true) 35 | chart.render()() 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Views/BasePointChart.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BasePointChart.swift 3 | // F2Native 4 | // 5 | // Created by Westin on 2024-06-09. 6 | // 7 | 8 | import F2 9 | 10 | class BasePointChart: BaseLineChart { 11 | 12 | override func chartRender() { 13 | guard let jsonPath = Bundle.main.path(forResource: "Res/mockData_singlePointChart", ofType: "json"), 14 | let jsonDataString = try? String(contentsOfFile: jsonPath), 15 | let canvasView = self.canvasView, 16 | let chart = self.chart else { 17 | return 18 | } 19 | let jsonData = F2Utils.toJsonArray(jsonDataString) 20 | chart.clear() 21 | chart.canvas()(canvasView).padding()(20, 10, 20, 0) 22 | chart.source()(jsonData) 23 | chart.point()().position()("x*y").size()("z", [3, 10]).fixedShape()("circle") 24 | chart.animate()(true) 25 | chart.render()() 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Views/ContrastLineChart.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContrastLineChart.swift 3 | // F2Native 4 | // 5 | // Created by Westin on 2024-06-09. 6 | // 7 | 8 | import Foundation 9 | import F2 10 | 11 | class ContrastLineChart: BaseLineChart { 12 | 13 | override func chartRender() { 14 | guard let jsonPath = Bundle.main.path(forResource: "Res/mockData_multiLines", ofType: "json"), 15 | let jsonDataString = try? String(contentsOfFile: jsonPath), 16 | let canvasView = self.canvasView, 17 | let chart = self.chart else { 18 | return 19 | } 20 | let jsonData = F2Utils.toJsonArray(jsonDataString) 21 | chart.clear() 22 | chart.canvas()(canvasView).padding()(20, 10, 20, 0) 23 | chart.source()(jsonData) 24 | chart.scale()("value", ["nice": true]) 25 | chart.scale()("date", ["tickCount": 5]) 26 | chart.axis()("date", ["label": ["textAlign": "center"]]) 27 | chart.line()().position()("date*value").color()("type", []).fixedSize()(2).fixedShape()("smooth") 28 | chart.legend()("type", ["radius": 3, "symbol": "square"]) 29 | chart.tooltip()([:]) 30 | chart.animate()(true) 31 | chart.render()() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Views/GroupBarChart.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GroupBarChart.swift 3 | // F2Native 4 | // 5 | // Created by Westin on 2024-06-09. 6 | // 7 | 8 | import F2 9 | 10 | class GroupBarChart: BaseLineChart { 11 | 12 | override func chartRender() { 13 | guard let jsonPath = Bundle.main.path(forResource: "Res/mockData_multiInterval", ofType: "json"), 14 | let jsonDataString = try? String(contentsOfFile: jsonPath), 15 | let canvasView = self.canvasView, 16 | let chart = self.chart else { 17 | return 18 | } 19 | let jsonData = F2Utils.toJsonArray(jsonDataString) 20 | chart.clear() 21 | chart.canvas()(canvasView).padding()(15, 15, 15, 15) 22 | chart.source()(jsonData) 23 | chart.axis()("month", ["grid": false]) 24 | chart.scale()("month", ["range": [0.1, 0.9]]) 25 | chart.scale()("value", ["nice": true]) 26 | chart.interval()().adjust()("dodge").position()("month*value").color()("name", []) 27 | chart.tooltip()([:]) 28 | chart.legend()("name", ["position": "bottom", "align": "center"]) 29 | chart.animate()(true) 30 | chart.render()() 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Views/GroupBarChart2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GroupBarChart2.swift 3 | // F2Native 4 | // 5 | // Created by Westin on 2024-06-09. 6 | // 7 | 8 | import F2 9 | 10 | class GroupBarChart2: BaseLineChart { 11 | 12 | override func chartRender() { 13 | guard let jsonPath = Bundle.main.path(forResource: "Res/mockData_singleIntervalChart_under_zero", ofType: "json"), 14 | let jsonDataString = try? String(contentsOfFile: jsonPath), 15 | let canvasView = self.canvasView, 16 | let chart = self.chart else { 17 | return 18 | } 19 | let jsonData = F2Utils.toJsonArray(jsonDataString) 20 | chart.clear() 21 | chart.canvas()(canvasView).padding()(20, 10, 20, 0) 22 | chart.source()(jsonData) 23 | chart.axis()("tem", ["grid": ["stroke": "#000"]]) 24 | chart.interval()().position()("time*tem").color()("city", []).adjust()("dodge") 25 | chart.scale()("time", ["range": [0.1, 0.9]]) 26 | chart.scale()("tem", ["nice": true]) 27 | chart.tooltip()([:]) 28 | chart.animate()(true) 29 | chart.render()() 30 | } 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Views/GroupStackBarChart.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GroupStackBarChart.swift 3 | // F2Native 4 | // 5 | // Created by Westin on 2024-06-09. 6 | // 7 | 8 | import F2 9 | 10 | class GroupStackBarChart: BaseLineChart { 11 | 12 | override func chartRender() { 13 | guard let jsonPath = Bundle.main.path(forResource: "Res/mockData_multiInterval", ofType: "json"), 14 | let jsonDataString = try? String(contentsOfFile: jsonPath), 15 | let canvasView = self.canvasView, 16 | let chart = self.chart else { 17 | return 18 | } 19 | let jsonData = F2Utils.toJsonArray(jsonDataString) 20 | chart.clear() 21 | chart.canvas()(canvasView).padding()(20, 10, 20, 0) 22 | chart.source()(jsonData) 23 | chart.axis()("month", ["grid": false]) 24 | chart.scale()("month", ["range": [0.1, 0.9]]) 25 | chart.scale()("value", ["nice": true]) 26 | chart.interval()().adjust()("stack").position()("month*value").color()("name", []) 27 | chart.animate()(true) 28 | chart.render()() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Views/HistogramBarChart.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HistogramBarChart.swift 3 | // F2Native 4 | // 5 | // Created by Westin on 2024-06-09. 6 | // 7 | 8 | import F2 9 | 10 | class HistogramBarChart: BaseLineChart { 11 | 12 | override func chartRender() { 13 | guard let jsonPath = Bundle.main.path(forResource: "Res/mockData_setionInterval", ofType: "json"), 14 | let jsonDataString = try? String(contentsOfFile: jsonPath), 15 | let canvasView = self.canvasView, 16 | let chart = self.chart else { 17 | return 18 | } 19 | let jsonData = F2Utils.toJsonArray(jsonDataString) 20 | chart.clear() 21 | chart.canvas()(canvasView).padding()(20, 10, 20, 0) 22 | chart.source()(jsonData) 23 | chart.axis()("x", ["grid": false]) 24 | chart.axis()("y", ["grid": ["type": "dash", "lineWidth": 2, "lineDash": [6, 2]]]) 25 | chart.scale()("x", ["range": [0.1, 0.9]]) 26 | chart.scale()("y", ["nice": true]) 27 | chart.interval()().position()("x*y") 28 | chart.animate()(true) 29 | chart.render()() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Demos-Swift/Views/StackedAreaChart.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StackedAreaChart.swift 3 | // F2Native 4 | // 5 | // Created by Westin on 2024-06-09. 6 | // 7 | 8 | import F2 9 | 10 | class StackedAreaChart: BaseLineChart { 11 | 12 | override func chartRender() { 13 | guard let jsonPath = Bundle.main.path(forResource: "Res/mockData_multiArea", ofType: "json"), 14 | let jsonDataString = try? String(contentsOfFile: jsonPath), 15 | let canvasView = self.canvasView, 16 | let chart = self.chart else { 17 | return 18 | } 19 | let jsonData = F2Utils.toJsonArray(jsonDataString) 20 | chart.clear() 21 | chart.canvas()(canvasView).padding()(20, 10, 20, 0) 22 | chart.source()(jsonData) 23 | chart.scale()("date", ["tickCount": 5]) 24 | chart.scale()("value", ["min": 0]) 25 | chart.axis()("date", ["grid": false, "label": ["textAlign": "start"]]) 26 | chart.line()().adjust()("stack").position()("date*value").color()("city", []).fixedSize()(2) 27 | chart.area()().adjust()("stack").position()("date*value").color()("city", []).fixedSize()(2) 28 | chart.tooltip()([:]) 29 | chart.animate()(true) 30 | chart.render()() 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /demos/ios/Demos-Swift/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '13.0' 2 | 3 | target "Demos-Swift" do 4 | pod 'F2' 5 | end 6 | 7 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface AppDelegate : UIResponder 4 | 5 | @property (nonatomic, strong) UIWindow *window; 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "ViewController.h" 3 | 4 | @interface AppDelegate () 5 | 6 | @end 7 | 8 | @implementation AppDelegate 9 | 10 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 11 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 12 | UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[ViewController new]]; 13 | self.window.rootViewController = nav; 14 | [self.window makeKeyAndVisible]; 15 | return YES; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/128x128.png -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/16x16.png -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/180x180.png -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/256x256.png -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/32x32.png -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/512x512.png -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/ios/Demos/Demos/Assets.xcassets/AppIcon.appiconset/64x64.png -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/BugFixViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BugFixViewController.h 3 | // F2Native 4 | // 5 | // Created by ruize on 2022/2/7. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BugFixViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/ChartListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ChartListViewController.h 3 | // F2Native 4 | // 5 | // Created by 青原 on 2021/5/13. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ChartListViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/DemoViewController.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | NS_ASSUME_NONNULL_BEGIN 5 | 6 | @interface DemoViewController : UIViewController 7 | 8 | -(instancetype)initWithInfo:(NSDictionary *)info; 9 | 10 | @end 11 | 12 | NS_ASSUME_NONNULL_END 13 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Res/mockData_baseArea.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "time": "Jan.", 3 | "tem": 1000 4 | }, { 5 | "time": "Feb.", 6 | "tem": 2200 7 | }, { 8 | "time": "Mar.", 9 | "tem": 2000 10 | }, { 11 | "time": "Apr.", 12 | "tem": 2600 13 | }, { 14 | "time": "May.", 15 | "tem": 2000 16 | }, { 17 | "time": "Jun.", 18 | "tem": 2600 19 | }, { 20 | "time": "Jul.", 21 | "tem": 2800 22 | }, { 23 | "time": "Aug.", 24 | "tem": 2000 25 | }] -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Res/mockData_baseInterval.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "year": "1951 年\n第一季度", 3 | "sales": 38 4 | }, { 5 | "year": "1952 年\n第一季度", 6 | "sales": 52 7 | }, { 8 | "year": "1956 年\n第一季度", 9 | "sales": 61 10 | }, { 11 | "year": "1957 年\n第一季度", 12 | "sales": 145 13 | }, { 14 | "year": "1958 年\n第一季度", 15 | "sales": 48 16 | }, { 17 | "year": "1959 年\n第一季度", 18 | "sales": 38 19 | }, { 20 | "year": "1960 年\n第一季度", 21 | "sales": 38 22 | }, { 23 | "year": "1962 年\n第一季度", 24 | "sales": 38 25 | }] 26 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Res/mockData_basePie.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name": "芳华", 3 | "percent": 0.4, 4 | "a": "1" 5 | }, { 6 | "name": "妖猫传", 7 | "percent": 0.2, 8 | "a": "1" 9 | }, { 10 | "name": "机器之血", 11 | "percent": 0.18, 12 | "a": "1" 13 | }, { 14 | "name": "心理罪", 15 | "percent": 0.15, 16 | "a": "1" 17 | }, { 18 | "name": "寻梦环游记", 19 | "percent": 0.05, 20 | "a": "1" 21 | }, { 22 | "name": "其他", 23 | "percent": 0.12, 24 | "a": "1" 25 | }] 26 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Res/mockData_multiInterval.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name": "London", 3 | "month": "Jan.", 4 | "value": 18.9 5 | }, { 6 | "name": "London", 7 | "month": "Feb.", 8 | "value": 28.8 9 | }, { 10 | "name": "London", 11 | "month": "Mar.", 12 | "value": 39.3 13 | }, { 14 | "name": "London", 15 | "month": "Apr.", 16 | "value": 81.4 17 | }, { 18 | "name": "London", 19 | "month": "May.", 20 | "value": 47 21 | }, { 22 | "name": "London", 23 | "month": "Jun.", 24 | "value": 20.3 25 | }, { 26 | "name": "London", 27 | "month": "Jul.", 28 | "value": 24 29 | }, { 30 | "name": "London", 31 | "month": "Aug.", 32 | "value": 35.6 33 | }, { 34 | "name": "Berlin", 35 | "month": "Jan.", 36 | "value": 12.4 37 | }, { 38 | "name": "Berlin", 39 | "month": "Feb.", 40 | "value": 23.2 41 | }, { 42 | "name": "Berlin", 43 | "month": "Mar.", 44 | "value": 34.5 45 | }, { 46 | "name": "Berlin", 47 | "month": "Apr.", 48 | "value": 99.7 49 | }, { 50 | "name": "Berlin", 51 | "month": "May.", 52 | "value": 52.6 53 | }, { 54 | "name": "Berlin", 55 | "month": "Jun.", 56 | "value": 35.5 57 | }, { 58 | "name": "Berlin", 59 | "month": "Jul.", 60 | "value": 37.4 61 | }, { 62 | "name": "Berlin", 63 | "month": "Aug.", 64 | "value": 42.4 65 | }] -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Res/mockData_radarArea.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "item": "Design", 3 | "user": "用户 A", 4 | "score": 70 5 | }, { 6 | "item": "Design", 7 | "user": "用户 B", 8 | "score": 30 9 | }, { 10 | "item": "Development", 11 | "user": "用户 A", 12 | "score": 60 13 | }, { 14 | "item": "Development", 15 | "user": "用户 B", 16 | "score": 70 17 | }, { 18 | "item": "Marketing", 19 | "user": "用户 A", 20 | "score": 50 21 | }, { 22 | "item": "Marketing", 23 | "user": "用户 B", 24 | "score": 60 25 | }, { 26 | "item": "Users", 27 | "user": "用户 A", 28 | "score": 40 29 | }, { 30 | "item": "Users", 31 | "user": "用户 B", 32 | "score": 50 33 | }, { 34 | "item": "Test", 35 | "user": "用户 A", 36 | "score": 60 37 | }, { 38 | "item": "Test", 39 | "user": "用户 B", 40 | "score": 70 41 | }, { 42 | "item": "Language", 43 | "user": "用户 A", 44 | "score": 70 45 | }, { 46 | "item": "Language", 47 | "user": "用户 B", 48 | "score": 50 49 | }, { 50 | "item": "Technology", 51 | "user": "用户 A", 52 | "score": 70 53 | }, { 54 | "item": "Technology", 55 | "user": "用户 B", 56 | "score": 40 57 | }, { 58 | "item": "Support", 59 | "user": "用户 A", 60 | "score": 60 61 | }, { 62 | "item": "Support", 63 | "user": "用户 B", 64 | "score": 40 65 | }] 66 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Res/mockData_setionInterval.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "x": "分类一", 3 | "y": [ 76, 100 ] 4 | }, { 5 | "x": "分类二", 6 | "y": [ 56, 108 ] 7 | }, { 8 | "x": "分类三", 9 | "y": [ 38, 129 ] 10 | }, { 11 | "x": "分类四", 12 | "y": [ 58, 155 ] 13 | }, { 14 | "x": "分类五", 15 | "y": [ 45, 120 ] 16 | }, { 17 | "x": "分类六", 18 | "y": [ 23, 99 ] 19 | }, { 20 | "x": "分类七", 21 | "y": [ 18, 56 ] 22 | }, { 23 | "x": "分类八", 24 | "y": [ 18, 34 ] 25 | }] 26 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Res/mockData_singleAreaChart_2.json: -------------------------------------------------------------------------------- 1 | [{"month":"Jan.","value":6.06},{"month":"Feb.","value":82.2},{"month":"Mar.","value":-22.11},{"month":"Apr.","value":21.53},{"month":"May.","value":-21.74},{"month":"Jun.","value":73.61},{"month":"Jul.","value":53.75},{"month":"Aug.","value":60.32}] -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/Res/mockData_singleIntervalChart_under_zero.json: -------------------------------------------------------------------------------- 1 | [{"time":"周一","tem":6.9,"city":"tokyo"},{"time":"周二","tem":9.5,"city":"tokyo"},{"time":"周三","tem":14.5,"city":"tokyo"},{"time":"周四","tem":18.2,"city":"tokyo"},{"time":"周五","tem":21.5,"city":"tokyo"},{"time":"周六","tem":25.2,"city":"tokyo"},{"time":"周日","tem":26.5,"city":"tokyo"},{"time":"周一","tem":-10.8,"city":"newYork"},{"time":"周二","tem":-5.7,"city":"newYork"},{"time":"周三","tem":-11.3,"city":"newYork"},{"time":"周四","tem":-17,"city":"newYork"},{"time":"周五","tem":-22,"city":"newYork"},{"time":"周六","tem":-24.8,"city":"newYork"},{"time":"周日","tem":-24.1,"city":"newYork"},{"time":"周一","tem":2.6,"city":"berlin"},{"time":"周二","tem":3.5,"city":"berlin"},{"time":"周三","tem":8.4,"city":"berlin"},{"time":"周四","tem":13.5,"city":"berlin"},{"time":"周五","tem":17,"city":"berlin"},{"time":"周六","tem":-18.6,"city":"berlin"},{"time":"周日","tem":17.9,"city":"berlin"}] -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/ViewController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface ViewController : UIViewController 4 | 5 | + (NSArray *)demoInfo; 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | Demos 4 | 5 | Created by weiqing.twq on 2022/6/1. 6 | Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | */ 8 | "ChartList" = "ChartList"; 9 | "BaseLineChart" = "BaseLineChart"; 10 | "BaseLineChart2" = "BaseLineChart(Dual Y-axis)"; 11 | "ContrastLineChart" = "ContrastLineChart"; 12 | "BaseAreaChart" = "BaseAreaChart"; 13 | "BaseAreaChart2" = "BaseAreaChart2(with negative value)"; 14 | "BaseAreaChart3" = "BaseAreaChart3(x baseline is not 0)"; 15 | "StackedAreaChart" = "StackedAreaChart"; 16 | "BaseBarChart" = "BaseBarChart"; 17 | "BaseBarChart2" = "BaseBarChart2"; 18 | "GroupBarChart" = "GroupBarChart"; 19 | "GroupBarChart2" = "GroupBarChart2(with negative value)"; 20 | "GroupStackBarChart"="GroupStackBarChart"; 21 | "HistogramBarChart" = "HistogramBarChart"; 22 | "BasePointChart" = "BasePointChart"; 23 | "StripChart" = "StripChart"; 24 | "BasePieChart" = "BasePieChart"; 25 | "CyclicPieChart" = "CyclicPieChart"; 26 | "RadarAreaChart" = "RadarAreaChart"; 27 | "CandleChart" = "CandleChart"; 28 | "TimeSharingChart" = "TimeSharingChart"; 29 | "MarketMovingChart" = "MarketMovingChart"; 30 | "BaseGuideChart" = "BaseGuideChart"; 31 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/main.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import 3 | 4 | int main(int argc, char *argv[]) { 5 | NSString *appDelegateClassName; 6 | @autoreleasepool { 7 | // Setup code that might create autoreleased objects goes here. 8 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 9 | } 10 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 11 | } 12 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseAreaChart.h: -------------------------------------------------------------------------------- 1 | 2 | #import "BaseLineChart.h" 3 | 4 | NS_ASSUME_NONNULL_BEGIN 5 | 6 | @interface BaseAreaChart : BaseLineChart 7 | 8 | @end 9 | 10 | NS_ASSUME_NONNULL_END 11 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseAreaChart2.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseAreaUIView2.h 3 | // F2Native 4 | // 5 | // Created by 青原 on 2020/12/23. 6 | // Copyright © 2020 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "BaseLineChart.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BaseAreaChart2 : BaseLineChart 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseAreaChart2.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseAreaUIView2.m 3 | // F2Native 4 | // 5 | // Created by 青原 on 2020/12/23. 6 | // Copyright © 2020 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "BaseAreaChart2.h" 10 | 11 | @implementation BaseAreaChart2 12 | 13 | - (void)chartRender { 14 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_singleAreaChart_2" ofType:@"json"]; 15 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 16 | self.chart.canvas(self.canvasView).padding(20, 10, 20, 0).source(jsonData); 17 | self.chart.axis(@"tem", @{@"grid": @{@"stroke": @"#000"}}); 18 | 19 | self.chart.line().position(@"month*value"); 20 | self.chart.area().position(@"month*value").fixedColor(@"#1890FF0F"); 21 | 22 | self.chart.scale(@"value", @{@"nice": @(YES)}); 23 | self.chart.animate(@YES); 24 | self.chart.render(); 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseAreaChart3.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseAreaUIView3.h 3 | // F2Native 4 | // 5 | // Created by weiqing.twq on 2021/4/27. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "BaseLineChart.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BaseAreaChart3 : BaseLineChart 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseAreaChart3.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseAreaUIView3.m 3 | // F2Native 4 | // 5 | // Created by weiqing.twq on 2021/4/27. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "BaseAreaChart3.h" 10 | 11 | @implementation BaseAreaChart3 12 | 13 | - (void)chartRender { 14 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_singleAreaChart_2" ofType:@"json"]; 15 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 16 | self.chart.canvas(self.canvasView).padding(20, 10, 20, 0).source(jsonData); 17 | self.chart.axis(@"tem", @{@"grid": @{@"stroke": @"#000"}}); 18 | 19 | self.chart.line().position(@"month*value"); 20 | self.chart.area().position(@"month*value").fixedColor(@"#1890FF0F").style(@{@"startOnZero":@(NO)}); 21 | 22 | self.chart.scale(@"value", @{@"nice": @(YES)}); 23 | self.chart.render(); 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseBarChart.h: -------------------------------------------------------------------------------- 1 | #import "BaseLineChart.h" 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @interface BaseBarChart : BaseLineChart 6 | 7 | @end 8 | 9 | NS_ASSUME_NONNULL_END 10 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseBarChart.m: -------------------------------------------------------------------------------- 1 | #import "BaseBarChart.h" 2 | 3 | @implementation BaseBarChart 4 | 5 | - (void)chartRender { 6 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_baseInterval" ofType:@"json"]; 7 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 8 | self.chart.canvas(self.canvasView).padding(20, 10, 20, 10.f); 9 | self.chart.source([F2Utils toJsonArray:jsonData]); 10 | self.chart.axis(@"year", @{@"grid": @(NO)}); 11 | self.chart.axis(@"sales", @{@"grid": @{@"type": @"dash", @"lineWidth": @(2), @"lineDash": @[@(6), @(2)]}}); 12 | self.chart.scale(@"year", @{@"range": @[@(0.1), @(0.9)]}); 13 | self.chart.scale(@"sales", @{@"nice": @(YES)}); 14 | self.chart.interval().position(@"year*sales").style(@{ 15 | @"rounding": @[@(10), @(10), @(0), @(0)] // [tl, tr, bl, br] 16 | }); 17 | self.chart.tooltip(@{}); 18 | self.chart.animate(@(YES)); 19 | self.chart.render(); 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseBarChart2.h: -------------------------------------------------------------------------------- 1 | #import "BaseLineChart.h" 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @interface BaseBarChart2 : BaseLineChart 6 | 7 | @end 8 | 9 | NS_ASSUME_NONNULL_END 10 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseBarChart2.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseInterval2UIView.m 3 | // Demos 4 | // 5 | // Created by XiaLuo on 2020/11/5. 6 | // Copyright © 2020 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "BaseBarChart2.h" 10 | 11 | @implementation BaseBarChart2 12 | 13 | - (NSString *)jsonData { 14 | return @"[{\"genre\":\"Sports\",\"sold\":275},{\"genre\":\"Strategy\",\"sold\":115},{\"genre\":\"Action\",\"sold\":120},{" 15 | @"\"genre\":\"Shooter\",\"sold\":350},{\"genre\":\"Other\",\"sold\":150}]"; 16 | } 17 | 18 | - (void)chartRender { 19 | self.chart.canvas(self.canvasView); 20 | self.chart.padding(10, 20, 10, 0.f); 21 | self.chart.source([F2Utils toJsonArray:[self jsonData]]); 22 | self.chart.interval().position(@"genre*sold").color(@"genre", @[]); 23 | self.chart.tooltip(@{}); 24 | self.chart.render(); 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseGuideChart.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | #import "BaseLineChart.h" 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | @interface BaseGuideChart : BaseLineChart 8 | @end 9 | 10 | NS_ASSUME_NONNULL_END 11 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseLineChart.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | #import 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | @interface BaseLineChart : UIView 8 | 9 | @property (nonatomic, strong, readonly) F2CanvasView *canvasView; 10 | @property (nonatomic, strong, readonly) F2Chart *chart; 11 | 12 | @end 13 | 14 | NS_ASSUME_NONNULL_END 15 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseLineChart2.h: -------------------------------------------------------------------------------- 1 | 2 | #import "BaseLineChart.h" 3 | 4 | NS_ASSUME_NONNULL_BEGIN 5 | 6 | @interface BaseLineChart2 : BaseLineChart 7 | 8 | @end 9 | 10 | NS_ASSUME_NONNULL_END 11 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BaseLineChart2.m: -------------------------------------------------------------------------------- 1 | 2 | #import "BaseLineChart2.h" 3 | 4 | @implementation BaseLineChart2 5 | 6 | - (void)chartRender { 7 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_multiAxiesLine" ofType:@"json"]; 8 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 9 | self.chart.syncYScale(NO); 10 | self.chart.canvas(self.canvasView).padding(20, 10, 20, 0.f).source(jsonData); 11 | self.chart.scale(@"date", @{@"tickCount": @(5)}); 12 | self.chart.scale(@"value", @{@"nice": @(YES)}); 13 | self.chart.scale(@"offset", @{@"nice": @(YES)}); 14 | self.chart.axis(@"value", @{@"grid": @{@"type": @"dash", @"dash": @[@(15), @(15), @(5), @(5)]}}); 15 | self.chart.axis(@"offset", @{@"label": @{@"labelOffset": @(10), @"textAlign": @"start"}}); 16 | self.chart.axis(@"date", @{ 17 | @"label": @{ 18 | @"labelOffset": @(5), 19 | } 20 | }); 21 | self.chart.line().position(@"date*value").fixedSize(2).fixedColor(@"#1890FF"); 22 | self.chart.line().position(@"date*offset").fixedSize(2).fixedColor(@"#2FC25B"); 23 | self.chart.tooltip(@{}); 24 | self.chart.render(); 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BasePieChart.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import "BaseLineChart.h" 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | @interface BasePieChart : BaseLineChart 8 | 9 | @end 10 | 11 | NS_ASSUME_NONNULL_END 12 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BasePieChart.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import "BasePieChart.h" 4 | 5 | @implementation BasePieChart 6 | 7 | - (void)chartRender { 8 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_basePie" ofType:@"json"]; 9 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 10 | self.chart.canvas(self.canvasView).padding(0, 0, 0, 0.f); 11 | self.chart.source([F2Utils toJsonArray:jsonData]); 12 | self.chart.axis(@"percent", @{@"line": @(NO), @"label": @(NO), @"grid": @(NO)}); 13 | self.chart.axis(@"a", @{@"line": @(NO), @"label": @(NO) , @"grid": @(NO)}); 14 | self.chart.coord(@{@"type": @"polar", @"transposed": @(YES)}); 15 | self.chart.interval().position(@"a*percent").color(@"name", @[]).adjust(@"stack").fixedSize(1).style(@{@"lineWidth": @(1),@"stroke": @"#ffffff"}); 16 | self.chart.animate(@YES); 17 | self.chart.render(); 18 | } 19 | @end 20 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BasePointChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // BasePointUIView.h 3 | // F2Native 4 | // 5 | // Created by 青原 on 2021/1/4. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "BaseLineChart.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface BasePointChart : BaseLineChart 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/BasePointChart.m: -------------------------------------------------------------------------------- 1 | // 2 | // BasePointUIView.m 3 | // F2Native 4 | // 5 | // Created by 青原 on 2021/1/4. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "BasePointChart.h" 10 | 11 | @implementation BasePointChart 12 | 13 | - (void)chartRender { 14 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_singlePointChart" ofType:@"json"]; 15 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 16 | self.chart.canvas(self.canvasView).padding(20, 10, 20, 0.f).source(jsonData); 17 | self.chart.point().position(@"x*y").size(@"z", @[@(3), @(10)]).fixedShape(@"circle"); 18 | self.chart.animate(@YES); 19 | self.chart.render(); 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/CandleChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // KLineUIView.h 3 | // F2Native 4 | // 5 | // Created by XiaLuo on 2021/1/14. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "BaseLineChart.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface CandleChart : BaseLineChart 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/ContrastLineChart.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import "BaseLineChart.h" 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | @interface ContrastLineChart : BaseLineChart 8 | 9 | @end 10 | 11 | NS_ASSUME_NONNULL_END 12 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/ContrastLineChart.m: -------------------------------------------------------------------------------- 1 | 2 | #import "ContrastLineChart.h" 3 | 4 | @implementation ContrastLineChart 5 | 6 | - (void)chartRender { 7 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_multiLines" ofType:@"json"]; 8 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 9 | self.chart.canvas(self.canvasView).padding(20, 10, 20, 0.f); 10 | self.chart.source([F2Utils toJsonArray:jsonData]); 11 | self.chart.scale(@"value", @{@"nice": @(YES)}); 12 | self.chart.scale(@"date", @{@"tickCount": @(5)}); 13 | self.chart.axis(@"date", @{@"label": @{@"textAlign": @"center"}}); 14 | self.chart.line().position(@"date*value").color(@"type", @[]).fixedSize(2).fixedShape(@"smooth"); 15 | self.chart.legend(@"type", @{@"radius": @(3), @"symbol": @"square"}); 16 | self.chart.tooltip(@{}); 17 | self.chart.render(); 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/CyclicPieChart.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import "BaseLineChart.h" 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | @interface CyclicPieChart : BaseLineChart 8 | 9 | @end 10 | 11 | NS_ASSUME_NONNULL_END 12 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/CyclicPieChart.m: -------------------------------------------------------------------------------- 1 | 2 | #import "CyclicPieChart.h" 3 | 4 | @implementation CyclicPieChart 5 | 6 | - (void)chartRender { 7 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_basePie" ofType:@"json"]; 8 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 9 | self.chart.canvas(self.canvasView).padding(0, 0, 0, 0.f).source(jsonData); 10 | self.chart.axis(@"percent", @{@"line": @(NO), @"label": @(NO), @"grid": @(NO)}); 11 | self.chart.axis(@"a", @{@"line": @(NO), @"label": @(NO), @"grid": @(NO)}); 12 | self.chart.coord(@{@"type": @"polar"}); 13 | self.chart.interval().style(@{@"lineWidth": @(0)}).position(@"a*percent").color(@"name", @[]).adjust(@"stack"); 14 | self.chart.animate(@YES); 15 | self.chart.render(); 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/GroupBarChart.h: -------------------------------------------------------------------------------- 1 | #import "BaseLineChart.h" 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @interface GroupBarChart : BaseLineChart 6 | 7 | @end 8 | 9 | NS_ASSUME_NONNULL_END 10 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/GroupBarChart.m: -------------------------------------------------------------------------------- 1 | #import "GroupBarChart.h" 2 | 3 | @implementation GroupBarChart 4 | 5 | - (void)chartRender { 6 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_multiInterval" ofType:@"json"]; 7 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 8 | self.chart.canvas(self.canvasView).padding(15, 15, 15, 15.f); 9 | self.chart.source([F2Utils toJsonArray:jsonData]); 10 | self.chart.axis(@"month", @{@"grid": @(NO)}); 11 | self.chart.scale(@"month", @{@"range": @[@(0.1), @(0.9)]}); 12 | self.chart.scale(@"value", @{@"nice": @(YES)}); 13 | self.chart.interval().adjust(@"dodge").position(@"month*value").color(@"name", @[]); 14 | self.chart.tooltip(@{}); 15 | self.chart.legend(@"name", @{@"position": @"bottom", @"align": @"center"}); 16 | self.chart.render(); 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/GroupBarChart2.h: -------------------------------------------------------------------------------- 1 | // 2 | // MultiIntervalUIView2.h 3 | // F2Native 4 | // 5 | // Created by 青原 on 2020/12/22. 6 | // Copyright © 2020 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "BaseLineChart.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface GroupBarChart2 : BaseLineChart 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/GroupBarChart2.m: -------------------------------------------------------------------------------- 1 | // 2 | // MultiIntervalUIView2.m 3 | // F2Native 4 | // 5 | // Created by 青原 on 2020/12/22. 6 | // Copyright © 2020 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "GroupBarChart2.h" 10 | 11 | @implementation GroupBarChart2 12 | 13 | - (void)chartRender { 14 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_singleIntervalChart_under_zero" ofType:@"json"]; 15 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 16 | self.chart.canvas(self.canvasView).padding(20, 10, 20, 0); 17 | self.chart.source([F2Utils toJsonArray:jsonData]); 18 | self.chart.axis(@"tem", @{@"grid": @{@"stroke": @"#000"}}); 19 | self.chart.interval().position(@"time*tem").color(@"city", @[]).adjust(@"dodge"); 20 | self.chart.scale(@"time", @{@"range": @[@(0.1), @(0.9)]}); 21 | self.chart.scale(@"tem", @{@"nice": @(YES)}); 22 | self.chart.tooltip(@{}); 23 | self.chart.render(); 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/GroupStackBarChart.h: -------------------------------------------------------------------------------- 1 | #import "BaseLineChart.h" 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @interface GroupStackBarChart : BaseLineChart 6 | 7 | @end 8 | 9 | NS_ASSUME_NONNULL_END 10 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/GroupStackBarChart.m: -------------------------------------------------------------------------------- 1 | #import "GroupStackBarChart.h" 2 | 3 | @implementation GroupStackBarChart 4 | 5 | - (void)chartRender { 6 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_multiInterval" ofType:@"json"]; 7 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 8 | self.chart.canvas(self.canvasView).padding(20, 10, 20, 0.f).source(jsonData); 9 | self.chart.axis(@"month", @{@"grid": @(NO)}); 10 | self.chart.scale(@"month", @{@"range": @[@(0.1), @(0.9)]}); 11 | self.chart.scale(@"value", @{@"nice": @(YES)}); 12 | self.chart.interval().adjust(@"stack").position(@"month*value").color(@"name", @[]); 13 | self.chart.render(); 14 | } 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/HistogramBarChart.h: -------------------------------------------------------------------------------- 1 | #import "BaseLineChart.h" 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @interface HistogramBarChart : BaseLineChart 6 | 7 | @end 8 | 9 | NS_ASSUME_NONNULL_END 10 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/HistogramBarChart.m: -------------------------------------------------------------------------------- 1 | 2 | #import "HistogramBarChart.h" 3 | 4 | @implementation HistogramBarChart 5 | 6 | - (void)chartRender { 7 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_setionInterval" ofType:@"json"]; 8 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 9 | self.chart.canvas(self.canvasView).padding(20, 10, 20, 0.f).source(jsonData); 10 | self.chart.axis(@"x", @{@"grid": @(NO)}); 11 | self.chart.axis(@"y", @{@"grid": @{@"type": @"dash", @"lineWidth": @(2), @"lineDash": @[@(6), @(2)]}}); 12 | self.chart.scale(@"x", @{@"range": @[@(0.1), @(0.9)]}); 13 | self.chart.scale(@"y", @{@"nice": @(YES)}); 14 | self.chart.interval().position(@"x*y"); 15 | self.chart.render(); 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/MarketMovingChart.h: -------------------------------------------------------------------------------- 1 | #import "BaseLineChart.h" 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @interface MarketMovingChart : BaseLineChart 6 | 7 | @end 8 | 9 | NS_ASSUME_NONNULL_END 10 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/RadarAreaChart.h: -------------------------------------------------------------------------------- 1 | // 2 | // RadarAreaUIView.h 3 | // F2Native 4 | // 5 | // Created by weiqing.twq on 2021/9/16. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "BaseLineChart.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface RadarAreaChart : BaseLineChart 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/StackedAreaChart.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import "BaseLineChart.h" 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | @interface StackedAreaChart : BaseLineChart 8 | 9 | @end 10 | 11 | NS_ASSUME_NONNULL_END 12 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/StackedAreaChart.m: -------------------------------------------------------------------------------- 1 | #import "StackedAreaChart.h" 2 | 3 | @implementation StackedAreaChart 4 | 5 | - (void)chartRender { 6 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_multiArea" ofType:@"json"]; 7 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 8 | self.chart.canvas(self.canvasView).padding(20, 10, 20, 0.f); 9 | self.chart.source([F2Utils toJsonArray:jsonData]); 10 | self.chart.scale(@"date", @{@"tickCount": @(5)}); 11 | self.chart.scale(@"value", @{@"min": @(0)}); 12 | self.chart.axis(@"date", @{@"grid": @(NO), @"label": @{@"textAlign": @"start"}}); 13 | self.chart.line().adjust(@"stack").position(@"date*value").color(@"city", @[]).fixedSize(2); 14 | self.chart.area().adjust(@"stack").position(@"date*value").color(@"city", @[]).fixedSize(2); 15 | self.chart.tooltip(@{}); 16 | self.chart.render(); 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/StripChart.h: -------------------------------------------------------------------------------- 1 | 2 | #import "BaseLineChart.h" 3 | 4 | NS_ASSUME_NONNULL_BEGIN 5 | 6 | @interface StripChart : BaseLineChart 7 | 8 | @end 9 | 10 | NS_ASSUME_NONNULL_END 11 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/StripChart.m: -------------------------------------------------------------------------------- 1 | 2 | #import "StripChart.h" 3 | 4 | @implementation StripChart 5 | 6 | - (void)chartRender { 7 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/mockData_baseInterval" ofType:@"json"]; 8 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 9 | self.chart.canvas(self.canvasView).padding(20, 10, 20, 0.f).source(jsonData); 10 | self.chart.coord(@{@"transposed": @(YES)}); 11 | self.chart.scale(@"sales", @{@"min": @(0)}); 12 | self.chart.scale(@"year", @{@"range": @[@(0.1), @(0.9)]}); 13 | self.chart.interval().position(@"year*sales"); 14 | self.chart.render(); 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/TimeSharingChart.h: -------------------------------------------------------------------------------- 1 | 2 | #import "BaseLineChart.h" 3 | 4 | NS_ASSUME_NONNULL_BEGIN 5 | 6 | @interface TimeSharingChart : BaseLineChart 7 | 8 | @end 9 | 10 | NS_ASSUME_NONNULL_END 11 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/bugfix/KLineTrendBugFix1.h: -------------------------------------------------------------------------------- 1 | /** 2 | 解决大盘异动旗子的布局问题 3 | */ 4 | 5 | #import "BaseLineChart.h" 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | @interface KLineTrendBugFix1 : BaseLineChart 10 | 11 | @end 12 | 13 | NS_ASSUME_NONNULL_END 14 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/bugfix/KLineTrendBugFix1.m: -------------------------------------------------------------------------------- 1 | // 2 | // MarketMovingBugFix1.m 3 | // F2Native 4 | // 5 | // Created by weiqing.twq on 2022/2/23. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "KLineTrendBugFix1.h" 10 | 11 | @implementation KLineTrendBugFix1 12 | 13 | -(instancetype)initWithFrame:(CGRect)frame { 14 | CGRect chartFrame = CGRectMake(0, 0, frame.size.width, 280); 15 | if (self = [super initWithFrame:chartFrame]) {} 16 | return self; 17 | } 18 | 19 | - (void)chartRender { 20 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/bugfix/kline_trend" ofType:@"json"]; 21 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 22 | NSDictionary *jsonDict = [F2Utils toJsonObject:jsonData]; 23 | FunctionItemCallback callback = ^NSDictionary *_Nonnull(NSString *_Nonnull functionId, NSDictionary *_Nonnull param) { 24 | return param; 25 | }; 26 | self.chart.canvas(self.canvasView).padding(15, 10, 15, 0.f).callback(callback); 27 | self.chart.config(jsonDict); 28 | self.chart.render(); 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/bugfix/MarketMovingBugFix1.h: -------------------------------------------------------------------------------- 1 | /** 2 | 解决大盘异动旗子的布局问题 3 | */ 4 | 5 | #import "BaseLineChart.h" 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | @interface MarketMovingBugFix1 : BaseLineChart 10 | 11 | @end 12 | 13 | NS_ASSUME_NONNULL_END 14 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/bugfix/MarketMovingBugFix1.m: -------------------------------------------------------------------------------- 1 | // 2 | // MarketMovingBugFix1.m 3 | // F2Native 4 | // 5 | // Created by weiqing.twq on 2022/2/23. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "MarketMovingBugFix1.h" 10 | 11 | @implementation MarketMovingBugFix1 12 | 13 | - (void)chartRender { 14 | NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Res/bugfix/market_trend" ofType:@"json"]; 15 | NSString *jsonData = [NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]; 16 | NSDictionary *jsonDict = [F2Utils toJsonObject:jsonData]; 17 | FunctionItemCallback callback = ^NSDictionary *_Nonnull(NSString *_Nonnull functionId, NSDictionary *_Nonnull param) { 18 | return param; 19 | }; 20 | self.chart.canvas(self.canvasView).padding(15, 10, 15, 0.f).callback(callback); 21 | NSTimeInterval start = [[NSDate date] timeIntervalSince1970] * 1000; 22 | self.chart.config(jsonDict); 23 | NSTimeInterval end = [[NSDate date] timeIntervalSince1970] * 1000; 24 | NSLog(@"config parse cost %fms", (end - start)); 25 | self.chart.render(); 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/views/bugfix/TimeSharingBugFix1.h: -------------------------------------------------------------------------------- 1 | /** 2 | 折线太贴近顶端导致折线部分被裁,业务在chart加top padding临时解决下,引擎侧后续看下这个问题 3 | */ 4 | 5 | #import "BaseLineChart.h" 6 | 7 | NS_ASSUME_NONNULL_BEGIN 8 | 9 | @interface TimeSharingBugFix1 : BaseLineChart 10 | 11 | @end 12 | 13 | NS_ASSUME_NONNULL_END 14 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/zh-HK.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/zh-Hans.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /demos/ios/Demos/Demos/zh-Hans.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | Demos 4 | 5 | Created by weiqing.twq on 2022/6/1. 6 | Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | */ 8 | "ChartList" = "多图列表"; 9 | "BaseLineChart" = "基础折线图"; 10 | "BaseLineChart2" = "基础折线图(双Y轴)"; 11 | "ContrastLineChart" = "对比折线图"; 12 | "BaseAreaChart" = "基础面积图"; 13 | "BaseAreaChart2" = "基础面积图2(带负值)"; 14 | "BaseAreaChart3" = "基础面积图2(x基线不为0)"; 15 | "StackedAreaChart" = "层叠面积图"; 16 | "BaseBarChart" = "基础柱状图"; 17 | "BaseBarChart2" = "基础柱状图2"; 18 | "GroupBarChart" = "分组柱状图"; 19 | "GroupBarChart2" = "分组柱状图2(带负值)"; 20 | "GroupStackBarChart"="分组层叠柱状图"; 21 | "HistogramBarChart" = "区间柱状图"; 22 | "BasePointChart" = "散点图"; 23 | "StripChart" = "条状图"; 24 | "BasePieChart" = "饼图"; 25 | "CyclicPieChart" = "环形饼图"; 26 | "RadarAreaChart" = "雷达面积图"; 27 | "CandleChart" = "蜡烛图(日K)"; 28 | "TimeSharingChart" = "股票分时图"; 29 | "MarketMovingChart" = "大盘异动"; 30 | "BaseGuideChart" = "辅助组件"; 31 | -------------------------------------------------------------------------------- /demos/ios/Demos/F2Native.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /demos/ios/Demos/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '13.0' 2 | 3 | target "F2Native" do 4 | pod 'F2' 5 | end 6 | 7 | -------------------------------------------------------------------------------- /demos/videos/ios_demo.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/videos/ios_demo.mp4 -------------------------------------------------------------------------------- /demos/webassembly/f2wasm.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/demos/webassembly/f2wasm.wasm -------------------------------------------------------------------------------- /demos/webassembly/run.sh: -------------------------------------------------------------------------------- 1 | python3 -m http.server 8083 2 | -------------------------------------------------------------------------------- /docs/api/F2Area.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: F2Area 3 | order: 5 4 | --- 5 | 6 | Graphics area object, used to draw area extents 7 | 8 | ## Create F2Area Instance 9 | #### iOS 10 | ````obj-c 11 | chart.area(); 12 | ```` 13 | 14 | #### Android 15 | ````java 16 | chart.area(); 17 | ```` 18 |
19 | 20 | ## Method 21 | ### - Position 22 | draw area location 23 | #### iOS 24 | ````obj-c 25 | chart.area().position(@"date*value"); 26 | ```` 27 | #### Android 28 | ````java 29 | chart.area().position("date*value"); 30 | ```` 31 | - parameters 32 | 33 | | **Attribute Name** | **Type** | **Explanation** | 34 | | --- | --- | --- | 35 | | `attr`| String | X*Y: The corresponding name of the drawn area in the source 36 | 37 |
38 | 39 | ### - FixedColor 40 | Set the color of the uniform area fill 41 | #### iOS 42 | ````obj-c 43 | chart.area().fixedColor(@"#108EE9"); 44 | ```` 45 | #### Android 46 | ````java 47 | chart.area().fixedColor("#108EE9"); 48 | ```` 49 | - parameters 50 | 51 | | **Attribute Name** | **Type** | **Explanation** | 52 | | --- | --- | --- | 53 | | `attr`| String | Set the color of the area fill (Hex rgba) -------------------------------------------------------------------------------- /docs/api/F2Area.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: F2Area 3 | order: 5 4 | --- 5 | 6 | 图形区域对象,用于绘制区域范围 7 | 8 | ## 创建 F2Area 实例 9 | 10 | ``` 11 | chart.area(); 12 | ``` 13 |
14 | 15 | ## 方法 16 | ### - position 17 | ``` 18 | chart.area().position("date*value"); 19 | ``` 20 | - 参数 21 | 22 | | **属性名** | **类型** | **解释** | 23 | | --- | --- | --- | 24 | | `attr`| String | X*Y:绘制的区域在source中对应的名称 25 | 26 |
27 | 28 | ### - fixedColor 29 | 设置统一的区域填充的颜色 30 | ``` 31 | chart.area().fixedColor("#108EE9"); 32 | ``` 33 | - 参数 34 | 35 | | **属性名** | **类型** | **解释** | 36 | | --- | --- | --- | 37 | | `attr`| String | 设置区域填充的颜色 (Hex rgba) 38 | -------------------------------------------------------------------------------- /docs/tutorial/manual/coordinate.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 坐标系 3 | order: 6 4 | --- 5 | 6 | 坐标系是将两种位置标度结合在一起组成的 2 维定位系统,描述了数据是如何映射到图形所在的平面。 7 | 8 | F2Native 提供了直角坐标系和极坐标两种类型,目前所有的坐标系均是 2 维的。 9 | 10 | ## 如何设置坐标系 11 | 12 | F2Native 默认提供的坐标系类型为笛卡尔坐标系,当需要切换坐标系时,可以通过调用下面的语法声明需要使用的坐标系: 13 | 14 | ``` obj-c 15 | chart.coord(@{@"type": @"polar", @"transposed": @(YES)}); 16 | ``` 17 | 18 | | **坐标系类型** | **说明** | 19 | | --- | --- | 20 | | `rect` | 直角坐标系,目前仅支持二维,由 x, y 两个互相垂直的坐标轴构成。 | 21 | | `polar` | 极坐标系,由角度和半径 2 个维度构成。 | 22 | 23 | 24 | ## 坐标系类型及配置 25 | 26 | 坐标系可以分为笛卡尔坐标系和非笛卡尔坐标系,非笛卡尔坐标系即极坐标,由角度和半径这两个维度来确定位置。 27 | 28 | 利用极坐标可生成饼图、玫瑰图和雷达图等,较适用于周期性数据的可视化场景,比如时间和方向数据。 29 | 30 | 坐标系类型的变换会改变几何标记的形状,比如在极坐标系中,矩形将变为圆环的一部分。 31 | 32 | 33 | ### 坐标系配置 34 | 35 | #### 直角坐标系 36 | 37 | ``` 38 | // 声明直角坐标系 39 | // 直角坐标系转置 40 | chart.coord(@{@"type": @"rect", @"transposed": @(YES)}); 41 | ``` 42 | 43 | #### 极坐标 44 | 45 | ``` 46 | chart.coord(@{ 47 | @"type": @"polar", // 声明极坐标系 48 | @"transposed": @(YES) // 转置 49 | }); 50 | ``` 51 | 52 | 这里需要说明的是,F2Native 极坐标默认的起始角度和结束角度如下图所示: 53 | 54 | ![](https://zos.alipayobjects.com/skylark/85950a42-9579-44cb-b656-8dd28c9a014a/attach/2378/d648679184c6977c/image.png#width=) 55 | -------------------------------------------------------------------------------- /docs/tutorial/manual/data.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 数据 3 | order: 2 4 | --- 5 | 6 | 数据是绘制一张图表最基本的部分。F2Native 支持的数据格式为 jsonString: 7 | 8 | ``` json 9 | [{"genre":"Sports", "sold":275}, 10 | {"genre":"Strategy","sold":115}, 11 | {"genre":"Action","sold":120}, 12 | {"genre":"Shooter","sold":350}, 13 | {"genre":"Other","sold":150}] 14 | ``` 15 | 16 | ## 如何装载数据 17 | 18 | 当 chart 实例创建完毕之后,通过调用以下接口装载数据: 19 | 20 | ``` 21 | chart.source(data); 22 | ``` 23 | 24 | ## 如何更新数据 25 | 26 | 27 | 1. 更新图表数据。 28 | 29 | ``` 30 | chart.source(data); 31 | ``` 32 | 33 | 2.在需要更新图表的时机调用重绘方法。 34 | 35 | ``` 36 | chart.source(newData); // 更新数据源 37 | 38 | // do something 39 | 40 | chart.repaint(); // 更新图表! 41 | ``` 42 | 43 | 3. 更新数据时还可以重新定义图形语法,改变图表类型和各种配置。 44 | 45 | ``` 46 | chart.source(newData); // 加载新数据 47 | chart.interval().position('x*y').color('z'); // 重新定义图形语法组合 48 | chart.repaint(); 49 | ``` 50 | 51 | ## 特殊图表的数据说明 52 | 53 | ### 饼图 54 | 55 | 绘制饼图时,数据集中的每一条记录中**必须包含一个常量字段(并且必须是字符串类型)**,如下所示: 56 | 57 | ```json 58 | [ 59 | { "name": "芳华", "percent": 0.4, "a": "1" }, 60 | { "name": "妖猫传", "percent": 0.2, "a": "1" }, 61 | { "name": "机器之血", "percent": 0.18, "a": "1"}, 62 | { "name": "心理罪", "percent": 0.15, "a": "1" }, 63 | { "name": "寻梦环游记", "percent": 0.05, "a": "1" }, 64 | { "name": "其他", "percent": 0.02, "a": "1" } 65 | ] 66 | ``` 67 | 68 | 详见饼图[示例](/zh/examples/pie/basic)。 69 | -------------------------------------------------------------------------------- /docs/tutorial/manual/grammar.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 图形语法 3 | order: 0 4 | --- 5 | 6 | F2Native 同 G2 一样,基于《The Grammar of Graphics》(Leland Wilkinson 著)一书所提的图形理论。该理论是一套用来描述所有统计图形深层特性的语法规则,该语法回答了『什么是统计图形』这一问题,以自底向上的方式组织最基本的元素形成更高级的元素。 7 | 8 | 所以对于 F2Native 来说,**没有具体的图表类型的概念,所有的图表都是通过组合不同的图形语法元素形成的**,这些图形语法元素包括: 9 | 10 | - 最基础的部分是你想要可视化的[数据](./data)以及一系列将数据中的变量对应到[图形属性](./attribute)的映射; 11 | 12 | - [几何标记](./geometry),可以理解为你在图表中实际看到的图形元素,如点、线、多边形等,每个几何标记对象含有多个图形属性,F2Native 图形语法的核心就是建立数据中的一系列变量到图形属性的映射; 13 | 14 | - [度量](./scale),作为数据空间到图形属性空间的转换桥梁,每一个图形属性都对应着一个或者多个度量; 15 | 16 | - [坐标系](./coordinate),描述了数据是如何映射到图形所在的平面的,一个几何标记在不同坐标系下会有不同的表现。目前 F2Native 提供了笛卡尔坐标系、极坐标系两种坐标系; 17 | 18 | - 辅助元素是为了增强图表的可读性和可理解性,F2Native 中的辅助元素包含坐标轴 Axis、图例 Legend、提示信息 Tooltip、静态辅助标记 Guide。 19 | 20 | 21 | 所以,在 F2Native 中,我们通常这么描述一张图表:一张图表就是从数据到几何标记对象的图形属性的一个映射,此外图形中还可能包含数据的统计变换,最后绘制在某个特定的坐标系中。 22 | 23 | 更多内容请阅读以下篇章: 24 | 25 | - [图表组成](./understanding) 26 | 27 | - [数据](./data) 28 | 29 | - [度量](./scale) 30 | 31 | - [几何标记](./geometry) 32 | 33 | - [图形属性](./attribute) 34 | 35 | - [坐标系](./coordinate) 36 | 37 | 38 | -------------------------------------------------------------------------------- /docs/tutorial/manual/understanding.zh.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 图表组成 3 | order: 1 4 | --- 5 | 6 | 为了更好得使用 F2Native 进行数据可视化,我们需要了解 F2Native 图表的组成以及相关术语。 7 | 8 | ## 图表部件 9 | 10 | 一般情况下,F2Native 的图表包含坐标轴(Axis)、几何标记(Geometry)、提示信息(Tooltip)、图例(Legend)等,另外还可以包括辅助标记(Guide)、数据标签(dataLabels)等。 11 | 12 | F2Native 基本组成部分如下图所示: 13 | 14 | ![](https://gw.alipayobjects.com/zos/rmsportal/tpfdzWDYmxzHkquTihJe.png#width=600) ![](https://gw.alipayobjects.com/zos/rmsportal/lUqXwLjgRWhugemcNsqc.png#width=600) 15 | 16 | ## 术语 17 | | **术语** | **英文** | **描述** | 18 | | --- | --- | --- | 19 | | 坐标轴 | Axis | 每个图表通常包含两个坐标轴,在直角坐标系(笛卡尔坐标系)下,分别为 x 轴和 y 轴,在极坐标轴下,则分别由角度和半径 2 个维度构成。每个坐标轴由坐标轴线(line)、刻度线(tickLine)、刻度文本(label)以及网格线(grid)组成。 | 20 | | 图例 | Legend | 图例作为图表的辅助元素,用于标定不同的数据类型以及数据的范围,用于辅助阅读图表以及帮助用户在图表中进行数据的筛选过滤。 | 21 | | 几何标记 | Geometry | 即我们所说的点、线、面这些几何图形,在图形语法 中几何标记的类型决定了生成图表的类型。也就是数据被可视化后的实际表现,不同的几何标记都包含对应的图形属性。 | 22 | | 图形属性 | Attribute | 图形属性对应视觉编码中的视觉通道,是图形语法元素非常重要和灵活的一部分,不同的几何标记拥有自己的图形属性,F2Native 提供了位置(position)、颜色(color)、大小(size)、形状(shape)这四种图形属性。 | 23 | | 坐标系 | Coordinate | 坐标系是将两种位置标度结合在一起组成的 2 维定位系统,描述了数据是如何映射到图形所在的平面。 | 24 | | 提示信息 | Tooltip | 当鼠标悬停在某个点上时,会以提示框的形式显示当前点对应的数据的信息,比如该点的值,数据单位等,帮助用户从图表中获取具体的数据信息。 | 25 | | 辅助标记 | Guide | 当需要在图表上绘制一些辅助线、辅助框或者文本时,比如增加预警线、最高值线或者标示明显的范围区域时,辅助标记 Guide 是非常有用的工具。 | 26 | 27 | -------------------------------------------------------------------------------- /externals.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.less'; 2 | -------------------------------------------------------------------------------- /gatsby-browser.js: -------------------------------------------------------------------------------- 1 | window.react = require('react'); 2 | window.reactDom = require('react-dom'); 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jan 27 10:21:44 CST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /ios/F2/F2-Prefix.pch: -------------------------------------------------------------------------------- 1 | 2 | #define TARGET_STANDALONE 1 3 | 4 | #define JSON_NOEXCEPTION 1 5 | -------------------------------------------------------------------------------- /ios/F2/F2.h: -------------------------------------------------------------------------------- 1 | #ifndef F2_H 2 | #define F2_H 3 | 4 | //objc headers 5 | #import 6 | #import 7 | #import 8 | #import 9 | #import 10 | #import 11 | 12 | #endif /* F2_H */ 13 | -------------------------------------------------------------------------------- /ios/F2/F2Callback.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | NS_ASSUME_NONNULL_BEGIN 4 | typedef NSDictionary *_Nonnull(^ItemCallback)(NSDictionary *_Nonnull param); 5 | 6 | typedef NSDictionary *_Nonnull(^FunctionItemCallback)(NSString *_Nonnull functionId, NSDictionary *_Nonnull param); 7 | 8 | @interface F2Callback : NSObject 9 | 10 | @property (nonatomic, copy, readonly) NSString *functionId; 11 | 12 | + (instancetype)callback:(ItemCallback)block; 13 | 14 | - (NSDictionary *)execute:(NSDictionary *)param; 15 | 16 | @end 17 | 18 | @interface F2RequestAnimationFrameHandle : F2Callback 19 | 20 | + (instancetype)initWithF2Chart:(id)chart canvas:(id)canvasView; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /ios/F2/F2CanvasContext.h: -------------------------------------------------------------------------------- 1 | // 2 | // F2CoreGraphicsCanvasContext.h 3 | // F2 4 | // 5 | // Created by weiqing.twq on 2021/12/8. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface F2CanvasContext : NSObject 15 | 16 | /// 创建渲染的canvas, 内部会创建CGContextRef 17 | /// @param size canvas的size 18 | - (instancetype)initWithSize:(CGSize)size; 19 | 20 | /// 如果画布的大小与之前的不同,则更新画布的大小 21 | /// @param size 画布的大小 22 | - (void)changeSize:(CGSize)size; 23 | 24 | ///获取C++的context对象 25 | ///@return CGContextRef 渲染的上下文 26 | - (CGContextRef)context2d; 27 | 28 | /// 画布 29 | /// @return CGImageRef bitmap 30 | - (CGImageRef)bitmap; 31 | 32 | /// 返回画布的密度 33 | - (CGFloat)nativeScale; 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /ios/F2/F2Coordinate.h: -------------------------------------------------------------------------------- 1 | // 2 | // F2Coordinate.h 3 | // F2 4 | // 5 | // Created by weiqing.twq on 2021/11/13. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | //笛卡尔坐标系 15 | /* 16 | |----------------------end 17 | | | 18 | | | 19 | | | 20 | | | 21 | start--------------------- 22 | */ 23 | 24 | //极坐标系 25 | /* 26 | |--------------end 27 | | | 28 | | | 29 | | center | 30 | | | 31 | | | 32 | start-------------- 33 | 34 | */ 35 | 36 | @interface F2Coordinate : NSObject 37 | 38 | - (instancetype)initWithCoordinate:(void *)coord; 39 | 40 | //获取极坐标系的中心点 41 | - (CGPoint (^)(void))getCenter; 42 | 43 | //坐标系左下角的点 44 | - (CGPoint (^)(void))getStart; 45 | 46 | //坐标系右上角的点 47 | - (CGPoint (^)(void))getEnd; 48 | 49 | //获取坐标系的宽度 50 | - (CGFloat (^)(void))getWidth; 51 | 52 | //获取坐标系的高度 53 | - (CGFloat (^)(void))getHeight; 54 | 55 | @end 56 | 57 | NS_ASSUME_NONNULL_END 58 | -------------------------------------------------------------------------------- /ios/F2/F2GestureListener.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | #import 4 | 5 | NS_ASSUME_NONNULL_BEGIN 6 | 7 | typedef void (^F2GestureCallback)(NSDictionary *_Nonnull info); 8 | 9 | @interface F2GestureListener : NSObject 10 | @property (nonatomic, strong) UILongPressGestureRecognizer *longGesture; 11 | @property (nonatomic, strong) UIPanGestureRecognizer *panGesture; 12 | @property (nonatomic, strong) UIPinchGestureRecognizer *pinchGesture; 13 | @property (nonatomic, copy) F2GestureCallback longGestureCallback; 14 | @property (nonatomic, copy) F2GestureCallback panGestureCallback; 15 | @property (nonatomic, copy) F2GestureCallback pinchGestureCallback; 16 | 17 | - (instancetype)initWithView:(UIView *)view; 18 | 19 | - (void)addLongPressGesture:(F2GestureCallback)callback; 20 | - (void)addPinchGesture:(F2GestureCallback)callback; 21 | - (void)addPanGesture:(F2GestureCallback)callback; 22 | 23 | - (void)removeLongPressGesture; 24 | - (void)removePinchGesture; 25 | - (void)removePanGesture; 26 | 27 | - (void)removeAllGestures; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /ios/F2/F2Guide.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | NS_ASSUME_NONNULL_BEGIN 4 | 5 | @interface F2Guide : NSObject 6 | 7 | - (instancetype)initWithGuide:(void *)guide; 8 | 9 | /// 创建旗子,config格式如下 10 | /// @{ @"position": @[@(x轴的值), @(y轴的值)], @"content": @"内容",@"padding": @(2) } 11 | - (F2Guide * (^)(NSDictionary *config))flag; 12 | 13 | /// 创建文字,config格式如下 14 | /// @{ @"position": @[@"min", @"max"], @"content": @"内容", @"color": @"#808080", @"margin": @[@(-5), @(-13)] 15 | - (F2Guide * (^)(NSDictionary *config))text; 16 | 17 | /// 创建线,config格式如下 18 | /// @{ @"position": @[@"min", @"max"], @"orientation": @"horizontal", @"color": @"#808080", @"lineWdith": @(1), @"dash": @[...] 19 | - (F2Guide * (^)(NSDictionary *config))line; 20 | 21 | ///创建背景,config格式如下 22 | ///@{@"color":@"#FF00001D",@"leftBottom":@[@"min", @"min"], @"rightTop":@[@"max", @(80)]} 23 | - (F2Guide * (^)(NSDictionary *config))background; 24 | 25 | ///创建图片 26 | ///@{@"position":@[@"median", @"median"], @"margin":@[top, right])} 27 | - (F2Guide * (^)(NSDictionary *config))image; 28 | 29 | /// 创建圆 30 | /// @{@"position": @[@"min", @"max"], @"fill":@"#A46FFE", @"size":@(2), @"offsetX": @(10), @"offsetY":@(10)} size为半径 31 | - (F2Guide * (^)(NSDictionary *config))point; 32 | 33 | @end 34 | 35 | NS_ASSUME_NONNULL_END 36 | -------------------------------------------------------------------------------- /ios/F2/F2Utils.h: -------------------------------------------------------------------------------- 1 | #import "F2Chart.h" 2 | #import 3 | 4 | NS_ASSUME_NONNULL_BEGIN 5 | 6 | #define F2SafeString(str) (str.length > 0 ? str : @"") 7 | #define F2SafeJson(json) (json.length > 0 ? json : @"[]") 8 | 9 | #define F2WeakSelf __weak __typeof(self) weakSelf = self; 10 | #define F2StrongSelf __strong __typeof(weakSelf) strongSelf = weakSelf; 11 | #define F2SafeBlockRun(block, ...) if(block != nil) block(__VA_ARGS__) 12 | 13 | #define F2NativeScale UIScreen.mainScreen.nativeScale 14 | 15 | @interface F2Utils : NSObject 16 | 17 | /// jsonDict可能是NSDictionary or NSArray 18 | + (NSString *)toJsonString:(id)jsonDict; 19 | 20 | 21 | /// 解析成NSArray或者NSDictionary, 如果解析失败返回nil 22 | /// @param jsonString json格式 23 | + (id)toJsonObject:(NSString *)jsonString; 24 | 25 | /// 解析成NSArray或者NSDictionary, 如果解析失败返回空字典 26 | /// @param jsonString json格式 27 | + (NSDictionary *)toJsonDictionary:(NSString *)jsonString; 28 | 29 | /// 解析成NSArray或者NSDictionary, 如果解析失败返回空数组 30 | /// @param jsonString json格式 31 | + (NSArray *)toJsonArray:(NSString *)jsonString; 32 | 33 | + (NSDictionary *)resetCallbacksFromOld:(NSDictionary *)config host:(F2Chart *)chart; 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /ios/F2Tests/F2TestUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // F2TestUtil.h 3 | // F2Tests 4 | // 5 | // Created by weiqing.twq on 2022/6/1. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface F2TestUtil : NSObject 15 | 16 | + (BOOL)saveImage:(UIImage *)image name:(NSString *)name; 17 | 18 | + (UIImage *)readImage:(NSString *)imageName; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /ios/F2Tests/F2TestUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // F2TestUtil.m 3 | // F2Tests 4 | // 5 | // Created by weiqing.twq on 2022/6/1. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import "F2TestUtil.h" 10 | 11 | @implementation F2TestUtil 12 | 13 | + (BOOL)saveImage:(UIImage *)image name:(NSString *)name { 14 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES); 15 | NSString *filePath = [[paths objectAtIndex:0]stringByAppendingPathComponent:name]; // 保存文件的名称 16 | NSLog(@"saveImage: %@", filePath); 17 | BOOL result =[UIImageJPEGRepresentation(image, 1) writeToFile:filePath atomically:YES]; // 保存成功会返回YES 18 | NSCAssert(result, @"saveImage failure"); 19 | return result; 20 | } 21 | 22 | + (UIImage *)readImage:(NSString *)imageName { 23 | NSBundle *bundle = [NSBundle bundleForClass:[self class]]; 24 | NSString *jsonPath = [bundle pathForResource:imageName ofType:nil]; 25 | return [[UIImage alloc] initWithContentsOfFile:jsonPath]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /ios/F2Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ios/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDisplayName 6 | App Name 7 | CFBundleIdentifier 8 | $(PRODUCT_BUNDLE_IDENTIFIER) 9 | CFBundleName 10 | $(PRODUCT_NAME) 11 | CFBundleShortVersionString 12 | 1.0 13 | CFBundleVersion 14 | 1 15 | UILaunchStoryboardName 16 | Main 17 | UIMainStoryboardFile 18 | Main 19 | UIRequiredDeviceCapabilities 20 | 21 | armv7 22 | 23 | UISupportedInterfaceOrientations 24 | 25 | UIInterfaceOrientationPortrait 26 | UIInterfaceOrientationLandscapeLeft 27 | UIInterfaceOrientationLandscapeRight 28 | 29 | UISupportedInterfaceOrientations~ipad 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationPortraitUpsideDown 33 | UIInterfaceOrientationLandscapeLeft 34 | UIInterfaceOrientationLandscapeRight 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':android:sample', ':android:f2native', ':android:sample-kotlin' 2 | 3 | project(':android:sample').dir = new File('demos/android/demos') 4 | project(':android:f2native').dir = new File('android/f2native/') 5 | project(':android:sample-kotlin').dir = new File('demos/android/demos-kotlin') -------------------------------------------------------------------------------- /site/pages/index.en.tsx: -------------------------------------------------------------------------------- 1 | import Index from './index.zh'; 2 | 3 | export default Index; 4 | -------------------------------------------------------------------------------- /tests/e2e/BaseInterval.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseInterval.h 3 | // F2Tests 4 | // 5 | // Created by weiqing.twq on 2022/1/18. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include "../../core/graphics/XChart.h" 12 | 13 | using namespace xg; 14 | 15 | namespace e2e { 16 | 17 | class BaseInterval { 18 | public: 19 | 20 | //基础的线图 21 | static bool Case1(float width, float height,float ratio, const std::string &path, void *context) { 22 | XChart chart("Baseline#Test", width, height, ratio); 23 | std::ifstream jsonFile(path); 24 | std::string jsonData((std::istreambuf_iterator(jsonFile)), std::istreambuf_iterator()); 25 | chart.Source(jsonData); 26 | chart.SetCanvasContext(context).Padding(20, 10, 20, 0); 27 | chart.ScaleObject("date", {{"tickCount", 3} , {"range", {0, 1}}}); 28 | chart.ScaleObject("value", {{"nice", true}}); 29 | chart.Interval().Position("date*value"); 30 | chart.Render(); 31 | return true; 32 | } 33 | }; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /tests/e2e/Baseline.h: -------------------------------------------------------------------------------- 1 | // 2 | // Baseline.h 3 | // F2Tests 4 | // 5 | // Created by weiqing.twq on 2022/1/18. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include "../../core/graphics/XChart.h" 12 | 13 | using namespace xg; 14 | 15 | namespace e2e { 16 | 17 | class Baseline { 18 | public: 19 | 20 | //基础的线图 21 | static bool Case1(float width, float height,float ratio, const std::string &path, void *context) { 22 | XChart chart("Baseline#Test", width, height, ratio); 23 | std::ifstream jsonFile(path); 24 | std::string jsonData((std::istreambuf_iterator(jsonFile)), std::istreambuf_iterator()); 25 | chart.Source(jsonData); 26 | chart.SetCanvasContext(context).Padding(20, 10, 20, 0); 27 | chart.Scale("date", "{\"tickCount\": 3}"); 28 | chart.Scale("value", "{\"nice\": true}"); 29 | chart.Line().Position("date*value"); 30 | chart.Render(); 31 | return true; 32 | } 33 | }; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /tests/e2e/F2PixelMatch.h: -------------------------------------------------------------------------------- 1 | // 2 | // PixelMatch.h 3 | // F2Tests 4 | // 5 | // Created by weiqing.twq on 2022/1/13. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface F2PixelMatch : NSObject 14 | 15 | +(bool)match:(UIImage *)image1 image2:(UIImage *)image2 outImage:(UIImage **)outImage; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /tests/e2e/MarketMoving.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseInterval.h 3 | // F2Tests 4 | // 5 | // Created by weiqing.twq on 2022/1/18. 6 | // Copyright © 2022 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include "../../core/graphics/XChart.h" 12 | 13 | using namespace xg; 14 | 15 | namespace e2e { 16 | 17 | class MarketMoving { 18 | public: 19 | 20 | //基础的线图 21 | static bool Case1(float width, float height,float ratio, const std::string &path, void *context) { 22 | XChart chart("Baseline#Test", width, height, ratio); 23 | std::ifstream jsonFile(path); 24 | std::string jsonData((std::istreambuf_iterator(jsonFile)), std::istreambuf_iterator()); 25 | chart.SetCanvasContext(context).Padding(20, 10, 20, 0); 26 | chart.Parse(jsonData); 27 | chart.Render(); 28 | return true; 29 | } 30 | }; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /tests/res/badcase.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/tests/res/badcase.jpg -------------------------------------------------------------------------------- /tests/res/black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/tests/res/black.png -------------------------------------------------------------------------------- /tests/res/e2e/baseInterval.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/tests/res/e2e/baseInterval.jpeg -------------------------------------------------------------------------------- /tests/res/e2e/baseLine.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/tests/res/e2e/baseLine.jpeg -------------------------------------------------------------------------------- /tests/res/e2e/chartBridge.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/tests/res/e2e/chartBridge.jpeg -------------------------------------------------------------------------------- /tests/res/e2e/marketMoving.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/tests/res/e2e/marketMoving.jpeg -------------------------------------------------------------------------------- /tests/res/mockData_baseInterval.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "year": "1951 年\n第一季度", 3 | "sales": 38 4 | }, { 5 | "year": "1952 年\n第一季度", 6 | "sales": 52 7 | }, { 8 | "year": "1956 年\n第一季度", 9 | "sales": 61 10 | }, { 11 | "year": "1957 年\n第一季度", 12 | "sales": 145 13 | }, { 14 | "year": "1958 年\n第一季度", 15 | "sales": 48 16 | }, { 17 | "year": "1959 年\n第一季度", 18 | "sales": 38 19 | }, { 20 | "year": "1960 年\n第一季度", 21 | "sales": 38 22 | }, { 23 | "year": "1962 年\n第一季度", 24 | "sales": 38 25 | }] 26 | -------------------------------------------------------------------------------- /tests/res/red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/tests/res/red.png -------------------------------------------------------------------------------- /tests/res/transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/tests/res/transparent.png -------------------------------------------------------------------------------- /tests/res/white&black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/tests/res/white&black.png -------------------------------------------------------------------------------- /tests/res/white&red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/tests/res/white&red.png -------------------------------------------------------------------------------- /tests/res/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/antvis/F2Native/b1f3f4e81721f68cd13d4a872ecf48e2bc99e88b/tests/res/white.png -------------------------------------------------------------------------------- /tests/run.sh: -------------------------------------------------------------------------------- 1 | rm -rf build 2 | mkdir build && cd build 3 | cmake .. 4 | make 5 | -------------------------------------------------------------------------------- /tests/unit/utils/Point.h: -------------------------------------------------------------------------------- 1 | // 2 | // Point.h 3 | // F2Tests 4 | // 5 | // Created by weiqing.twq on 2021/11/18. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | #include "../../../core/graphics/util/Point.h" 10 | 11 | using namespace xg; 12 | using namespace std; 13 | 14 | namespace unit { 15 | 16 | class PointTest { 17 | public: 18 | static bool Reset() { 19 | auto point = util::Point(0, 0); 20 | point.Reset(1, 2); 21 | return point.x == 1 && point.y == 2; 22 | } 23 | 24 | static bool Max() { 25 | return true; 26 | } 27 | 28 | static bool Min() { 29 | return true; 30 | } 31 | 32 | static bool Add() { 33 | return true; 34 | } 35 | 36 | static bool Sub() { 37 | return true; 38 | } 39 | 40 | static bool Scale() { 41 | return true; 42 | } 43 | 44 | static bool Distance() { 45 | return true; 46 | } 47 | 48 | }; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /tests/unit/utils/StringUtils.h: -------------------------------------------------------------------------------- 1 | #include "../../../core/utils/StringUtil.h" 2 | 3 | namespace unit { 4 | 5 | class StringUtils { 6 | public: 7 | static bool SplitFields1() { 8 | std::vector rst; 9 | StringUtil::Split("x*y", rst, '*'); 10 | return (2 == rst.size()) && ("x" == rst[0]) && ("y"== rst[1]); 11 | } 12 | 13 | static bool SplitFields2() { 14 | std::vector rst; 15 | StringUtil::Split("color", rst, '*'); 16 | return (1 == rst.size()) && ("color"== rst[0]); 17 | }; 18 | 19 | static bool SplitDay() { 20 | std::vector rst; 21 | StringUtil::Split("kline-day", rst, '-'); 22 | return (2 == rst.size()) && ("kline" == rst[0]) && ("day"== rst[1]); 23 | }; 24 | 25 | static bool SplitMinutes() { 26 | std::vector rst; 27 | StringUtil::Split("kline-minutes-5", rst, '-'); 28 | int minutes = std::stoi(rst[2]); 29 | return (3 == rst.size()) && ("kline" == rst[0]) && ("minutes" == rst[1]) && (5 == minutes); 30 | }; 31 | 32 | }; 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /tests/unit/utils/Vector2d.h: -------------------------------------------------------------------------------- 1 | // 2 | // Vector2d.h 3 | // F2Tests 4 | // 5 | // Created by weiqing.twq on 2021/11/18. 6 | // Copyright © 2021 com.alipay.xgraph. All rights reserved. 7 | // 8 | 9 | --------------------------------------------------------------------------------