private int GetPosPieIndex(PieTempData tempData, Vector2 local) { var dist = Vector2.Distance(local, tempData.center); if (dist < tempData.insideRadius || dist > tempData.outsideRadius) { return(-1); } Vector2 dir = local - tempData.center; float angle = VectorAngle(Vector2.up, dir); var angleList = tempData.angleList; for (int i = angleList.Count - 1; i >= 0; i--) { if (i == 0) { if (angle <= angleList[i]) { return(0); } } else if (angle <= angleList[i] && angle > angleList[i - 1]) { return(i); } } return(-1); }
private void DrawLabelLine(VertexHelper vh, Serie serie, PieTempData tempData, float outSideRadius, Vector2 center, float currAngle, Color color) { if (serie.label.show && serie.label.position == SerieLabel.Position.Outside && serie.label.line) { if (serie.label.color != Color.clear) { color = serie.label.color; } float currSin = Mathf.Sin(currAngle * Mathf.Deg2Rad); float currCos = Mathf.Cos(currAngle * Mathf.Deg2Rad); var radius1 = outSideRadius; var radius2 = tempData.outsideRadius + serie.label.lineLength1; var pos1 = new Vector2(center.x + radius1 * currSin, center.y + radius1 * currCos); var pos2 = new Vector2(center.x + radius2 * currSin, center.y + radius2 * currCos); float tx, ty; Vector2 pos3; if (currAngle < 90) { ty = serie.label.lineWidth * Mathf.Cos((90 - currAngle) * Mathf.Deg2Rad); tx = serie.label.lineWidth * Mathf.Sin((90 - currAngle) * Mathf.Deg2Rad); pos3 = new Vector2(pos2.x - tx, pos2.y + ty - serie.label.lineWidth); } else if (currAngle < 180) { ty = serie.label.lineWidth * Mathf.Sin((180 - currAngle) * Mathf.Deg2Rad); tx = serie.label.lineWidth * Mathf.Cos((180 - currAngle) * Mathf.Deg2Rad); pos3 = new Vector2(pos2.x - tx, pos2.y - ty + serie.label.lineWidth); } else if (currAngle < 270) { ty = serie.label.lineWidth * Mathf.Sin((180 + currAngle) * Mathf.Deg2Rad); tx = serie.label.lineWidth * Mathf.Cos((180 + currAngle) * Mathf.Deg2Rad); pos3 = new Vector2(pos2.x + tx, pos2.y - ty + serie.label.lineWidth); } else { ty = serie.label.lineWidth * Mathf.Cos((90 + currAngle) * Mathf.Deg2Rad); tx = serie.label.lineWidth * Mathf.Sin((90 + currAngle) * Mathf.Deg2Rad); pos3 = new Vector2(pos2.x + tx, pos2.y + ty - serie.label.lineWidth); } var pos4 = new Vector2(currAngle > 180 ? pos3.x - serie.label.lineLength2 : pos3.x + serie.label.lineLength2, pos3.y); ChartHelper.DrawLine(vh, pos1, pos2, serie.label.lineWidth, color); ChartHelper.DrawLine(vh, pos3, pos4, serie.label.lineWidth, color); } }
protected override void DrawChart(VertexHelper vh) { base.DrawChart(vh); serieNameSet.Clear(); int serieNameCount = -1; bool isClickOffset = false; bool isDataHighlight = false; for (int i = 0; i < m_Series.Count; i++) { var serie = m_Series.series[i]; serie.index = i; var data = serie.data; serie.animation.InitProgress(data.Count, 0, 360); if (!serie.show) { continue; } if (!serie.animation.NeedAnimation(i)) { break; } bool isFinish = true; if (serie.pieClickOffset) { isClickOffset = true; } PieTempData tempData; if (i < m_PieTempDataList.Count) { tempData = m_PieTempDataList[i]; tempData.angleList.Clear(); } else { tempData = new PieTempData(); m_PieTempDataList.Add(tempData); } tempData.angleList.Clear(); tempData.dataMax = serie.yMax; tempData.dataTotal = serie.yTotal; UpdatePieCenter(serie); float totalDegree = 360; float startDegree = 0; int showdataCount = 0; foreach (var sd in serie.data) { if (sd.show && serie.pieRoseType == RoseType.Area) { showdataCount++; } sd.canShowLabel = false; } for (int n = 0; n < data.Count; n++) { var serieData = data[n]; float value = serieData.data[1]; string dataName = serieData.name; Color color; if (string.IsNullOrEmpty(dataName)) { serieNameCount++; color = m_ThemeInfo.GetColor(serieNameCount); } else if (!serieNameSet.ContainsKey(dataName)) { serieNameSet.Add(dataName, serieNameCount); serieNameCount++; color = m_ThemeInfo.GetColor(serieNameCount); } else { color = m_ThemeInfo.GetColor(serieNameSet[dataName]); } if (!serieData.show) { tempData.angleList.Add(0); continue; } float degree = serie.pieRoseType == RoseType.Area ? (totalDegree / showdataCount) : (totalDegree * value / tempData.dataTotal); float toDegree = startDegree + degree; float outSideRadius = serie.pieRoseType > 0 ? tempData.insideRadius + (tempData.outsideRadius - tempData.insideRadius) * value / tempData.dataMax : tempData.outsideRadius; if (serieData.highlighted) { isDataHighlight = true; color *= 1.2f; outSideRadius += m_Pie.tooltipExtraRadius; } var offset = serie.pieSpace; if (serie.pieClickOffset && serieData.selected) { offset += m_Pie.selectedOffset; } var halfDegree = (toDegree - startDegree) / 2; float currAngle = startDegree + halfDegree; float currRad = currAngle * Mathf.Deg2Rad; float currSin = Mathf.Sin(currRad); float currCos = Mathf.Cos(currRad); var center = tempData.center; var currDegree = toDegree; if (serie.animation.CheckDetailBreak(n, toDegree)) { isFinish = false; currDegree = serie.animation.GetCurrDetail(); } if (offset > 0) { float offsetRadius = serie.pieSpace / Mathf.Sin(halfDegree * Mathf.Deg2Rad); var insideRadius = tempData.insideRadius - offsetRadius; var outsideRadius = outSideRadius - offsetRadius; if (serie.pieClickOffset && serieData.selected) { offsetRadius += m_Pie.selectedOffset; if (insideRadius > 0) { insideRadius += m_Pie.selectedOffset; } outsideRadius += m_Pie.selectedOffset; } var offestCenter = new Vector3(center.x + offsetRadius * currSin, center.y + offsetRadius * currCos); ChartHelper.DrawDoughnut(vh, offestCenter, insideRadius, outsideRadius, startDegree, currDegree, color); } else { ChartHelper.DrawDoughnut(vh, center, tempData.insideRadius, outSideRadius, startDegree, currDegree, color); } serieData.canShowLabel = currDegree >= currAngle; if (currDegree >= currAngle) { DrawLabelLine(vh, serie, tempData, outSideRadius, center, currAngle, color); } isDrawPie = true; tempData.angleList.Add(toDegree); startDegree = toDegree; if (isFinish) { serie.animation.SetDataFinish(n); } else { break; } } if (!serie.animation.IsFinish()) { float duration = serie.animation.duration > 0 ? (float)serie.animation.duration / 1000 : 1; float speed = 360 / duration; float symbolSpeed = serie.symbol.size / duration; serie.animation.CheckProgress(Time.deltaTime * speed); serie.animation.CheckSymbol(Time.deltaTime * symbolSpeed, serie.symbol.size); RefreshChart(); } } DrawLabelBackground(vh); raycastTarget = isClickOffset && isDataHighlight; }
private void DrawLabel(Serie serie, int dataIndex, SerieData serieData, PieTempData tempData, Color serieColor, float currAngle, float offsetRadius, float insideRadius, float outsideRadius) { if (serieData.labelText == null) { return; } var isHighlight = (serieData.highlighted && serie.highlightLabel.show); if ((serie.label.show || isHighlight) && serieData.canShowLabel) { serieData.SetLabelActive(true); float rotate = 0; bool isInsidePosition = serie.label.position == SerieLabel.Position.Inside; if (serie.label.rotate > 0 && isInsidePosition) { if (currAngle > 180) { rotate += 270 - currAngle; } else { rotate += -(currAngle - 90); } } Color color = serieColor; if (isHighlight) { if (serie.highlightLabel.color != Color.clear) { color = serie.highlightLabel.color; } } else if (serie.label.color != Color.clear) { color = serie.label.color; } else { color = isInsidePosition ? Color.white : serieColor; } var fontSize = isHighlight ? serie.highlightLabel.fontSize : serie.label.fontSize; var fontStyle = isHighlight ? serie.highlightLabel.fontStyle : serie.label.fontStyle; float currRad = currAngle * Mathf.Deg2Rad; serieData.labelText.color = color; serieData.labelText.fontSize = fontSize; serieData.labelText.fontStyle = fontStyle; serieData.labelRect.transform.localEulerAngles = new Vector3(0, 0, rotate); switch (serie.label.position) { case SerieLabel.Position.Center: serieData.labelPosition = tempData.center; break; case SerieLabel.Position.Inside: var labelRadius = offsetRadius + insideRadius + (outsideRadius - insideRadius) / 2; var labelCenter = new Vector2(tempData.center.x + labelRadius * Mathf.Sin(currRad), tempData.center.y + labelRadius * Mathf.Cos(currRad)); serieData.labelPosition = labelCenter; break; case SerieLabel.Position.Outside: labelRadius = tempData.outsideRadius + serie.label.lineLength1; labelCenter = new Vector2(tempData.center.x + labelRadius * Mathf.Sin(currRad), tempData.center.y + labelRadius * Mathf.Cos(currRad)); float labelWidth = serieData.labelText.preferredWidth; if (currAngle > 180) { serieData.labelPosition = new Vector2(labelCenter.x - serie.label.lineLength2 - 5 - labelWidth / 2, labelCenter.y); } else { serieData.labelPosition = new Vector2(labelCenter.x + serie.label.lineLength2 + 5 + labelWidth / 2, labelCenter.y); } break; } if (!string.IsNullOrEmpty(serie.label.formatter)) { var value = serieData.data[1]; var total = serie.yTotal; var content = serie.label.GetFormatterContent(serie.name, serieData.name, value, total); if (serieData.SetLabelText(content)) { RefreshChart(); } } serieData.SetLabelPosition(serieData.labelPosition); } else { serieData.SetLabelActive(false); } }
protected override void OnRefreshLabel() { serieNameSet.Clear(); int serieNameCount = -1; for (int i = 0; i < m_Series.Count; i++) { var serie = m_Series.series[i]; serie.index = i; if (!serie.show) { continue; } PieTempData tempData; if (i < m_PieTempDataList.Count) { tempData = m_PieTempDataList[i]; tempData.angleList.Clear(); } else { tempData = new PieTempData(); m_PieTempDataList.Add(tempData); } tempData.angleList.Clear(); tempData.dataMax = serie.yMax; tempData.dataTotal = serie.yTotal; UpdatePieCenter(serie); var data = serie.data; float totalDegree = 360; float startDegree = 0; int showdataCount = 0; if (serie.pieRoseType == RoseType.Area) { foreach (var sd in serie.data) { if (sd.show) { showdataCount++; } } } for (int n = 0; n < data.Count; n++) { var serieData = data[n]; if (!serieData.canShowLabel) { serieData.SetLabelActive(false); continue; } float value = serieData.data[1]; string dataName = serieData.name; Color color; if (string.IsNullOrEmpty(dataName)) { serieNameCount++; color = m_ThemeInfo.GetColor(serieNameCount); } else if (!serieNameSet.ContainsKey(dataName)) { serieNameSet.Add(dataName, serieNameCount); serieNameCount++; color = m_ThemeInfo.GetColor(serieNameCount); } else { color = m_ThemeInfo.GetColor(serieNameSet[dataName]); } if (!serieData.show) { tempData.angleList.Add(0); continue; } float degree = serie.pieRoseType == RoseType.Area ? (totalDegree / showdataCount) : (totalDegree * value / tempData.dataTotal); float toDegree = startDegree + degree; float outSideRadius = serie.pieRoseType > 0 ? tempData.insideRadius + (tempData.outsideRadius - tempData.insideRadius) * value / tempData.dataMax : tempData.outsideRadius; if (serieData.highlighted) { outSideRadius += m_Pie.tooltipExtraRadius; } var offset = serie.pieSpace; if (serie.pieClickOffset && serieData.selected) { offset += m_Pie.selectedOffset; } var halfDegree = (toDegree - startDegree) / 2; float currAngle = startDegree + halfDegree; if (offset > 0) { float offsetRadius = serie.pieSpace / Mathf.Sin(halfDegree * Mathf.Deg2Rad); var insideRadius = tempData.insideRadius - offsetRadius; var outsideRadius = outSideRadius - offsetRadius; if (serie.pieClickOffset && serieData.selected) { offsetRadius += m_Pie.selectedOffset; if (insideRadius > 0) { insideRadius += m_Pie.selectedOffset; } outsideRadius += m_Pie.selectedOffset; } DrawLabel(serie, n, serieData, tempData, color, currAngle, offsetRadius, insideRadius, outsideRadius); } else { DrawLabel(serie, n, serieData, tempData, color, currAngle, 0, tempData.insideRadius, outSideRadius); } tempData.angleList.Add(toDegree); startDegree = toDegree; } } }
protected override void DrawChart(VertexHelper vh) { base.DrawChart(vh); serieNameSet.Clear(); int serieNameCount = -1; bool isClickOffset = false; bool isDataHighlight = false; for (int i = 0; i < m_Series.Count; i++) { var serie = m_Series.series[i]; serie.index = i; if (!serie.show) { continue; } if (serie.clickOffset) { isClickOffset = true; } PieTempData tempData; if (i < m_PieTempDataList.Count) { tempData = m_PieTempDataList[i]; tempData.angleList.Clear(); } else { tempData = new PieTempData(); m_PieTempDataList.Add(tempData); } tempData.angleList.Clear(); tempData.dataMax = serie.yMax; tempData.dataTotal = serie.yTotal; UpdatePieCenter(serie); var data = serie.data; float totalDegree = 360; float startDegree = 0; int showdataCount = 0; if (serie.roseType == RoseType.Area) { foreach (var sd in serie.data) { if (sd.show) { showdataCount++; } } } for (int n = 0; n < data.Count; n++) { var serieData = data[n]; float value = serieData.data[1]; string dataName = serieData.name; Color color; if (string.IsNullOrEmpty(dataName)) { serieNameCount++; color = m_ThemeInfo.GetColor(serieNameCount); } else if (!serieNameSet.ContainsKey(dataName)) { serieNameSet.Add(dataName, serieNameCount); serieNameCount++; color = m_ThemeInfo.GetColor(serieNameCount); } else { color = m_ThemeInfo.GetColor(serieNameSet[dataName]); } if (!serieData.show) { tempData.angleList.Add(0); continue; } float degree = serie.roseType == RoseType.Area ? (totalDegree / showdataCount) : (totalDegree * value / tempData.dataTotal); float toDegree = startDegree + degree; float outSideRadius = serie.roseType > 0 ? tempData.insideRadius + (tempData.outsideRadius - tempData.insideRadius) * value / tempData.dataMax : tempData.outsideRadius; if (serieData.highlighted) { isDataHighlight = true; color *= 1.2f; outSideRadius += m_Pie.tooltipExtraRadius; } var offset = serie.space; if (serie.clickOffset && serieData.selected) { offset += m_Pie.selectedOffset; } var halfDegree = (toDegree - startDegree) / 2; float currAngle = startDegree + halfDegree; float currRad = currAngle * Mathf.Deg2Rad; float currSin = Mathf.Sin(currRad); float currCos = Mathf.Cos(currRad); var center = tempData.center; if (offset > 0) { float offsetRadius = serie.space / Mathf.Sin(halfDegree * Mathf.Deg2Rad); var insideRadius = tempData.insideRadius - offsetRadius; var outsideRadius = outSideRadius - offsetRadius; if (serie.clickOffset && serieData.selected) { offsetRadius += m_Pie.selectedOffset; if (insideRadius > 0) { insideRadius += m_Pie.selectedOffset; } outsideRadius += m_Pie.selectedOffset; } var offestCenter = new Vector3(center.x + offsetRadius * currSin, center.y + offsetRadius * currCos); ChartHelper.DrawDoughnut(vh, offestCenter, insideRadius, outsideRadius, startDegree, toDegree, color); } else { ChartHelper.DrawDoughnut(vh, center, tempData.insideRadius, outSideRadius, startDegree, toDegree, color); } DrawLabelLine(vh, serie, tempData, outSideRadius, center, currAngle, color); isDrawPie = true; tempData.angleList.Add(toDegree); startDegree = toDegree; } } raycastTarget = isClickOffset && isDataHighlight; }
private void DrawLabel(Serie serie, SerieData serieData, PieTempData tempData, Color serieColor, float currAngle, float offsetRadius, float insideRadius, float outsideRadius) { var isHighlight = (serieData.highlighted && serie.highlightLabel.show); if (serie.label.show || isHighlight) { float rotate = 0; bool isInsidePosition = serie.label.position == SerieLabel.Position.Inside; if (serie.label.rotate > 0 && isInsidePosition) { if (currAngle > 180) { rotate += 270 - currAngle; } else { rotate += -(currAngle - 90); } } Color color = serieColor; if (isHighlight) { if (serie.highlightLabel.color != Color.clear) { color = serie.highlightLabel.color; } } else if (serie.label.color != Color.clear) { color = serie.label.color; } else { color = isInsidePosition ? Color.white : serieColor; } var fontSize = isHighlight ? serie.highlightLabel.fontSize : serie.label.fontSize; var fontStyle = isHighlight ? serie.highlightLabel.fontStyle : serie.label.fontStyle; float currRad = currAngle * Mathf.Deg2Rad; serieData.label.color = color; serieData.label.fontSize = fontSize; serieData.label.fontStyle = fontStyle; serieData.label.transform.localEulerAngles = new Vector3(0, 0, rotate); switch (serie.label.position) { case SerieLabel.Position.Center: serieData.label.transform.localPosition = tempData.center; break; case SerieLabel.Position.Inside: var labelRadius = offsetRadius + insideRadius + (outsideRadius - insideRadius) / 2; var labelCenter = new Vector2(tempData.center.x + labelRadius * Mathf.Sin(currRad), tempData.center.y + labelRadius * Mathf.Cos(currRad)); serieData.label.transform.localPosition = labelCenter; break; case SerieLabel.Position.Outside: labelRadius = tempData.outsideRadius + serie.label.lineLength1; labelCenter = new Vector2(tempData.center.x + labelRadius * Mathf.Sin(currRad), tempData.center.y + labelRadius * Mathf.Cos(currRad)); float labelWidth = serieData.label.preferredWidth; if (currAngle > 180) { serieData.label.transform.localPosition = new Vector2(labelCenter.x - serie.label.lineLength2 - 5 - labelWidth / 2, labelCenter.y); } else { serieData.label.transform.localPosition = new Vector2(labelCenter.x + serie.label.lineLength2 + 5 + labelWidth / 2, labelCenter.y); } break; } serieData.label.gameObject.SetActive(true); } else { serieData.label.gameObject.SetActive(false); } }