• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "frameworks/bridge/common/dom/dom_chart.h"
17 
18 #include "frameworks/bridge/common/utils/utils.h"
19 
20 #include "base/utils/linear_map.h"
21 #include "base/utils/string_utils.h"
22 #include "base/utils/utils.h"
23 #include "core/components/common/properties/color_factory.h"
24 
25 namespace OHOS::Ace::Framework {
26 namespace {
27 
28 const char LIGHT_RED_COLOR[] = "#EB4034";
29 const char LIGHT_GREEN_COLOR[] = "#AEEB34";
30 const char LIGHT_BLUE_COLOR[] = "#34EBD9";
31 constexpr double PROGRESS_DEFAULT_MAX_VALUE = 100.0;
32 constexpr uint32_t METHOD_APPEND_ARGS_SIZE = 1;
33 
34 } // namespace
35 
GetSpecializedComponent()36 RefPtr<Component> DOMChart::GetSpecializedComponent()
37 {
38     if (chartType_ == ChartType::BAR || chartType_ == ChartType::LINE) {
39         return chartChild_;
40     }
41     if (chartType_ == ChartType::GAUGE) {
42         return progressChild_;
43     }
44     return dataPanelChild_;
45 }
46 
DOMChart(NodeId nodeId,const std::string & nodeName)47 DOMChart::DOMChart(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName) {}
48 
SetChartAttrOptions(const ChartOptions & chartOptions)49 void DOMChart::SetChartAttrOptions(const ChartOptions& chartOptions)
50 {
51     chartOptions_ = chartOptions;
52 }
53 
SetChartAttrDatasets(const std::vector<MainChart> & datasets)54 void DOMChart::SetChartAttrDatasets(const std::vector<MainChart>& datasets)
55 {
56     chartDatasets_ = datasets;
57     isResetPosition_ = false;
58     position_ = 0;
59     seriesNum_ = 0;
60     lineData_.clear();
61     isSetFirst_ = false;
62 }
63 
SetChartAttrSegments(const std::vector<Segment> & segments)64 void DOMChart::SetChartAttrSegments(const std::vector<Segment>& segments)
65 {
66     segments_ = segments;
67 }
68 
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)69 bool DOMChart::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
70 {
71     // this map should be sorted by key.
72     static const LinearMapNode<void (*)(const std::string&, DOMChart&)> chartAttrsOperators[] = {
73         { DOM_CHART_ANIMATION_DURATION,
74             [](const std::string& val, DOMChart& chart) {
75               chart.animationDuration_ = StringToDouble(val);
76             } },
77         { DOM_AUTO_SCALE,
78             [](const std::string& val, DOMChart& chart) {
79               chart.autoScale_ = StringToBool(val);
80             } },
81         { DOM_EFFECTS_ON,
82             [](const std::string& val, DOMChart& chart) {
83               chart.showEffect_ = StringToBool(val);
84             } },
85         { DOM_PROGRESS_PERCENT,
86             [](const std::string& val, DOMChart& chart) {
87                 chart.percent_ = StringToDouble(val);
88                 if (chart.percent_ > chart.max_) {
89                     chart.percent_ = chart.max_;
90                 }
91                 if (chart.percent_ < chart.min_) {
92                     chart.percent_ = chart.min_;
93                 }
94             } },
95         { DOM_CHART_TYPE,
96             [](const std::string& val, DOMChart& chart) {
97                 if (val == DOM_CHART_TYPE_GAUGE) {
98                     chart.chartType_ = ChartType::GAUGE;
99                 } else if (val == DOM_CHART_TYPE_BAR) {
100                     chart.chartType_ = ChartType::BAR;
101                 } else if (val == DOM_CHART_TYPE_LINE) {
102                     chart.chartType_ = ChartType::LINE;
103                 } else if (val == DOM_CHART_TYPE_PROGRESS) {
104                     chart.chartType_ = ChartType::PROGRESS;
105                 } else if (val == DOM_CHART_TYPE_RAINBOW) {
106                     chart.chartType_ = ChartType::RAINBOW;
107                 } else if (val == DOM_CHART_TYPE_LOADING) {
108                     chart.chartType_ = ChartType::LOADING;
109                 } else {
110                     LOGI("chart type error %{public}s, now using loading", val.c_str());
111                     chart.chartType_ = ChartType::LINE;
112                 }
113             } },
114     };
115     auto operatorIter = BinarySearchFindIndex(chartAttrsOperators, ArraySize(chartAttrsOperators), attr.first.c_str());
116     if (operatorIter != -1) {
117         chartAttrsOperators[operatorIter].value(attr.second, *this);
118         return true;
119     }
120     return false;
121 }
122 
SetSpecializedStyle(const std::pair<std::string,std::string> & style)123 bool DOMChart::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
124 {
125     // this map should be sorted by key.
126     static const LinearMapNode<void (*)(const std::string&, DOMChart&)> chartStylesOperators[] = {
127         { DOM_BACKGROUND_COLOR,
128             [](const std::string& val, DOMChart& chart) {
129                 if (chart.chartType_ == ChartType::LINE || (chart.chartType_ == ChartType::BAR) ||
130                     (chart.chartType_ == ChartType::GAUGE)) {
131                     auto declaration = chart.GetDeclaration();
132                     if (declaration) {
133                         auto backgroundColor = chart.ParseColor(val);
134                         declaration->GetBackDecoration()->SetBackgroundColor(backgroundColor);
135                         declaration->SetHasBackGroundColor(true);
136                         declaration->SetHasDecorationStyle(true);
137                         return;
138                     }
139                 }
140                 chart.backgroundColor_ = chart.ParseColor(val);
141                 chart.trackColorSet_ = true;
142             } },
143         { DOM_CENTER_X,
144             [](const std::string& val, DOMChart& chart) {
145                 chart.centerX_.first = StringToDouble(val);
146                 chart.centerX_.second = true;
147             } },
148         { DOM_CENTER_Y,
149             [](const std::string& val, DOMChart& chart) {
150                 chart.centerY_.first = StringToDouble(val);
151                 chart.centerY_.second = true;
152             } },
153         { DOM_COLORS_ARRAY,
154             [](const std::string& val, DOMChart& chart) {
155                 chart.colors_.clear();
156                 StringUtils::StringSplitter(val, ',', chart.colors_);
157             } },
158         { DOM_TEXT_FONT_FAMILY,
159             [](const std::string& val, DOMChart& chart) {
160               chart.fontFamily_ = ConvertStrToFontFamilies(val);
161             } },
162         { DOM_TEXT_FONT_SIZE,
163             [](const std::string& val, DOMChart& chart) {
164                 chart.textSize_ = StringToDouble(val);
165             } },
166         { DOM_PROGRESS_RADIUS,
167             [](const std::string& val, DOMChart& chart) {
168                 chart.radius_.first = StringToDouble(val);
169                 chart.radius_.second = true;
170             } },
171         { DOM_START_DEGREE,
172             [](const std::string& val, DOMChart& chart) {
173                 chart.startAngle_.first = StringToDouble(val);
174                 chart.startAngle_.second = true;
175             } },
176         { DOM_PROGRESS_STROKE_WIDTH,
177             [](const std::string& val, DOMChart& chart) {
178                 chart.strokeWidth_.first = chart.ParseDimension(val);
179                 chart.strokeWidth_.second = true;
180             } },
181         { DOM_SWEEP_DEGREE,
182             [](const std::string& val, DOMChart& chart) {
183                 chart.totalAngle_.first = StringToDouble(val);
184                 chart.totalAngle_.second = true;
185             } },
186         { DOM_WEIGHTS_ARRAY,
187             [](const std::string& val, DOMChart& chart) {
188                 chart.weights_.clear();
189                 StringUtils::StringSplitter(val, ',', chart.weights_);
190             } },
191     };
192     auto operatorIter =
193         BinarySearchFindIndex(chartStylesOperators, ArraySize(chartStylesOperators), style.first.c_str());
194     if (operatorIter != -1) {
195         chartStylesOperators[operatorIter].value(style.second, *this);
196         return true;
197     }
198     return false;
199 }
200 
OnSetStyleFinished()201 void DOMChart::OnSetStyleFinished()
202 {
203     // colors or weight are illegal, and set default color and weight
204     if (colors_.empty() || weights_.empty() || colors_.size() != weights_.size()) {
205         colors_.push_back(ParseColor(LIGHT_RED_COLOR));
206         colors_.push_back(ParseColor(LIGHT_GREEN_COLOR));
207         colors_.push_back(ParseColor(LIGHT_BLUE_COLOR));
208         // equally separate the range
209         weights_.push_back(1);
210         weights_.push_back(1);
211         weights_.push_back(1);
212     }
213     if (!centerY_.second || !centerX_.second || !radius_.second) {
214         centerY_.first = -1.0;
215         centerX_.first = -1.0;
216         radius_.first = -1.0;
217         centerY_.second = false;
218         centerX_.second = false;
219         radius_.second = false;
220     }
221 }
222 
223 // Sets other properties of a point, except coordinates.
SetPoint(PointInfo & pointInfo,PointInfo getPointInfo)224 void DOMChart::SetPoint(PointInfo& pointInfo, PointInfo getPointInfo)
225 {
226     if (!getPointInfo.GetFillColorString().empty()) {
227         getPointInfo.SetFillColor(ParseColor(getPointInfo.GetFillColorString()));
228     }
229     pointInfo.SetFillColor(getPointInfo.GetFillColor());
230     if (!getPointInfo.GetStrokeColorString().empty()) {
231         getPointInfo.SetStrokeColor(ParseColor(getPointInfo.GetStrokeColorString()));
232     }
233     pointInfo.SetStrokeColor(getPointInfo.GetStrokeColor());
234     pointInfo.SetPointStrokeWidth(getPointInfo.GetPointStrokeWidth());
235     pointInfo.SetPointSize(getPointInfo.GetPointSize());
236     pointInfo.SetPointShape(getPointInfo.GetPointShape());
237     pointInfo.SetDisplay(getPointInfo.GetDisplay());
238 }
239 
SetChart(MainChart & chartDataset)240 void DOMChart::SetChart(MainChart& chartDataset)
241 {
242     chartDataset.SetLineWidth(chartOptions_.GetLineWidth());
243     chartDataset.SetSmoothFlag(chartOptions_.GetSmoothFlag());
244     chartDataset.SetLineGradient(chartOptions_.GetLineGradient());
245     chartDataset.SetWholeLineGradient(chartOptions_.GetWholeLineGradient());
246     chartDataset.SetTargetColor(chartOptions_.GetTargetColor());
247     chartDataset.SetErasePointNumber(chartOptions_.GetErasePointNumber());
248     chartDataset.SetTextSize(textSize_);
249     chartDataset.SetFontFamily(fontFamily_);
250 
251     auto points = chartDataset.GetData();
252     if (points.empty()) {
253         LOGD("points is empty, chart has no data to set.");
254         return;
255     }
256 
257     // parse color from color string
258     for (auto& point : points) {
259         auto pointInfo = point.GetPointInfo();
260         if (!pointInfo.GetStrokeColorString().empty()) {
261             pointInfo.SetStrokeColor(ParseColor(pointInfo.GetStrokeColorString()));
262         }
263         if (!pointInfo.GetFillColorString().empty()) {
264             pointInfo.SetFillColor(ParseColor(pointInfo.GetFillColorString()));
265         }
266         auto segment = point.GetSegmentInfo();
267         if (!segment.GetColorString().empty()) {
268             segment.SetSegmentColor(ParseColor(segment.GetColorString()));
269         }
270         auto text = point.GetTextInfo();
271         if (!text.GetColorString().empty()) {
272             text.SetColor(ParseColor(text.GetColorString()));
273         }
274         point.SetPointInfo(pointInfo);
275         point.SetSegmentInfo(segment);
276         point.SetTextInfo(text);
277     }
278 
279     // remove points out of range. get topPoint and bottomPoint.
280     sort(points.begin(), points.end(),
281         [](LineInfo a, LineInfo b) { return a.GetPointInfo().GetX() < b.GetPointInfo().GetX(); });
282 
283     PointInfo headPoint;
284     PointInfo topPoint = points.begin()->GetPointInfo();
285     PointInfo bottomPoint = points.begin()->GetPointInfo();
286 
287     for (auto pointInfo = points.begin(); pointInfo != points.end();) {
288         auto point = pointInfo->GetPointInfo();
289         auto segment = pointInfo->GetSegmentInfo();
290         if (segment.GetSegmentColor() == Color::TRANSPARENT) {
291             segment.SetSegmentColor(chartDataset.GetStrokeColor());
292             pointInfo->SetSegmentInfo(segment);
293         }
294         if ((chartType_ == ChartType::LINE && point.GetX() < chartOptions_.GetXAxis().min) ||
295             (chartType_ == ChartType::LINE && point.GetX() > chartOptions_.GetXAxis().max) ||
296             ((chartType_ != ChartType::LINE && chartType_ != ChartType::BAR)
297             && (point.GetY() < chartOptions_.GetYAxis().min || point.GetY() > chartOptions_.GetYAxis().max))) {
298             points.erase(pointInfo);
299         } else {
300             if (point.GetY() > topPoint.GetY()) {
301                 topPoint = point;
302             }
303             if (point.GetY() < bottomPoint.GetY()) {
304                 bottomPoint = point;
305             }
306             ++pointInfo;
307         }
308     }
309     chartDataset.SetData(points);
310 
311     if (!points.empty()) {
312         headPoint = points[points.size() - 1].GetPointInfo();
313         SetPoint(headPoint, chartOptions_.GetHeadPoint());
314         chartDataset.SetHeadPoint(headPoint);
315     }
316 
317     SetPoint(topPoint, chartOptions_.GetTopPoint());
318     chartDataset.SetTopPoint(topPoint);
319 
320     SetPoint(bottomPoint, chartOptions_.GetBottomPoint());
321     chartDataset.SetBottomPoint(bottomPoint);
322 }
323 
PrepareSpecializedComponent()324 void DOMChart::PrepareSpecializedComponent()
325 {
326     if (chartType_ == ChartType::GAUGE) {
327         if (!progressChild_) {
328             progressChild_ =
329                 AceType::MakeRefPtr<ProgressComponent>(0.0, 0.0, 0.0, PROGRESS_DEFAULT_MAX_VALUE, ProgressType::GAUGE);
330         }
331         progressChild_->SetValue(percent_);
332         progressChild_->SetMaxValue(max_);
333         progressChild_->SetMinValue(min_);
334         progressChild_->GetTrack()->SetIndicatorFlag(true);
335         progressChild_->GetTrack()->SetSectionsStyle(colors_, weights_);
336         progressChild_->GetTrack()->SetTrackThickness(strokeWidth_.first);
337         progressChild_->GetTrack()->GetTrackInfo()->SetStartDegree(startAngle_.first);
338         progressChild_->GetTrack()->GetTrackInfo()->SetSweepDegree(totalAngle_.first);
339         progressChild_->GetTrack()->SetCenterX(centerX_.first);
340         progressChild_->GetTrack()->SetCenterY(centerY_.first);
341         progressChild_->GetTrack()->SetRadius(radius_.first);
342     } else if (chartType_ == ChartType::BAR || chartType_ == ChartType::LINE) {
343         if (!chartChild_) {
344             chartChild_ = AceType::MakeRefPtr<ChartComponent>(chartType_);
345         }
346         chartChild_->SetHorizontalOption(chartOptions_.GetXAxis());
347         chartChild_->SetVerticalOption(chartOptions_.GetYAxis());
348         // Convert the data in options to mainchart
349         for (auto& charDataset : chartDatasets_) {
350             SetChart(charDataset);
351         }
352         chartChild_->SetMainCharts(chartDatasets_);
353     } else if (chartType_ == ChartType::PROGRESS || chartType_ == ChartType::LOADING) {
354         dataPanelChild_ = AceType::MakeRefPtr<ProgressDataPanelComponent>(chartType_);
355         dataPanelChild_->InitalStyle(GetThemeManager());
356         dataPanelChild_->SetEffects(showEffect_);
357         if (trackColorSet_) {
358             dataPanelChild_->SetTrackColor(backgroundColor_);
359         }
360         dataPanelChild_->SetAutoScale(autoScale_);
361         if (segments_.empty()) {
362             LOGI("progress chart hasn't set segment");
363             return;
364         }
365         auto progressDataPanel = AceType::DynamicCast<ProgressDataPanelComponent>(dataPanelChild_);
366         if (segments_[0].GetColorType() == SegmentStyleType::USE_COLOR) {
367             progressDataPanel->SetStartColor(segments_[0].GetStartColor());
368             progressDataPanel->SetEndColor(segments_[0].GetEndColor());
369         } else if (segments_[0].GetColorType() == SegmentStyleType::USE_GRADIENT) {
370             auto& colorManager = ColorFactory::GetInstance();
371             auto colorPair = colorManager.GetColorTuple(segments_[0].GetColorDescriptor());
372             progressDataPanel->SetStartColor(colorPair.first);
373             progressDataPanel->SetEndColor(colorPair.second);
374         }
375         // for else case, keep default color
376         progressDataPanel->SetProgressValue(segments_[0].GetValue());
377         if (strokeWidth_.second) {
378             dataPanelChild_->SetThickness(strokeWidth_.first);
379         }
380     } else if (chartType_ == ChartType::RAINBOW) {
381         dataPanelChild_ = AceType::MakeRefPtr<PercentageDataPanelComponent>(chartType_);
382         dataPanelChild_->SetAnimationDuration(animationDuration_);
383         dataPanelChild_->SetEffects(showEffect_);
384         dataPanelChild_->SetAutoScale(autoScale_);
385         auto percentageDataPanel = AceType::DynamicCast<PercentageDataPanelComponent>(dataPanelChild_);
386         // the angle range is from 0 to 360.
387         percentageDataPanel->SetStartDegree(startAngle_.second ? startAngle_.first : 0.0);
388         percentageDataPanel->SetSweepDegree(totalAngle_.second ? totalAngle_.first : 360.0);
389         percentageDataPanel->ClearSegment();
390         if (segments_.empty()) {
391             LOGI("progress chart hasn't set segment");
392             return;
393         }
394         for (const auto& segment : segments_) {
395             percentageDataPanel->AppendSegment(segment);
396         }
397         dataPanelChild_->InitalStyle(GetThemeManager());
398         if (trackColorSet_) {
399             dataPanelChild_->SetTrackColor(backgroundColor_);
400         }
401         if (strokeWidth_.second) {
402             dataPanelChild_->SetThickness(strokeWidth_.first);
403         }
404     }
405 }
406 
CallSpecializedMethod(const std::string & method,const std::string & args)407 void DOMChart::CallSpecializedMethod(const std::string& method, const std::string& args)
408 {
409     if (method != DOM_METHOD_APPEND) {
410         LOGD("Not support method %{private}s yet!", method.c_str());
411         return;
412     }
413     std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(args);
414     if (!argsValue || !argsValue->IsArray() || argsValue->GetArraySize() != METHOD_APPEND_ARGS_SIZE) {
415         LOGE("parse args error");
416         return;
417     }
418 
419     std::unique_ptr<JsonValue> serialValue = argsValue->GetArrayItem(0)->GetValue("serial");
420     if (!serialValue || !serialValue->IsNumber()) {
421         LOGE("get serial failed");
422         return;
423     }
424     seriesNum_ = serialValue->GetInt();
425 
426     std::unique_ptr<JsonValue> dataValue = argsValue->GetArrayItem(0)->GetValue("data");
427     if (!dataValue || !dataValue->IsArray()) {
428         LOGE("get data failed");
429         return;
430     }
431     int32_t arraySize = dataValue->GetArraySize();
432     auto chartDatas = chartChild_->GetMainCharts();
433 
434     if (seriesNum_ < 0 || (static_cast<size_t>(seriesNum_) >= chartDatas.size())) {
435         LOGE("series number is greater or equal to the size of chart");
436         return;
437     }
438 
439     if (!isSetFirst_) {
440         isSetFirst_ = true;
441         for (int32_t i = 0; i < static_cast<int32_t>(chartDatas.size()); i++) {
442             lineData_.emplace_back(chartOptions_.GetXAxis().min, false);
443         }
444     }
445 
446     // get the head point position of the series data to be updated.
447     position_ = lineData_[seriesNum_].first;
448     isResetPosition_ = lineData_[seriesNum_].second;
449 
450     for (int32_t i = 0; i < arraySize; i++) {
451         std::unique_ptr<JsonValue> coorVal = dataValue->GetArrayItem(i);
452         if (!coorVal || !coorVal->IsNumber()) {
453             LOGE("get coorVal failed");
454             return;
455         }
456         int32_t coorY = coorVal->GetInt();
457         if (coorY <= chartOptions_.GetYAxis().max && coorY >= chartOptions_.GetYAxis().min) {
458             UpdateChartData(coorY, chartDatas);
459         }
460     }
461 
462     // save the head point position of the updated series data.
463     lineData_[seriesNum_].first = position_;
464     lineData_[seriesNum_].second = isResetPosition_;
465 
466     UpdateTopBottomPoint(chartDatas);
467 
468     chartChild_->SetMainCharts(chartDatas);
469     auto node = DOMNode::GetRootComponent();
470     node->MarkNeedUpdate();
471     auto pipelineContext = pipelineContext_.Upgrade();
472     if (!pipelineContext) {
473         LOGE("pipelineContext_ is nullptr");
474         return;
475     }
476     pipelineContext->ScheduleUpdate(node);
477 }
478 
UpdateTopBottomPoint(std::vector<MainChart> & data)479 void DOMChart::UpdateTopBottomPoint(std::vector<MainChart>& data)
480 {
481     Point bottomPt = Point(0, 0);
482     Point topPt = Point(0, 0);
483     auto pointVec = data[seriesNum_].GetData();
484     double minY = pointVec[0].GetPointInfo().GetY();
485     double maxY = pointVec[0].GetPointInfo().GetY();
486 
487     for (auto iter : pointVec) {
488         if (iter.GetPointInfo().GetY() <= minY) {
489             bottomPt.SetX(iter.GetPointInfo().GetX());
490             bottomPt.SetY(iter.GetPointInfo().GetY());
491             minY = iter.GetPointInfo().GetY();
492         }
493         if (iter.GetPointInfo().GetY() >= maxY) {
494             topPt.SetX(iter.GetPointInfo().GetX());
495             topPt.SetY(iter.GetPointInfo().GetY());
496             maxY = iter.GetPointInfo().GetY();
497         }
498     }
499     auto bottomPoint = data[seriesNum_].GetBottomPoint();
500     bottomPoint.SetX(bottomPt.GetX());
501     bottomPoint.SetY(bottomPt.GetY());
502     data[seriesNum_].SetBottomPoint(bottomPoint);
503 
504     auto topPoint = data[seriesNum_].GetTopPoint();
505     topPoint.SetX(topPt.GetX());
506     topPoint.SetY(topPt.GetY());
507     data[seriesNum_].SetTopPoint(topPoint);
508 }
509 
UpdateChartData(int32_t coorY,std::vector<MainChart> & data)510 void DOMChart::UpdateChartData(int32_t coorY, std::vector<MainChart>& data)
511 {
512     if (isResetPosition_) {
513         position_ = position_ + 1;
514     } else {
515         position_ = static_cast<int32_t>(data[seriesNum_].GetData().size());
516     }
517     if (position_ > chartOptions_.GetXAxis().max || position_ < chartOptions_.GetXAxis().min) {
518         return;
519     }
520     if (chartOptions_.GetLoop() && position_ > chartOptions_.GetXAxis().max - 1) {
521         isResetPosition_ = true;
522         position_ = chartOptions_.GetXAxis().min;
523         Point coor = Point(position_, coorY);
524         PointInfo point = PointInfo(coor);
525         SegmentInfo segment;
526         segment.SetSegmentColor(data[seriesNum_].GetStrokeColor());
527         LineInfo line = LineInfo(point);
528         line.SetSegmentInfo(segment);
529         data[seriesNum_].ReplaceData(position_, line);
530         data[seriesNum_].SetErasePointNumber(chartOptions_.GetErasePointNumber());
531         data[seriesNum_].SetHeadPointIndex(position_);
532     } else {
533         Point coor = Point(position_, coorY);
534         PointInfo point = PointInfo(coor);
535         SegmentInfo segment;
536         segment.SetSegmentColor(data[seriesNum_].GetStrokeColor());
537         LineInfo line = LineInfo(point);
538         line.SetSegmentInfo(segment);
539         if (!isResetPosition_) {
540             data[seriesNum_].AppendData(line);
541         } else {
542             data[seriesNum_].ReplaceData(position_, line);
543             data[seriesNum_].SetHeadPointIndex(position_);
544         }
545     }
546     auto headPoint = data[seriesNum_].GetHeadPoint();
547     headPoint.SetX(position_);
548     headPoint.SetY(coorY);
549     data[seriesNum_].SetHeadPoint(headPoint);
550 }
551 
552 } // namespace OHOS::Ace::Framework
553