Commit a88d8385 by 王宇航

3-06 首頁曲線圖更改

parent 0e74f220
apply plugin: 'com.android.library'
//apply plugin: 'com.github.dcendents.android-maven'
group='com.github.huangyanbin'
android {
compileSdkVersion 25
buildToolsVersion '26.0.2'
defaultConfig {
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
}
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in E:\Android\Sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.david.chart">
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">
</application>
</manifest>
package com.daivd.chart.component;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import com.daivd.chart.component.base.IChartTitle;
import com.daivd.chart.component.base.PercentComponent;
import com.daivd.chart.data.style.FontStyle;
/**
* 绘制标题
* @author huangyanbin
*/
public class ChartTitle extends PercentComponent<String> implements IChartTitle {
/**
* 图表标题最大占比
*/
private static final float MAX_PERCENT =0.4f;
/**
* 标题字体样式
*/
private FontStyle fontStyle= new FontStyle();
private Path path = new Path();
/**
* 设置标题占比
* @param percent 百分比
*/
@Override
public void setPercent(float percent) {
if(percent > MAX_PERCENT){
percent = MAX_PERCENT;
}
super.setPercent(percent);
}
/**
* 绘制标题
* <p>通过设置标题方位绘制标题</p>
* @param canvas 画布
* @param chartName 图表标题
* @param paint 画笔
*/
@Override
public void draw(Canvas canvas, String chartName, Paint paint) {
fontStyle.fillPaint(paint);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
paint.setTextAlign(Paint.Align.LEFT);
float textHeight = fontMetrics.descent - fontMetrics.ascent;
int textWidth = (int)paint.measureText(chartName);
Rect rect = getRect();
int startY = rect.centerY();
int startX = rect.centerX();
path.rewind();
switch (direction) {
case TOP:
case BOTTOM:
startY-= textHeight/2;
startX -=textWidth/2;
canvas.drawText(chartName, startX, startY, paint);
break;
case LEFT:
case RIGHT:
path.moveTo(startX,rect.top);
path.lineTo(startX,rect.bottom);
canvas.drawTextOnPath(chartName,path,(rect.height()-textWidth)/2,0,paint);
break;
}
}
/**
* 获取标题字体样式
* @return 标题字体样式
*/
public FontStyle getFontStyle() {
return fontStyle;
}
/**
* 设置标题字体样式
* @param fontStyle 标题字体样式
*/
public void setFontStyle(FontStyle fontStyle) {
this.fontStyle = fontStyle;
}
}
package com.daivd.chart.component;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import com.daivd.chart.component.base.IEmpty;
import com.daivd.chart.data.style.FontStyle;
/**
* 空白提示
* @author huangyanbin
*/
public class EmptyView implements IEmpty {
/**
* 空白提示字体样式
*/
private FontStyle fontStyle = new FontStyle();
/**
* 空白文字
*/
private String emptyTip = "No Data";
/**
* 空白范围
*/
private Rect rect;
/**
* 绘制空白
* @param canvas 画布
* @param paint 画笔
*/
@Override
public void draw(Canvas canvas, Paint paint) {
draw(canvas,emptyTip,paint);
}
/**
* 获取空白字体样式
* @return 空白字体样式
*/
public FontStyle getFontStyle() {
return fontStyle;
}
/**
* 设置空白字体样式
* @param fontStyle 空白字体样式
*/
public void setFontStyle(FontStyle fontStyle) {
this.fontStyle = fontStyle;
}
/**
* 设置空白提示
* @return 空白提示
*/
@Override
public String getEmptyTip() {
return emptyTip;
}
/**
* 获取空白提示
* @param emptyTip 空白提示
*/
@Override
public void setEmptyTip(String emptyTip) {
this.emptyTip = emptyTip;
}
/**
* 计算空白大小
* <p>因为空白提示是占整个图表不需要计算</>
* @param chartRect 图表范围
*/
@Override
public void computeRect(Rect chartRect) {
rect = chartRect;
}
/**
* 绘制空白
* @param canvas 画布
* @param emptyTip 空白提示
* @param paint 画笔
*/
@Override
public void draw(Canvas canvas, String emptyTip, Paint paint) {
fontStyle.fillPaint(paint);
paint.setTextAlign(Paint.Align.LEFT);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
int textHeight = (int) (fontMetrics.descent - fontMetrics.ascent);
int textWidth = (int) paint.measureText(emptyTip);
canvas.drawText(emptyTip,rect.left +(rect.right-rect.left-textWidth)/2,rect.top+(rect.bottom - rect.top-textHeight)/2,paint);
}
}
package com.daivd.chart.component;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import com.daivd.chart.component.base.ILegend;
import com.daivd.chart.component.base.PercentComponent;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.ColumnData;
import com.daivd.chart.data.style.FontStyle;
import com.daivd.chart.listener.OnClickLegendListener;
import com.daivd.chart.provider.component.point.ILegendPoint;
import com.daivd.chart.provider.component.point.IPoint;
import com.daivd.chart.provider.component.point.LegendPoint;
import java.util.List;
/**
* 图表图例
* @author huangyanbin
*/
public class Legend<C extends ColumnData> extends PercentComponent<ChartData<C>> implements ILegend<C> {
private FontStyle fontStyle;
private ILegendPoint point;
private int padding = 10;
private PointF pointF;
private boolean isSelectColumn = true;
private OnClickLegendListener<C> onClickLegendListener;
private boolean isDisplay = true;
public Legend(){
LegendPoint p = new LegendPoint();
p.getPointStyle().setWidth(p.getPointStyle().getWidth()*2);
point = p;
fontStyle = new FontStyle();
}
@Override
public void computeRect(Rect chartRect) {
if(isDisplay) {
super.computeRect(chartRect);
}
}
/**
* 绘制
* @param canvas 画布
* @param chartData 数据
* @param paint 画笔
*/
@Override
public void draw(Canvas canvas, ChartData<C> chartData, Paint paint) {
if(isDisplay) {
paint.setTextAlign(Paint.Align.LEFT);
Rect legendRect = getRect();
List<C> columnDataList = chartData.getColumnDataList();
int maxLegendNameLength = 0;
int columnDataSize = columnDataList.size();
String maxLengthColumnName = null;
for (int i = 0; i < columnDataSize; i++) {
ColumnData columnData = columnDataList.get(i);
String name = columnData.getName();
if (maxLegendNameLength < name.length()) {
maxLengthColumnName = name;
maxLegendNameLength = name.length();
}
}
fontStyle.fillPaint(paint);
int textWidth = (int) paint.measureText(maxLengthColumnName);//文本长度
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float textHeight = fontMetrics.descent - fontMetrics.ascent;
int maxLegendLength = (int) (point.getWidth() + padding * 3 + textWidth);
int columnSize = legendRect.width() / maxLegendLength; //列
columnSize = columnSize > 0 ? columnSize : 1;
int rowSize = columnDataSize / columnSize;
rowSize = rowSize > 0 ? rowSize : 1;
int perHeight = (int) (textHeight + padding);
int perWidth = legendRect.width() / columnSize;
int offsetY = (legendRect.height() - perHeight * rowSize) / 2;
offsetY = offsetY > 0 ? offsetY : 0;
int offsetX = columnDataSize < columnSize ? (columnSize - columnDataSize) * perWidth / 2 : 0;
for (int i = 0; i < columnDataList.size(); i++) {
int column = i % columnSize;
int row = i / columnSize;
int startX = offsetX + legendRect.left + column * perWidth + (perWidth - maxLegendLength) / 2;
int startY = legendRect.top + offsetY + row * perHeight;
C columnData = columnDataList.get(i);
String name = columnData.getName();
float pointWidth = point.getWidth();
float pointHeight = point.getHeight();
if (pointF != null && isClickRect(startX - pointWidth, startX + perWidth, startY - padding / 2, startY + perHeight + padding / 2)) {
if (isSelectColumn) {
columnData.setDraw(!columnData.isDraw());
}
pointF = null;
if (onClickLegendListener != null) {
onClickLegendListener.onClickLegend(columnData, this);
}
}
paint.setColor(columnData.getColor());
drawPoint(canvas, columnData.isDraw(), startX, (int) (startY - textHeight / 2 + pointHeight / 2), paint);
startX += pointWidth + padding;
drawText(canvas, startX, startY, name, paint);
}
}
}
@Override
public void setFontStyle(FontStyle fontStyle) {
this.fontStyle = fontStyle;
}
/**
* Determine whether to click or not rect
*/
private boolean isClickRect(float left, float right, float top, float bottom){
if(pointF != null) {
return pointF.x >= left && pointF.x <= right && pointF.y >= top && pointF.y <= bottom;
}
return false;
}
/**
* 绘制文字
*/
private void drawText(Canvas canvas, int startX, int startY, String content, Paint paint) {
fontStyle.fillPaint(paint);
canvas.drawText(content, startX, startY, paint);
}
private void drawPoint(Canvas canvas,boolean isDraw,int x, int y, Paint paint){
float w = point.getWidth();
x += w/2;
point.drawPoint(canvas,x,y,0,!isDraw,paint);
}
@Override
public FontStyle getFontStyle() {
return fontStyle;
}
@Override
public void onClickLegend(PointF pointF) {
this.pointF = pointF;
}
@Override
public void setOnClickLegendListener(OnClickLegendListener<C> onClickLegendListener) {
this.onClickLegendListener = onClickLegendListener;
}
@Override
public int getPadding() {
return padding;
}
@Override
public void setPadding(int padding) {
this.padding = padding;
}
public IPoint getPoint() {
return point;
}
public void setPoint(ILegendPoint point) {
this.point = point;
}
@Override
public void setSelectColumn(boolean selectColumn) {
isSelectColumn = selectColumn;
}
@Override
public void setDisplay(boolean isDisplay) {
this.isDisplay = isDisplay;
}
}
package com.daivd.chart.component;
import android.content.ContentValues;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import com.daivd.chart.data.PicOption;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Created by huang on 2017/10/30.
* 图片生成
*/
public class PicGeneration<V extends View> {
public boolean save(V v,PicOption option){
getChartBitmap(v);
return saveToGallery(v,option);
}
private Bitmap getChartBitmap(V v) {
// 创建一个bitmap 根据我们自定义view的大小
Bitmap returnedBitmap = Bitmap.createBitmap(v.getWidth(),
v.getHeight(), Bitmap.Config.RGB_565);
// 绑定canvas
Canvas canvas = new Canvas(returnedBitmap);
// 获取视图的背景
Drawable bgDrawable = v.getBackground();
if (bgDrawable != null)
// 如果有就绘制
bgDrawable.draw(canvas);
else
// 没有就绘制白色
canvas.drawColor(Color.WHITE);
// 绘制
v.draw(canvas);
return returnedBitmap;
}
private boolean saveToGallery(V v, PicOption option) {
String mFilePath;
// 控制图片质量
if (option.getQuality() < 0 || option.getQuality() > 100)
option.setQuality(50);
long currentTime = System.currentTimeMillis();
File extBaseDir = Environment.getExternalStorageDirectory();
File file = new File(extBaseDir.getAbsolutePath() + "/DCIM/" + option.getSubFolderPath());
if (!file.exists()) {
if (!file.mkdirs()) {
return false;
}
}
String mimeType = "";
String fileName = option.getFileName();
switch (option.getFormat()) {
case PNG:
mimeType = "image/png";
if (!fileName.endsWith(".png"))
fileName += ".png";
break;
case WEBP:
mimeType = "image/webp";
if (!fileName.endsWith(".webp"))
fileName += ".webp";
break;
case JPEG:
default:
mimeType = "image/jpeg";
if (!(fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")))
fileName += ".jpg";
break;
}
mFilePath = file.getAbsolutePath() + "/" + fileName;
FileOutputStream out = null;
try {
out = new FileOutputStream(mFilePath);
Bitmap b = getChartBitmap(v);
b.compress(option.getFormat(), option.getQuality(), out);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
long size = new File(mFilePath).length();
ContentValues values = new ContentValues(8);
// store the details
values.put(MediaStore.Images.Media.TITLE, fileName);
values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
values.put(MediaStore.Images.Media.DATE_ADDED, currentTime);
values.put(MediaStore.Images.Media.MIME_TYPE, mimeType);
values.put(MediaStore.Images.Media.DESCRIPTION, option.getFileDescription());
values.put(MediaStore.Images.Media.ORIENTATION, 0);
values.put(MediaStore.Images.Media.DATA, mFilePath);
values.put(MediaStore.Images.Media.SIZE, size);
return v.getContext().getContentResolver().
insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values) != null;
}
}
package com.daivd.chart.component.axis;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.view.Gravity;
import com.daivd.chart.component.base.IAxis;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.format.IFormat;
import com.daivd.chart.data.BarData;
import com.daivd.chart.data.ScaleData;
import com.daivd.chart.data.style.FontStyle;
import com.daivd.chart.data.style.LineStyle;
import com.daivd.chart.matrix.MatrixHelper;
/**
* 基本轴 负责轴的计算方位和绘制
* @author huangyanbin
*/
public abstract class BaseAxis<V> implements IAxis<V> {
/**
* 轴线样式
*/
protected LineStyle axisStyle = new LineStyle();
/**
* 刻度样式
*/
protected FontStyle scaleStyle = new FontStyle();
/**
* 网格样式
*/
protected LineStyle gridStyle = new LineStyle(); //网格样式
/**
* 是否绘制网格
*/
protected boolean isDrawGrid; //是否绘制网格
/**
* 是否显示轴线
*/
protected boolean isShowAxisLine = true;
/**
* 轴文字位置
*/
protected int gravity = Gravity.CENTER;
/**
* 轴方位(上下左右,横向轴可以设置上下,竖轴可以设置左右)
*/
protected int direction;
/**
* 是否是线性图
* 因为线性图一般从0开始绘制轴文字,而柱状图从每个间隔中间开始绘制
*/
protected boolean isLine;
/**
* 文字格式化
*/
private IFormat<V> format;
/**
* 是否显示轴
*/
private boolean isDisplay = true;
/**
*设置是否绘制网格
* @param drawGrid 是否绘制
*/
public void setDrawGrid(boolean drawGrid) {
isDrawGrid = drawGrid;
}
/**
* 获取轴样式
* 默认赋予样式,可以直接get来使用
* @return 轴样式
*/
public LineStyle getAxisStyle() {
return axisStyle;
}
/**
* 设置轴样式
* 如果你对LineStyle提供的样式不满意,可以自定义新的LineStyle
* @param axisStyle 轴样式
*/
public void setAxisStyle(LineStyle axisStyle) {
this.axisStyle = axisStyle;
}
/**
* 获取刻度字体样式
* 默认赋予样式,可以直接get来使用
* @return 刻度字体样式
*/
public FontStyle getScaleStyle() {
return scaleStyle;
}
/**
* 设置刻度字体样式
* 如果你对FontStyle提供的样式不满意,可以自定义新的FontStyle
* @param scaleStyle 刻度字体样式
*/
public void setScaleStyle(FontStyle scaleStyle) {
this.scaleStyle = scaleStyle;
}
/**
* 获取网格样式
* @return 网格样式
*/
public LineStyle getGridStyle() {
return gridStyle;
}
/**
* 设置网格样式
* @param gridStyle 网格样式
*/
public void setGridStyle(LineStyle gridStyle) {
this.gridStyle = gridStyle;
}
/**
* 设置轴偏移方位
* @param gravity 偏移方位
*/
public void setGravity(int gravity) {
this.gravity = gravity;
}
/**
* 是否是线性图表
* 因为线性图一般从0开始绘制轴文字,而柱状图从每个间隔中间开始绘制
* @param isLine 是否是线性图表
*/
public void isLine(boolean isLine) {
this.isLine = isLine;
}
/**
* 是否显示轴
* @return 是否显示轴
*/
public boolean isDisplay() {
return isDisplay;
}
/**
* 绘制轴
* 判断是否需要绘制以及调用绘制轴刻度和绘制轴线
* @param canvas 画布
* @param rect 绘制范围
* @param helper 缩放移动辅助类
* @param paint 画笔
* @param chartData 图表数据
*/
@Override
public void draw(Canvas canvas, Rect rect, MatrixHelper helper, Paint paint, ChartData<? extends BarData> chartData) {
if(isDisplay) {
drawScale(canvas, rect, helper, paint, chartData);
drawAxis(canvas, rect, paint, chartData);
}
}
/**
* 绘制轴刻度
* @param canvas 画布
* @param rect 绘制范围
* @param helper 缩放移动辅助类
* @param paint 画笔
* @param chartData 图表数据
*/
protected void drawScale(Canvas canvas, Rect rect, MatrixHelper helper, Paint paint, ChartData<? extends BarData> chartData) {
ScaleData scaleData = chartData.getScaleData();
Rect clipRect = new Rect(rect);
Rect scaleRect = scaleData.scaleRect;
Rect zoomRect = helper.getZoomProviderRect(scaleData.getOffsetRect(new Rect(rect), scaleRect));
chartData.getScaleData().zoom = helper.getZoom();
if (direction == AxisDirection.BOTTOM || direction == AxisDirection.TOP) {
zoomRect.top = rect.top;
zoomRect.bottom = rect.bottom;
clipRect.left = rect.left + scaleRect.left;
clipRect.right = rect.right - scaleRect.right;
} else {
zoomRect.left = rect.left;
zoomRect.right = rect.right;
clipRect.top = rect.top + scaleRect.top;
clipRect.bottom = rect.bottom - scaleRect.bottom;
}
drawScale(canvas, zoomRect, clipRect, paint, chartData);
}
/**
* 绘制轴线
* @param canvas 画布
* @param rect 绘制范围
* @param paint 画笔
* @param chartData 图表数据
*/
protected void drawAxis(Canvas canvas, Rect rect, Paint paint, ChartData<? extends BarData> chartData) {
if(isShowAxisLine) {
Rect scaleRect = chartData.getScaleData().scaleRect;
axisStyle.fillPaint(paint);
int[] r = calculation(rect, scaleRect);
Path path = new Path();
path.moveTo(r[0],r[1]);
path.lineTo(r[2],r[3]);
canvas.drawPath(path, paint);
}
}
/**
* 计算轴范围
* @param rect 原始范围
* @param scaleRect 缩放范围
* @return 轴上下左右的大小
*/
protected abstract int[] calculation(Rect rect, Rect scaleRect);
/**
* 提供给子类绘制刻度抽象方法
* @param canvas 画布
* @param rect 原始范围
* @param clipRect 裁切轴之后范围
* @param paint 画笔
* @param chartData 图表数据
*/
protected abstract void drawScale(Canvas canvas, Rect rect, Rect clipRect, Paint paint,ChartData<? extends BarData> chartData);
/**
* 获取文字格式化
* @return 文字格式化
*/
public IFormat<V> getFormat() {
return format;
}
/**
* 设置文字格式化
* @param format 文字格式化
*/
@Override
public void setFormat(IFormat<V> format) {
this.format = format;
}
/**
* 是否显示轴线
* @return 是否显示轴线
*/
public boolean isShowAxisLine() {
return isShowAxisLine;
}
/**
* 设置是否显示轴线
* @param showAxisLine 是否显示轴线
*/
public void setShowAxisLine(boolean showAxisLine) {
isShowAxisLine = showAxisLine;
}
/**
* 设置是否显示轴
* @param isShow 是否显示轴
*/
@Override
public void setDisplay(boolean isShow) {
this.isDisplay = isShow;
}
}
package com.daivd.chart.component.axis;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.view.Gravity;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.BarData;
import com.daivd.chart.data.ScaleData;
import com.daivd.chart.exception.ChartException;
import java.util.List;
/**
* 图表横轴
*
* @author huangyanbin
*/
public class HorizontalAxis extends BaseAxis<String> {
/**
* 横轴默认构造方法
* 默认方位在底部
*/
public HorizontalAxis() {
direction = AxisDirection.BOTTOM;
}
/**
* 文字旋转角度
*/
private int rotateAngle = 0;
/**
* 文字是否旋转
*/
private boolean isRotateAngle;
/**
* 文字宽度
*/
private int textWidth;
/**
* 文字高度
*/
private int textHeight;
/**
* 旋转文字高度
*/
private int rotateTextHeight;
/**
* 是否需要偏移来完整显示左右两边文字
*/
private boolean isShowFullValue; //是否显示全文字
/**
* 刻度数据
*/
private ScaleData scaleData;
/**
* 计算刻度大小
* <p>通过计算刻度的宽高得到轴的大小,然后保存到scaleData对象中,以便后面的计算</p>
*
* @param chartData 图表数据
* @param rect 图表原始范围
* @param paint 画笔
*/
@Override
public void computeScale(ChartData<? extends BarData> chartData, Rect rect, Paint paint) {
if (isDisplay()) {
scaleData = chartData.getScaleData();
scaleStyle.fillPaint(paint);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
textHeight = (int) (fontMetrics.descent - fontMetrics.ascent);
int maxLength = 0;
String maxLengthXData = "1";
for (String xData : chartData.getCharXDataList()) {
String formatData = formatData(xData);
if (maxLength < formatData.length()) {
maxLengthXData = formatData;
maxLength = formatData.length();
}
}
textWidth = (int) paint.measureText(maxLengthXData);
//计算旋转的高宽
int dis = textHeight;
if (isRotateAngle) {
int tempHeight = (int) Math.abs(textWidth * Math.sin(rotateAngle * Math.PI / 180)
+ textHeight * Math.cos(rotateAngle * Math.PI / 180));
int tempWidth = (int) Math.abs(textWidth * Math.cos(rotateAngle * Math.PI / 180)
+ textHeight * Math.sin(rotateAngle * Math.PI / 180));
rotateTextHeight = tempHeight;
dis += rotateTextHeight;
textWidth = tempWidth;
}
dis += (int) (scaleStyle.getPadding() * 2 + axisStyle.getWidth());
if (direction == AxisDirection.BOTTOM) {
scaleData.scaleRect.bottom = dis;
} else {
scaleData.scaleRect.top = dis;
}
}
}
/**
* 绘制刻度
* <p>通过zoomRect计算出每个刻度的宽度,迭代绘制刻度</p>
*
* @param canvas 画布
* @param zoomRect 缩放之后范围
* @param rect 原始范围
* @param paint 画笔
* @param chartData 图表数据
*/
protected void drawScale(Canvas canvas, Rect zoomRect, Rect rect, Paint paint, ChartData<? extends BarData> chartData) {
ScaleData scaleData = chartData.getScaleData();
List<String> groupDataList = chartData.getCharXDataList();
int rowSize = scaleData.rowSize;
int groupSize = groupDataList.size();
if (groupSize != rowSize) {
throw new ChartException("Horizontal Vertical axis data inconsistency");
}
float startY;
if (direction == AxisDirection.BOTTOM) {
startY = zoomRect.bottom - scaleData.scaleRect.bottom / 2;
} else {
startY = zoomRect.top + scaleData.scaleRect.top / 2;
}
int left = zoomRect.left;
int width = zoomRect.right - left;
double perWidth = ((double) width) / (isLine ? groupSize - 1 : groupSize);
int filterMultiple = (int) (textWidth / perWidth + 1);
for (int i = 0; i < groupSize; i++) {
String content = groupDataList.get(i);
int startX = getGravityStartX(left, i, perWidth);
//留1px缓冲
if (startX >= rect.left - 1 && startX <= rect.right + 1) {
if (i % filterMultiple == 0) {
drawText(canvas, content, startX, startY, i, paint);
drawGrid(canvas, startX, rect, scaleData.scaleRect, paint);
}
}
}
}
/**
* 获取刻度起始X的位置
* <p>根据gravity来判断偏移的值</p>
*
* @param left 左边
* @param position 位置
* @param perWidth 每个刻度的宽度
* @return 刻度起始X的位置
*/
private int getGravityStartX(int left, int position, double perWidth) {
int startX = (int) (left + position * perWidth);
if (gravity == Gravity.CENTER) {
startX += perWidth / 2;
} else if (gravity == Gravity.RIGHT) {
startX += perWidth;
}
return startX;
}
/**
* 绘制文字
* <p>完成文字偏移,文字旋转,绘制</p>
*
* @param canvas 画布
* @param contentStr 文字内容
* @param startX 文字绘制起始X位置
* @param startY 文字绘制起始Y位置
* @param position 刻度序号
* @param paint 画笔
*/
private void drawText(Canvas canvas, String contentStr, int startX, float startY, int position, Paint paint) {
String content = formatData(contentStr);
scaleStyle.fillPaint(paint);
paint.setTextAlign(Paint.Align.CENTER);
if (isShowFullValue && position == 0) {
int width = (int) paint.measureText(content);
startX += width / 2;
} else if (isShowFullValue && position == scaleData.rowSize - 1) {
int width = (int) paint.measureText(content);
startX -= width / 2;
}
if (isRotateAngle) {
canvas.save();
canvas.rotate(rotateAngle, startX, startY);
canvas.drawText(content, startX, startY + textHeight / 2, paint);
canvas.restore();
} else {
canvas.drawText(content, startX, startY + textHeight / 2, paint);
}
}
/**
* 格式化文字
*
* @param data 文字
* @return 格式化完成之后的文字
*/
private String formatData(String data) {
return getFormat() != null ? getFormat().format(data) : data;
}
/**
* 绘制竖向网格
*
* @param canvas 画布
* @param startX 网格起始X位置
* @param rect 原始范围
* @param scaleRect 缩放范围
* @param paint 画布
*/
public void drawGrid(Canvas canvas, float startX, Rect rect, Rect scaleRect, Paint paint) {
if (gridStyle != null && isDrawGrid) {
gridStyle.fillPaint(paint);
Path path = new Path();
path.moveTo(startX, rect.top + scaleRect.top);
path.lineTo(startX, rect.bottom - scaleRect.bottom);
canvas.drawPath(path, paint);
}
}
/**
* 计算出裁切轴之后的范围
*
* @param rect 原始范围
* @param scaleRect 缩放范围
* @return 上下左右的大小
*/
protected int[] calculation(Rect rect, Rect scaleRect) {
int startX = rect.left + scaleRect.left;
int endX = rect.right - scaleRect.right;
int startY, endY;
if (direction == AxisDirection.BOTTOM) {
startY = rect.bottom - scaleRect.bottom;
} else {
startY = rect.top + scaleRect.top;
}
endY = startY;
return new int[]{startX, startY, endX, endY};
}
/**
* 设置轴方位
* <p>横轴只能设置上下方位</p>
*
* @param axisDirection 轴方位
*/
@Override
public void setAxisDirection(int axisDirection) {
if (axisDirection == AxisDirection.BOTTOM || axisDirection == AxisDirection.TOP) {
this.direction = axisDirection;
} else throw new ChartException("Can only set BOTTOM, TOP direction");
}
/**
* 设置文字旋转角度
*
* @param rotateAngle
*/
public void setRotateAngle(int rotateAngle) {
isRotateAngle = true;
this.rotateAngle = rotateAngle;
}
/**
* 是否需要偏移来完整显示左右两边文字
*
* @return 是否需要偏移
*/
public boolean isShowFullValue() {
return isShowFullValue;
}
/**
* 设置是否需要偏移来完整显示左右两边文字
*
* @param showFullValue 设置是否需要偏移
*/
public void setShowFullValue(boolean showFullValue) {
isShowFullValue = showFullValue;
}
}
package com.daivd.chart.component.axis;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.BarData;
import com.daivd.chart.data.ScaleData;
import com.daivd.chart.data.ScaleSetData;
import com.daivd.chart.exception.ChartException;
import java.util.List;
/**
* 图表竖轴
*
* @author huangyanbin
*/
public class VerticalAxis extends BaseAxis<Double> {
/**
* 图表刻度设置数据
* <p>用于保存用户设置最大,最小等数据</p>
*/
private ScaleSetData scaleSetData = new ScaleSetData();
/**
* 横轴构造方法
* <p>可以设置横轴方向 左右方位</p>
*
* @param direction 方位
*/
public VerticalAxis(int direction) {
this.direction = direction;
}
/**
* 小数点格式化
*/
private java.text.DecimalFormat df = new java.text.DecimalFormat("0");
/**
* 计算刻度大小
* <p>通过计算刻度的宽高得到轴的大小,然后保存到scaleData对象中,以便后面的计算</p>
*
* @param chartData 图表数据
* @param rect 图表原始范围
* @param paint 画笔
*/
@Override
public void computeScale(ChartData<? extends BarData> chartData, Rect rect, Paint paint) {
if (isDisplay()) {
ScaleData scaleData = chartData.getScaleData();
scaleData.resetScale(scaleSetData, direction);
scaleStyle.fillPaint(paint);
int length = Math.max(formatVerticalAxisData(scaleData.getMaxScaleValue(direction)).length(),
formatVerticalAxisData(scaleData.getMinScaleValue(direction)).length());
int textHeight = (int) (paint.measureText("1", 0, 1) * length);
int dis = (int) (textHeight + scaleStyle.getPadding() + axisStyle.getWidth() + scaleStyle.getScalePadding());
if (direction == AxisDirection.LEFT) {
scaleData.scaleRect.left = dis;
} else {
scaleData.scaleRect.right = dis;
}
}
}
/**
* 绘制刻度
* <p>通过zoomRect计算出每个刻度的宽度,迭代绘制刻度</p>scaleData对象,軸的數據
*
* @param canvas 画布
* @param zoomRect 缩放之后范围
* @param clipRect 原始范围
* @param paint 画笔
* @param chartData 图表数据
*/
@Override
protected void drawScale(Canvas canvas, Rect zoomRect, Rect clipRect, Paint paint, ChartData<? extends BarData> chartData) {
ScaleData scaleData = chartData.getScaleData();
List<Double> scaleList = scaleData.getScaleList(direction);
float startX;
if (direction == AxisDirection.LEFT) {
startX = zoomRect.left + scaleData.scaleRect.left + scaleStyle.getPadding() - scaleStyle.getScalePadding();
} else {
startX = zoomRect.right - scaleData.scaleRect.right + scaleStyle.getPadding() + scaleStyle.getScalePadding();
}
int bottom = zoomRect.bottom;
int height = zoomRect.height();
float textHeight = paint.measureText("1", 0, 1);
int perHeight = height / (scaleList.size() - 1);
for (int i = 0; i < scaleList.size(); i++) {
double value = scaleList.get(i);
float startY = bottom - i * perHeight;
if (clipRect.contains(clipRect.centerX(), (int) startY - 1)) {
drawText(canvas, startX, startY + textHeight / 2, value, paint);
drawGrid(canvas, startY, zoomRect, scaleData.scaleRect, paint);
}
}
}
/**
* 绘制文字
*/
private void drawText(Canvas canvas, float startX, float startY, double value, Paint paint) {
scaleStyle.fillPaint(paint);
String content = formatVerticalAxisData(value);
paint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(content, startX, startY, paint);
}
/**
* 绘制网格
*/
private void drawGrid(Canvas canvas, float startY, Rect rect, Rect scaleRect, Paint paint) {
if (gridStyle != null && isDrawGrid) {
gridStyle.fillPaint(paint);
Path path = new Path();
path.moveTo(rect.left + scaleRect.left, startY);
path.lineTo(rect.right - scaleRect.right, startY);
canvas.drawPath(path, paint);
}
}
/**
* 计算出裁切轴之后的范围
*
* @param rect 原始范围
* @param scaleRect 缩放范围
* @return 上下左右的大小
*/
protected int[] calculation(Rect rect, Rect scaleRect) {
int startY = rect.top + scaleRect.top;
int endY = rect.bottom - scaleRect.bottom;
int startX, endX;
if (direction == AxisDirection.LEFT) {
startX = rect.left + scaleRect.left;
} else {
startX = rect.right - scaleRect.right;
}
endX = startX;
return new int[]{startX, startY, endX, endY};
}
/**
* 设置轴方位
* <p>竖轴只能设置左右方位</p>
*
* @param axisDirection 轴方位
*/
@Override
public void setAxisDirection(int axisDirection) {
if (axisDirection == AxisDirection.LEFT || axisDirection == AxisDirection.RIGHT) {
this.direction = axisDirection;
} else throw new ChartException("Can only set LEFT, RIGHT direction");
}
/**
* 格式化竖轴数据
*
* @param value 数值
* @return 格式化竖轴之后数据
*/
private String formatVerticalAxisData(double value) {
if (getFormat() != null) {
return getFormat().format(value);
}
return df.format(value);
}
/**
* 设置刻度是否从0开始
*/
public void setStartZero(boolean isStartZero) {
this.scaleSetData.setStartZoom(isStartZero);
}
/**
* 设置刻度最大值
*
* @param maxValue 最大值
*/
public void setMaxValue(double maxValue) {
this.scaleSetData.setMaxValue(maxValue);
}
/**
* 设置刻度最小值
*
* @param minValue 最大值
*/
public void setMinValue(double minValue) {
this.scaleSetData.setMinValue(minValue);
}
}
package com.daivd.chart.component.base;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.format.IFormat;
import com.daivd.chart.data.BarData;
import com.daivd.chart.matrix.MatrixHelper;
/**
* Created by huangYanBin on 2017/9/26.
* 轴接口
*/
public interface IAxis<V> {
void draw(Canvas canvas, Rect rect, MatrixHelper helper, Paint paint, ChartData<? extends BarData> chartData);
void computeScale(ChartData<? extends BarData> chartData, Rect rect, Paint paint);
void setAxisDirection(int axisDirection);
void setFormat(IFormat<V> format);
IFormat<V> getFormat();
void setDisplay(boolean isShow);
/**
* Created by huangYanBin on 2017/9/26.
* 轴方向
*/
interface AxisDirection {
int TOP = 1;
int BOTTOM=2;
int LEFT = 3;
int RIGHT = 4;
}
}
package com.daivd.chart.component.base;
import com.daivd.chart.data.style.FontStyle;
/**
* Created by huang on 2017/10/26.
*/
public interface IChartTitle extends IComponent<String> {
float getPercent();
void setPercent(float percent);
FontStyle getFontStyle();
int getDirection();
void setDirection(int direction);
void setFontStyle(FontStyle fontStyle);
}
package com.daivd.chart.component.base;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
/** 图表组件
* Created by huang on 2017/10/26.
*/
public interface IComponent<T> {
int LEFT = 0;
int TOP = 1;
int RIGHT =2;
int BOTTOM = 3;
/**
* 计算组件Rect
* @param chartRect
*/
void computeRect(Rect chartRect);
/**
* 绘制组件
* @param canvas 画布
* @param t 数据
* @param paint 画笔
*/
void draw(Canvas canvas, T t, Paint paint);
}
package com.daivd.chart.component.base;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import com.daivd.chart.data.style.FontStyle;
/**
* Created by huang on 2017/9/30.
*/
public interface IEmpty extends IComponent<String> {
void draw(Canvas canvas, Paint paint);
FontStyle getFontStyle();
void setFontStyle(FontStyle fontStyle) ;
String getEmptyTip();
void setEmptyTip(String emptyTip);
}
package com.daivd.chart.component.base;
import android.graphics.PointF;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.ColumnData;
import com.daivd.chart.data.style.FontStyle;
import com.daivd.chart.provider.component.point.ILegendPoint;
import com.daivd.chart.provider.component.point.IPoint;
import com.daivd.chart.listener.OnClickLegendListener;
/**
* Created by huang on 2017/10/26.
*/
public interface ILegend<C extends ColumnData> extends IComponent<ChartData<C>> {
float getPercent();
void setPercent(float percent);
FontStyle getFontStyle();
int getDirection();
void setDirection(int direction);
void setFontStyle(FontStyle fontStyle);
void onClickLegend(PointF pointF);
void setOnClickLegendListener(OnClickLegendListener<C> onClickLegendListener);
int getPadding();
void setPadding(int padding);
IPoint getPoint();
void setPoint(ILegendPoint point);
void setSelectColumn(boolean selectColumn);
void setDisplay(boolean isDisplay);
}
\ No newline at end of file
package com.daivd.chart.component.base;
import android.graphics.Rect;
/**图表百分百组件
* Created by huang on 2017/10/26.
*/
public abstract class PercentComponent<T> implements IComponent<T> {
private static final float DEFAULT_PERCENT = 0.1f;
private float percent = DEFAULT_PERCENT;
private Rect rect = new Rect();
protected int direction;
@Override
public void computeRect(Rect chartRect) {
rect.left = chartRect.left;
rect.right = chartRect.right;
rect.top = chartRect.top;
rect.bottom = chartRect.bottom;
int h = (int) (chartRect.height()*percent);
int w = (int) (chartRect.width()*percent);
switch (direction){
case TOP:
rect.bottom = rect.top+h;
chartRect.top = chartRect.top+h;
break;
case LEFT:
rect.right = rect.left + w;
chartRect.left = chartRect.left + w;
break;
case RIGHT:
rect.left = rect.right -w;
chartRect.right = chartRect.right - w;
break;
case BOTTOM:
rect.top = rect.bottom -h;
chartRect.bottom = chartRect.bottom -h;
break;
}
}
public float getPercent() {
return percent;
}
public void setPercent(float percent) {
this.percent = percent;
}
public Rect getRect() {
return rect;
}
public void setRect(Rect rect) {
this.rect = rect;
}
public int getDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}
}
package com.daivd.chart.core;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import com.daivd.chart.core.base.BaseBarLineChart;
import com.daivd.chart.data.BarData;
import com.daivd.chart.provider.barLine.Bar3DProvider;
/**
* Created by huang on 2017/9/26.
* 3DBar图表
*/
public class Bar3DChart extends BaseBarLineChart<Bar3DProvider,BarData> {
public Bar3DChart(Context context) {
super(context);
}
public Bar3DChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Bar3DChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected Bar3DProvider initProvider() {
return new Bar3DProvider();
}
}
package com.daivd.chart.core;
import android.content.Context;
import android.util.AttributeSet;
import com.daivd.chart.core.base.BaseBarLineChart;
import com.daivd.chart.data.BarData;
import com.daivd.chart.provider.barLine.BarProvider;
/**
* Created by huang on 2017/9/26.
* 柱状图
*/
public class BarChart extends BaseBarLineChart<BarProvider<BarData>,BarData> {
public BarChart(Context context) {
super(context);
}
public BarChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BarChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected BarProvider initProvider() {
return new BarProvider();
}
}
package com.daivd.chart.core;
import android.content.Context;
import android.util.AttributeSet;
import com.daivd.chart.core.base.BaseBarLineChart;
import com.daivd.chart.data.BarLineData;
import com.daivd.chart.provider.barLine.BarLineProvider;
/**
* Created by huang on 2017/9/26.
* 柱状图
*/
public class BarLineChart extends BaseBarLineChart<BarLineProvider,BarLineData> {
public BarLineChart(Context context) {
super(context);
}
public BarLineChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BarLineChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected BarLineProvider initProvider() {
return new BarLineProvider();
}
}
package com.daivd.chart.core;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import com.daivd.chart.core.base.BaseBarLineChart;
import com.daivd.chart.data.LineData;
import com.daivd.chart.exception.ChartException;
import com.daivd.chart.provider.barLine.LineProvider;
import com.daivd.chart.provider.component.line.CurveLineModel;
import com.daivd.chart.provider.component.line.BrokenLineModel;
/**
* Created by huang on 2017/9/26.
* 线性图
*/
public class LineChart extends BaseBarLineChart<LineProvider,LineData> {
public static final int LINE_MODEL = 0;
public static final int CURVE_MODEL = 1;
public LineChart(Context context) {
super(context);
}
public LineChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LineChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected LineProvider initProvider() {
horizontalAxis.setGravity(Gravity.LEFT);
horizontalAxis.isLine(true);
return new LineProvider();
}
public void setLineModel(int model){
if(model == LINE_MODEL){
provider.setLineModel(new BrokenLineModel());
}else if( model == CURVE_MODEL){
provider.setLineModel(new CurveLineModel());
}else {
throw new ChartException("Please set the correct Line model");
}
}
}
package com.daivd.chart.core;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import com.daivd.chart.core.base.BaseRotateChart;
import com.daivd.chart.data.PieData;
import com.daivd.chart.matrix.RotateHelper;
import com.daivd.chart.provider.pie.Pie3DProvider;
/**
* Created by huang on 2017/10/9.
* 饼图
*/
public class Pie3DChart extends BaseRotateChart<Pie3DProvider,PieData> {
public Pie3DChart(Context context) {
super(context);
}
public Pie3DChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Pie3DChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected Pie3DProvider initProvider(RotateHelper rotateHelper) {
Pie3DProvider provider = new Pie3DProvider(getContext());
provider.setRotateHelper(rotateHelper);
return provider;
}
}
package com.daivd.chart.core;
import android.content.Context;
import android.util.AttributeSet;
import com.daivd.chart.core.base.BaseRotateChart;
import com.daivd.chart.data.PieData;
import com.daivd.chart.matrix.RotateHelper;
import com.daivd.chart.provider.pie.PieProvider;
/**
* Created by huang on 2017/10/9.
* 饼图
*/
public class PieChart extends BaseRotateChart<PieProvider,PieData> {
public PieChart(Context context) {
super(context);
}
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PieChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected PieProvider initProvider(RotateHelper rotateHelper) {
PieProvider provider = new PieProvider();
provider.setRotateHelper(rotateHelper);
return provider;
}
}
package com.daivd.chart.core;
import android.content.Context;
import android.util.AttributeSet;
import com.daivd.chart.core.base.BaseRotateChart;
import com.daivd.chart.data.RadarData;
import com.daivd.chart.matrix.RotateHelper;
import com.daivd.chart.provider.radar.RadarProvider;
/**
* Created by huang on 2017/10/9.
* 雷达图
*/
public class RadarChart extends BaseRotateChart<RadarProvider,RadarData> implements RotateHelper.OnRotateListener{
public RadarChart(Context context) {
super(context);
}
public RadarChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RadarChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected RadarProvider initProvider(RotateHelper rotateHelper) {
RadarProvider provider = new RadarProvider();
provider.setRotateHelper(rotateHelper);
return provider;
}
}
package com.daivd.chart.core;
import android.content.Context;
import android.util.AttributeSet;
import com.daivd.chart.core.base.BaseRotateChart;
import com.daivd.chart.data.RoseData;
import com.daivd.chart.matrix.RotateHelper;
import com.daivd.chart.provider.rose.RoseProvider;
/**
* Created by huang on 2017/10/9.
* 饼图
*/
public class RoseChart extends BaseRotateChart<RoseProvider,RoseData> {
public RoseChart(Context context) {
super(context);
}
public RoseChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoseChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected RoseProvider initProvider(RotateHelper rotateHelper) {
RoseProvider provider = new RoseProvider();
provider.setRotateHelper(rotateHelper);
return provider;
}
}
package com.daivd.chart.core.base;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import com.daivd.chart.component.axis.HorizontalAxis;
import com.daivd.chart.component.axis.VerticalAxis;
import com.daivd.chart.component.base.IAxis;
import com.daivd.chart.data.BarData;
import com.daivd.chart.provider.IProvider;
/**
* Created by huang on 2017/9/26.
* 线性和柱状图
*/
public abstract class BaseBarLineChart<P extends IProvider<C>,C extends BarData> extends BaseChart<P,C> {
protected HorizontalAxis horizontalAxis; //横轴
protected VerticalAxis leftVerticalAxis;//竖轴
protected VerticalAxis rightVerticalAxis;//竖轴
public BaseBarLineChart(Context context) {
super(context);
}
public BaseBarLineChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BaseBarLineChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
protected void init(){
horizontalAxis = new HorizontalAxis();
leftVerticalAxis = new VerticalAxis(IAxis.AxisDirection.LEFT);
rightVerticalAxis = new VerticalAxis(IAxis.AxisDirection.RIGHT);
super.init();
}
protected void drawContent(Canvas canvas){
horizontalAxis.computeScale(chartData, chartRect, paint);
if (chartData.getScaleData().isLeftHasValue)
leftVerticalAxis.computeScale(chartData, chartRect, paint);
if (chartData.getScaleData().isRightHasValue)
rightVerticalAxis.computeScale(chartData, chartRect, paint);
if (chartData.getScaleData().isLeftHasValue)
leftVerticalAxis.draw(canvas, chartRect, matrixHelper, paint, chartData);
if (chartData.getScaleData().isRightHasValue)
rightVerticalAxis.draw(canvas, chartRect, matrixHelper, paint, chartData);
horizontalAxis.draw(canvas, chartRect, matrixHelper, paint, chartData);
computeScaleRect();
provider.drawProvider(canvas, chartRect, matrixHelper, paint);
}
/**
* 计算绘制刻度之后的大小
*/
private void computeScaleRect(){
Rect rect = chartData.getScaleData().scaleRect;
computeChartRect(rect);
}
public void setHeightPercent(){
}
public HorizontalAxis getHorizontalAxis() {
return horizontalAxis;
}
public VerticalAxis getLeftVerticalAxis() {
return leftVerticalAxis;
}
public VerticalAxis getRightVerticalAxis() {
return rightVerticalAxis;
}
}
package com.daivd.chart.core.base;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import com.daivd.chart.component.ChartTitle;
import com.daivd.chart.component.EmptyView;
import com.daivd.chart.component.Legend;
import com.daivd.chart.component.PicGeneration;
import com.daivd.chart.component.base.IChartTitle;
import com.daivd.chart.component.base.IEmpty;
import com.daivd.chart.component.base.ILegend;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.ColumnData;
import com.daivd.chart.data.PicOption;
import com.daivd.chart.data.ScaleData;
import com.daivd.chart.listener.ChartGestureObserver;
import com.daivd.chart.listener.OnChartChangeListener;
import com.daivd.chart.listener.OnClickColumnListener;
import com.daivd.chart.listener.OnClickLegendListener;
import com.daivd.chart.matrix.MatrixHelper;
import com.daivd.chart.provider.IProvider;
/**
* 基本图表
* Created by huang on 2017/9/26.
*/
public abstract class BaseChart<P extends IProvider<C>, C extends ColumnData> extends View
implements ChartGestureObserver, OnClickLegendListener<C>, OnChartChangeListener {
protected int width; //高
protected int height; //宽
protected int paddingLeft = 10;
protected int paddingRight = 10;
protected int paddingTop = 30;
protected int paddingBottom = 30;
protected Rect chartRect = new Rect();
protected ILegend<C> legend;
protected IChartTitle chartTitle;
protected P provider;//内容绘制者
protected Paint paint;
protected ChartData<C> chartData;
protected MatrixHelper matrixHelper;
protected boolean isShowChartName = true;
protected boolean isCharEmpty;
protected IEmpty emptyView;
private OnClickLegendListener<C> onClickLegendListener;
private boolean isFirstAnim = true;
public BaseChart(Context context) {
super(context);
init();
}
public BaseChart(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public BaseChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
/**
* 初始化组件
*/
protected void init() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
chartTitle = new ChartTitle();
legend = new Legend<>();
legend.setOnClickLegendListener(this);
matrixHelper = new MatrixHelper(getContext());
matrixHelper.register(this);
matrixHelper.setOnTableChangeListener(this);
emptyView = new EmptyView();
provider = initProvider();
}
/**
* 将触摸事件交给Iouch处理
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
return matrixHelper.handlerTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
matrixHelper.onDisallowInterceptEvent(this, event);
return super.dispatchTouchEvent(event);
}
/**
* 获取大小
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
width = w;
height = h;
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (chartData != null) {
resetScaleData();
computePaddingRect();
if (isShowChartName) {
//计算标题的大小
chartTitle.computeRect(chartRect);
chartTitle.draw(canvas, chartData.getChartName(), paint);
}
if (!chartData.isEmpty()) {
//计算图例的大小
legend.computeRect(chartRect);
//绘制图例
legend.draw(canvas, chartData, paint);
}
if (!isCharEmpty) {
//绘制内容
drawContent(canvas);
} else {
//绘制空白
emptyView.computeRect(chartRect);
emptyView.draw(canvas, paint);
}
}
}
//待改善
private void resetScaleData() {
ScaleData scaleData = chartData.getScaleData();
scaleData.scaleRect.set(0, 0, 0, 0);
}
protected abstract void drawContent(Canvas canvas);
protected void computeChartRect(Rect rect) {
chartRect.left = chartRect.left + rect.left;
chartRect.top = chartRect.top + rect.top;
chartRect.bottom = chartRect.bottom - rect.bottom;
chartRect.right = chartRect.right - rect.right;
}
/**
* 计算图表的区域
*
* @return
*/
private void computePaddingRect() {
chartRect.left = paddingLeft;
chartRect.top = paddingTop;
chartRect.bottom = height - paddingBottom;
chartRect.right = width - paddingRight;
}
public void setPadding(int[] padding) {
this.paddingLeft = padding[0];
this.paddingTop = padding[1];
this.paddingRight = padding[2];
this.paddingBottom = padding[3];
}
protected abstract P initProvider();
/**
* 设置图内容绘制者
*/
public void setProvider(P provider) {
this.provider = provider;
}
public P getProvider() {
return provider;
}
public ChartData<C> getChartData() {
return chartData;
}
/**
* 设置图表数据源
*/
public void setChartData(ChartData<C> chartData) {
isCharEmpty = !provider.calculation(chartData);
this.chartData = chartData;
invalidate();
}
private int duration = 400;
private Interpolator interpolator;
/**
* 动画
*/
private void startChartAnim() {
if (interpolator == null)
startChartAnim(duration);
else
startChartAnim(duration, interpolator);
}
/**
* 动画
*
* @param duration 时间
*/
public void startChartAnim(int duration) {
new DecelerateInterpolator();
provider.startAnim(this, duration, new DecelerateInterpolator());
}
public void startChartAnim(int duration, Interpolator interpolator) {
this.duration = duration;
this.interpolator = interpolator;
provider.startAnim(this, duration, interpolator);
}
@Override
public void onClick(float x, float y) {
PointF pointF = new PointF(x, y);
provider.clickPoint(pointF);
legend.onClickLegend(pointF);
invalidate();
}
@Override
public void onClickLegend(C c, Legend<C> legend) {
isCharEmpty = !provider.calculation(chartData);
if (!isFirstAnim) {
startChartAnim();
}
if (onClickLegendListener != null) {
onClickLegendListener.onClickLegend(c, legend);
}
}
public IEmpty getEmptyView() {
return emptyView;
}
public void setEmptyView(IEmpty emptyView) {
this.emptyView = emptyView;
}
public boolean isShowChartName() {
return isShowChartName;
}
public void setShowChartName(boolean showChartName) {
isShowChartName = showChartName;
}
public IChartTitle getChartTitle() {
return chartTitle;
}
public void setChartTitle(IChartTitle chartTitle) {
this.chartTitle = chartTitle;
}
public ILegend<C> getLegend() {
return legend;
}
/**
* 设置是否可以缩放
*
* @param zoom
*/
public void setZoom(boolean zoom) {
matrixHelper.setCanZoom(zoom);
}
@Override
public void onTableChanged(float translateX, float translateY) {
invalidate();
}
public MatrixHelper getMatrixHelper() {
return matrixHelper;
}
public void setOnClickColumnListener(OnClickColumnListener<C> onClickColumnListener) {
provider.setOnClickColumnListener(onClickColumnListener);
}
public void setOnClickLegendListener(OnClickLegendListener<C> onClickLegendListener) {
this.onClickLegendListener = onClickLegendListener;
}
/**
* 是否动画只执行一次
*
* @param isFirstAnim
*/
public void setFirstAnim(boolean isFirstAnim) {
this.isFirstAnim = isFirstAnim;
}
public boolean save() {
return save(new PicOption(chartData.getChartName()));
}
public boolean save(PicOption picOption) {
return new PicGeneration<BaseChart>().save(this, picOption);
}
}
\ No newline at end of file
package com.daivd.chart.core.base;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import com.daivd.chart.data.ColumnData;
import com.daivd.chart.matrix.RotateHelper;
import com.daivd.chart.provider.IProvider;
/**
* Created by huang on 2017/10/9.
* 饼图
*/
public abstract class BaseRotateChart<P extends IProvider<C>,C extends ColumnData> extends BaseChart<P,C> implements RotateHelper.OnRotateListener{
private RotateHelper rotateHelper;
private boolean isOnRotate;
public BaseRotateChart(Context context) {
super(context);
}
public BaseRotateChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BaseRotateChart(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void drawContent(Canvas canvas) {
provider.drawProvider(canvas, chartRect, matrixHelper, paint);
}
@Override
protected P initProvider() {
rotateHelper = new RotateHelper(this);
return initProvider(rotateHelper);
}
protected abstract P initProvider(RotateHelper rotateHelper);
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()== MotionEvent.ACTION_DOWN){
isOnRotate = rotateHelper.containsPoint(event);
}
if(isOnRotate){
super.onTouchEvent(event);
return rotateHelper.handlerTouchEvent(event);
}
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if(isOnRotate){
rotateHelper.onDisallowInterceptEvent(this,event);
}
return super.dispatchTouchEvent(event);
}
public void setRotate(boolean rotate) {
if(rotate){
setZoom(false);
}
rotateHelper.setRotate(rotate);
}
@Override
public void onRotate(double angle) {
invalidate();
}
}
package com.daivd.chart.data;
import com.daivd.chart.component.base.IAxis;
import java.util.List;
/**
* Created by huang on 2017/9/26.
*/
public class BarData extends ColumnData<List<Double>> {
public BarData(String name, String unit, int color, List<Double> chartYDataList) {
super(name,unit,color,chartYDataList);
}
public BarData(String name, String unit, int direction, int color, List<Double> datas) {
super(name,unit,direction,color,datas);
}
}
package com.daivd.chart.data;
import java.util.List;
/**
* Created by huang on 2017/10/19.
*/
public class BarLineData extends BarData {
public static final int BROKEN= 0;
public static final int CURVE = 1;
public static final int BAR = 2;
private int model = BAR;
public BarLineData(String name, String unit, int color, List<Double> chartYDataList) {
super(name, unit, color, chartYDataList);
}
public BarLineData(String name, int model,String unit, int color,List<Double> chartYDataList) {
super(name, unit, color, chartYDataList);
this.model = model;
}
public BarLineData(String name, String unit, int direction, int color, List<Double> datas) {
super(name, unit, direction, color, datas);
}
public BarLineData(String name,int model, String unit, int direction, int color, List<Double> datas) {
super(name, unit, direction, color, datas);
this.model = model;
}
public int getModel() {
return model;
}
public void setModel(int model) {
this.model = model;
}
}
package com.daivd.chart.data;
import java.util.Arrays;
import java.util.List;
/**
* Created by huang on 2017/9/26.
* chart data
*/
public class ChartData<T extends ColumnData> {
private String chartName;
private List<String> charXDataList;
private ScaleData scaleData = new ScaleData();
private List<T> columnDataList;
public ChartData(String chartName,List<String> charXDataList, T... columnDataList){
this.chartName = chartName;
this.charXDataList = charXDataList;
this.columnDataList = Arrays.asList(columnDataList);
}
public ChartData(String chartName,List<String> charXDataList, List<T> columnDataList){
this.chartName = chartName;
this.charXDataList = charXDataList;
this.columnDataList = columnDataList;
}
public String getChartName() {
return chartName;
}
public void setChartName(String chartName) {
this.chartName = chartName;
}
public boolean isEmpty() {
return columnDataList== null || this.columnDataList.size() ==0 ;
}
public List<String> getCharXDataList() {
return charXDataList;
}
public void setCharXDataList(List<String> charXDataList) {
this.charXDataList = charXDataList;
}
public ScaleData getScaleData() {
return scaleData;
}
public void setScaleData(ScaleData scaleData) {
this.scaleData = scaleData;
}
public List<T> getColumnDataList() {
return columnDataList;
}
public void setColumnDataList(List<T> columnDataList) {
this.columnDataList = columnDataList;
}
}
package com.daivd.chart.data;
import com.daivd.chart.component.base.IAxis;
/**
* Created by huang on 2017/9/26.
*/
public class ColumnData<T> {
public String name;
private String unit;
private int color;
private boolean isDraw = true;
private int direction = IAxis.AxisDirection.LEFT;
private T chartYDataList;
public ColumnData(String name, String unit, int color, T chartYDataList) {
this.name = name;
this.unit = unit;
this.color = color;
this.chartYDataList = chartYDataList;
}
public ColumnData(String name, String unit, int direction, int color, T datas) {
this.name = name;
this.unit = unit;
this.color = color;
this.chartYDataList = datas;
if(direction == IAxis.AxisDirection.LEFT || direction == IAxis.AxisDirection.RIGHT){
this.direction = direction;
}
}
public int getDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public T getChartYDataList() {
return chartYDataList;
}
public void setChartYDataList(T chartYDataList) {
this.chartYDataList = chartYDataList;
}
public boolean isDraw() {
return isDraw;
}
public void setDraw(boolean draw) {
isDraw = draw;
}
}
package com.daivd.chart.data;
import com.daivd.chart.data.style.LineStyle;
import com.daivd.chart.provider.component.line.ILineModel;
import com.daivd.chart.provider.component.point.IPoint;
import java.util.List;
/**
* Created by huang on 2017/9/26.
*/
public class LineData extends BarData {
private IPoint point;
private ILineModel lineModel;
private LineStyle lineStyle;
public LineData(String name, String unit, int color, List<Double> chartYDataList) {
super(name,unit,color,chartYDataList);
}
public LineData(String name, String unit, int direction, int color, List<Double> datas) {
super(name,unit,direction,color,datas);
}
public IPoint getPoint() {
return point;
}
public void setPoint(IPoint point) {
this.point = point;
}
public ILineModel getLineModel() {
return lineModel;
}
public void setLineModel(ILineModel lineModel) {
this.lineModel = lineModel;
}
public LineStyle getLineStyle() {
return lineStyle;
}
public void setLineStyle(LineStyle lineStyle) {
this.lineStyle = lineStyle;
}
}
package com.daivd.chart.data;
import android.graphics.Bitmap;
/**
* Created by huang on 2017/10/30.
* 保存图片Option
*/
public class PicOption {
private String fileName;
private String subFolderPath ="chart";
private String fileDescription="chart pic";
private Bitmap.CompressFormat format= Bitmap.CompressFormat.PNG;
private int quality = 100;
public PicOption(String fileName) {
this.fileName = fileName;
}
public String getFileName() {
return fileName;
}
public String getSubFolderPath() {
return subFolderPath;
}
public PicOption setSubFolderPath(String subFolderPath) {
this.subFolderPath = subFolderPath;
return this;
}
public String getFileDescription() {
return fileDescription;
}
public PicOption setFileDescription(String fileDescription) {
this.fileDescription = fileDescription;
return this;
}
public Bitmap.CompressFormat getFormat() {
return format;
}
public PicOption setFormat(Bitmap.CompressFormat format) {
this.format = format;
return this;
}
public int getQuality() {
return quality;
}
public PicOption setQuality(int quality) {
this.quality = quality;
return this;
}
}
package com.daivd.chart.data;
import com.daivd.chart.component.base.IAxis;
/**
* Created by huang on 2017/9/26.
*/
public class PieData extends ColumnData<Double> {
public PieData(String name, String unit, int color, Double chartYDataList) {
super(name, unit, color, chartYDataList);
}
public PieData(String name, String unit, IAxis.AxisDirection direction, int color, Double datas) {
super(name, unit, color, datas);
}
}
package com.daivd.chart.data;
import java.util.List;
/**
* Created by huang on 2017/9/26.
*/
public class RadarData extends BarData {
public RadarData(String name, String unit, int color, List<Double> chartYDataList) {
super(name,unit,color,chartYDataList);
}
}
package com.daivd.chart.data;
import java.util.List;
/**
* Created by huang on 2017/9/26.
*/
public class RoseData extends BarData {
public RoseData(String name, String unit, int color, List<Double> chartYDataList) {
super(name,unit,color,chartYDataList);
}
}
package com.daivd.chart.data;
import android.graphics.Rect;
import com.daivd.chart.component.base.IAxis;
import com.daivd.chart.matrix.MatrixHelper;
import java.util.ArrayList;
import java.util.List;
/**
* Created by huang on 2017/9/26.
* Scale data
*/
public class ScaleData {
public boolean isLeftHasValue = false;
public boolean isRightHasValue = false;
//竖轴数据
public double maxLeftValue; //最大值
public double minLeftValue; //最小值
//竖轴数据
public double maxRightValue; //最大值
public double minRightValue; //最小值
public int totalScale = 7; //刻度数量
public Rect scaleRect = new Rect();
//横轴数据
public int rowSize; //列数据
public float zoom = MatrixHelper.MIN_ZOOM; //放大比例
public List<Double> getScaleList(int direction){
List<Double> scaleList = new ArrayList<>();//asdfghjkl
int total = (int) (totalScale *zoom);
double scale = getTotalScaleLength(direction) /(total-1);
double minValue = getMinScaleValue(direction);
for(int i = 0;i < total;i++){
scaleList.add(minValue +scale*i);
}
return scaleList;
}
/**
* 获取最大刻度
* @param direction
* @return
*/
public double getMaxScaleValue(int direction){
if(direction == IAxis.AxisDirection.LEFT){
return maxLeftValue;
}
return maxRightValue;
}
/**
* 获取最小刻度
* @param direction
* @return
*/
public double getMinScaleValue(int direction){
if(direction == IAxis.AxisDirection.LEFT){
return minLeftValue;
}
return minRightValue;
}
/**
*获取总刻度值
* @param direction 方向
* @return 总刻度
*/
public double getTotalScaleLength(int direction){
if(direction == IAxis.AxisDirection.LEFT){
return maxLeftValue - minLeftValue;
}
return maxRightValue - minRightValue;
}
public Rect getOffsetRect(Rect rect, Rect offsetRect){
rect.left = rect.left + offsetRect.left;
rect.right = rect.right - offsetRect.right;
rect.top = rect.top + offsetRect.top;
rect.bottom = rect.bottom - offsetRect.bottom;
return rect;
}
public void resetScale(ScaleSetData scaleSetData,int direction){
if(direction == IAxis.AxisDirection.LEFT){
if(scaleSetData.isStartZoom()){
minLeftValue = 0;
}else {
if(scaleSetData.isHasMinValue()){
minLeftValue = scaleSetData.getMinValue();
}
}
if(scaleSetData.isHasMaxValue()){
maxLeftValue = scaleSetData.getMaxValue();
}
}else{
if(scaleSetData.isStartZoom()){
minRightValue = 0;
}else {
if(scaleSetData.isHasMinValue()){
minRightValue = scaleSetData.getMinValue();
}
}
if(scaleSetData.isHasMaxValue()){
maxRightValue = scaleSetData.getMaxValue();
}
}
}
}
package com.daivd.chart.data;
/**
* Created by huang on 2017/10/18.
*/
public class ScaleSetData {
private boolean isStartZoom;
private boolean isHasMaxValue;
private boolean isHasMinValue;
private double maxValue;
private double minValue;
public boolean isStartZoom() {
return isStartZoom;
}
public void setStartZoom(boolean startZoom) {
isHasMinValue = false;
isStartZoom = startZoom;
}
public boolean isHasMaxValue() {
return isHasMaxValue;
}
public boolean isHasMinValue() {
return isHasMinValue;
}
public double getMaxValue() {
return maxValue;
}
public void setMaxValue(double maxValue) {
isHasMaxValue = true;
this.maxValue = maxValue;
}
public double getMinValue() {
return minValue;
}
public void setMinValue(double minValue) {
isHasMinValue = true;
this.minValue = minValue;
}
}
package com.daivd.chart.data.format;
/**
* 格式化
* <p>用于横轴和竖轴文本格式化</p>
* @author huangyanbin
*/
public interface IFormat<T> {
String format( T t);
}
package com.daivd.chart.data.style;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import com.daivd.chart.utils.DensityUtils;
/**
* Created by huang on 2017/9/27.
*/
public class FontStyle implements IStyle{
public static int defaultFontSize = 12;
public static int defaultFontColor = Color.parseColor("#333333");
private int textSize;
private int textColor;
private int padding = 0;
private int scalePadding = 0;//刻度與軸的間距
public static void setDefaultTextSize(int defaultTextSize){
defaultFontSize = defaultTextSize;
}
public static void setDefaultTextSpSize(Context context,int defaultTextSpSize){
defaultFontSize = DensityUtils.sp2px(context,defaultTextSpSize);
}
public static void setDefaultTextColor(int defaultTextColor){
defaultFontColor = defaultTextColor;
}
public FontStyle() {
}
public FontStyle(int textSize, int textColor) {
this.textSize = textSize;
this.textColor = textColor;
}
public FontStyle(Context context,int sp, int textColor) {
this.textSize = DensityUtils.sp2px(context,sp);
this.textColor = textColor;
}
public int getScalePadding() {
return scalePadding;
}
public void setScalePadding(int scalePadding) {
this.scalePadding = scalePadding;
}
public int getTextSize() {
if(textSize == 0){
return defaultFontSize;
}
return textSize;
}
public FontStyle setTextSize(int textSize) {
this.textSize = textSize;
return this;
}
public FontStyle setTextSpSize(Context context,int sp){
this.setTextSize(DensityUtils.sp2px(context,sp));
return this;
}
public int getTextColor() {
if(textColor == 0){
return defaultFontColor;
}
return textColor;
}
public FontStyle setTextColor(int textColor) {
this.textColor = textColor;
return this;
}
public int getPadding() {
return padding;
}
public void setPadding(int padding) {
this.padding = padding;
}
@Override
public void fillPaint(Paint paint){
paint.setColor(getTextColor());
paint.setTextSize(getTextSize());
paint.setStyle(Paint.Style.FILL);
}
}
package com.daivd.chart.data.style;
import android.graphics.Paint;
/**
* Created by huang on 2017/9/27.
*/
public interface IStyle {
void fillPaint(Paint paint);
}
package com.daivd.chart.data.style;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PathEffect;
import com.daivd.chart.utils.DensityUtils;
/**
* Created by huang on 2017/9/27.
*/
public class LineStyle implements IStyle {
private float width;
private int color;
private PathEffect effect = new PathEffect();
private static float defaultLineSize = 2f;
private static int defaultLineColor = Color.parseColor("#888888");
public LineStyle() {
}
public LineStyle(float width, int color) {
this.width = width;
this.color = color;
}
public LineStyle(Context context, float dp, int color) {
this.width = DensityUtils.dp2px(context, dp);
this.color = color;
}
public static void setDefaultLineSize(float width) {
defaultLineSize = width;
}
public static void setDefaultLineSize(Context context, float dp) {
defaultLineSize = DensityUtils.dp2px(context, dp);
}
public static void setDefaultLineColor(int color) {
defaultLineColor = color;
}
public float getWidth() {
if (width == 0) {
return defaultLineSize;
}
return width;
}
public LineStyle setWidth(float width) {
this.width = width;
return this;
}
public LineStyle setWidth(Context context, int dp) {
this.width = DensityUtils.dp2px(context, dp);
return this;
}
public int getColor() {
if (color == 0) {
return defaultLineColor;
}
return color;
}
public LineStyle setColor(int color) {
this.color = color;
return this;
}
public LineStyle setEffect(PathEffect effect) {
this.effect = effect;
return this;
}
@Override
public void fillPaint(Paint paint) {
paint.setColor(getColor());
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(getWidth());
paint.setPathEffect(effect);
}
}
package com.daivd.chart.data.style;
import android.content.Context;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import com.daivd.chart.utils.DensityUtils;
/**
* Created by huang on 2017/9/27.
*/
public class PointStyle implements IStyle {
public static final int CIRCLE = 0;
public static final int SQUARE = 1;
public static final int RECT = 2;
private float width;
private int color;
private int shape;
private Paint.Style style;
private static float defaultPointSize = 10f;
private static int defaultPointColor = Color.parseColor("#888888");
private boolean isDraw = true;
public PointStyle() {
}
public PointStyle(float width, int color) {
this.width = width;
this.color = color;
}
public PointStyle(Context context, float dp, int color) {
this.width = DensityUtils.dp2px(context,dp);
this.color = color;
}
public static void setDefaultPointSize(float width){
defaultPointSize = width;
}
public static void setDefaultLineSize(Context context,float dp){
defaultPointSize = DensityUtils.dp2px(context,dp);
}
public static void setDefaultPointColor(int color){
defaultPointColor = color;
}
public float getWidth() {
if(width == 0){
return defaultPointSize;
}
return width;
}
public void setWidth(float width) {
this.width = width;
}
public void setWidth(Context context,int dp) {
this.width = DensityUtils.dp2px(context,dp);
}
public int getColor() {
if(color == 0){
return defaultPointColor;
}
return color;
}
public void setColor(int color) {
this.color = color;
}
public int getShape() {
return shape;
}
public void setShape(int shape) {
this.shape = shape;
}
public Paint.Style getStyle() {
if(style == null){
return Paint.Style.FILL;
}
return style;
}
public void setStyle(Paint.Style style) {
this.style = style;
}
public boolean isDraw() {
return isDraw;
}
public void setDraw(boolean draw) {
isDraw = draw;
}
@Override
public void fillPaint(Paint paint){
paint.setColor(getColor());
paint.setStyle(getStyle());
paint.setStrokeWidth(getWidth());
}
}
package com.daivd.chart.exception;
/**
* Created by huang on 2017/9/26.
*/
public class ChartException extends RuntimeException {
public ChartException(String message) {
super(message);
}
}
package com.daivd.chart.listener;
/**
* Created by huang on 2017/9/29.
*/
public interface ChartGestureObserver {
void onClick(float x,float y);
}
package com.daivd.chart.listener;
import java.util.ArrayList;
import java.util.List;
/**
* Created by huang on 2017/9/29.
*/
public abstract class Observable<T> {
public final ArrayList<T> observables = new ArrayList<>();
/**AttachObserver(通过实例注册观察者)
**/
public void register(T observer){
if(observer==null) throw new NullPointerException();
synchronized(observables){
if(!observables.contains(observer)){
observables.add(observer);
}
}
}
/**UnattachObserver(注销观察者)
**/
public void unRegister(T observer){
if(observer==null) throw new NullPointerException();
if(observables.contains(observer)){
observables.remove(observer);
}
}
public void unRegisterAll(){
synchronized(observables){
observables.clear();
}
}
/**Ruturnthesizeofobservers*/
public int countObservers(){
synchronized(observables){
return observables.size();
}
}
/**
*notify all observer(通知所有观察者,在子类中实现)
*/
public abstract void notifyObservers(List<T> observers);
}
package com.daivd.chart.listener;
/**
* Created by huang on 2017/11/4.
*/
public interface OnChartChangeListener {
void onTableChanged(float translateX, float translateY);
}
package com.daivd.chart.listener;
import com.daivd.chart.data.ColumnData;
/**
* Created by huang on 2017/9/30.
*/
public interface OnClickColumnListener<C extends ColumnData> {
void onClickColumn(C c,int position);
}
package com.daivd.chart.listener;
import com.daivd.chart.component.Legend;
import com.daivd.chart.data.ColumnData;
/**
* Created by huang on 2017/9/30.
*/
public interface OnClickLegendListener<C extends ColumnData> {
void onClickLegend(C c, Legend<C> legend);
}
package com.daivd.chart.matrix;
import android.view.MotionEvent;
import com.daivd.chart.core.base.BaseChart;
/**
* Created by huang on 2017/10/18.
*/
public interface ITouch {
/**
* 用于判断是否请求不拦截事件
* 解决手势冲突问题
* @param chart
* @param event
*/
void onDisallowInterceptEvent(BaseChart chart, MotionEvent event);
/**
* 处理touchEvent
* @param event
*/
boolean handlerTouchEvent(MotionEvent event);
}
package com.daivd.chart.matrix;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ViewConfiguration;
import android.view.ViewParent;
import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller;
import com.daivd.chart.core.base.BaseChart;
import com.daivd.chart.listener.ChartGestureObserver;
import com.daivd.chart.listener.Observable;
import com.daivd.chart.listener.OnChartChangeListener;
import java.util.List;
/**
* Created by huang on 2017/9/29.
* 图表放大缩小协助类
*/
public class MatrixHelper extends Observable<ChartGestureObserver> implements ITouch, ScaleGestureDetector.OnScaleGestureListener {
/**
* 最大缩放比
*/
private static final int MAX_ZOOM = 5;
/**
* 最小缩放比
*/
public static final int MIN_ZOOM = 1;
/**
* 当前缩放比
*/
private float zoom = MIN_ZOOM; //缩放比例 不得小于1
/**
* X轴位移的距离
*/
private int translateX; //以左上角为准,X轴位移的距离
/**
* y轴位移的距离
*/
private int translateY;//以左上角为准,y轴位移的距离
/**
* 缩放手势
*/
private ScaleGestureDetector mScaleGestureDetector;
/**
* 移动手势
*/
private GestureDetector mGestureDetector;
/**
* 是否可以缩放
*/
private boolean isCanZoom;
/**
* 是否正在缩放
*/
private boolean isScale; //是否正在缩放
/**
* 原始图表大小
*/
private Rect originalRect; //原始大小
/**
* 缩放之后的大小
*/
private Rect zoomRect;
/**
* 点击X,y点
*/
private float mDownX, mDownY;
/**
* 屏幕的手指点个数
*/
private int pointMode;
/**
* 宽缩放比
*/
private float widthMultiple =1;
/**
* 滚动辅助
*/
private Scroller scroller;
/**
* 最小速率
*/
private int mMinimumVelocity;
/**
* 是否正在飞滚
*/
private boolean isFling;
/**
* 飞滚速率
*/
private float flingRate = 0.8f; //速率
/**
* 图表缩放监听
*/
private OnChartChangeListener listener;
/**
* 缩放移动手势辅助类构造方法
* @param context context
*/
public MatrixHelper(Context context) {
mScaleGestureDetector = new ScaleGestureDetector(context, this);
mGestureDetector = new GestureDetector(context, new OnChartGestureListener());
final ViewConfiguration configuration = ViewConfiguration.get(context);
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
scroller = new Scroller(context);
}
/**
* 处理手势
*/
@Override
public boolean handlerTouchEvent(MotionEvent event) {
if (isCanZoom) {
mScaleGestureDetector.onTouchEvent(event);
}
mGestureDetector.onTouchEvent(event);
return true;
}
/**
* 判断是否需要接收触摸事件
*/
@Override
public void onDisallowInterceptEvent(BaseChart chart, MotionEvent event) {
if (!isCanZoom) {
return;
}
ViewParent parent = chart.getParent();
if (zoomRect == null || originalRect == null) {
parent.requestDisallowInterceptTouchEvent(false);
return;
}
switch (event.getAction()&MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
pointMode = 1;
//ACTION_DOWN的时候,赶紧把事件hold住
mDownX = event.getX();
mDownY = event.getY();
if(originalRect.contains((int)mDownX,(int)mDownY)){ //判断是否落在图表内容区中
parent.requestDisallowInterceptTouchEvent(true);
}else{
parent.requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
pointMode += 1;
parent.requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
if (pointMode > 1) {
parent.requestDisallowInterceptTouchEvent(true);
return;
}
float disX = event.getX() - mDownX;
float disY = event.getY() - mDownY;
boolean isDisallowIntercept = true;
if (Math.abs(disX) > Math.abs(disY)) {
if ((disX > 0 && toRectLeft()) || (disX < 0 && toRectRight())) { //向右滑动
isDisallowIntercept = false;
}
} else {
/* if ((disY > 0 && toRectTop()) || (disY < 0 && toRectBottom())) {*/
isDisallowIntercept = false;
/* }*/
}
parent.requestDisallowInterceptTouchEvent(isDisallowIntercept);
break;
case MotionEvent.ACTION_POINTER_UP:
pointMode -= 1;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
pointMode = 0;
parent.requestDisallowInterceptTouchEvent(false);
}
}
private boolean toRectLeft() {
return translateX <= -(zoomRect.width() - originalRect.width()) / 2;
}
private boolean toRectRight() {
return translateX >= (zoomRect.width() - originalRect.width()) / 2;
}
private boolean toRectBottom() {
return translateY >= (zoomRect.height() - originalRect.height()) / 2;
}
private boolean toRectTop() {
return translateY <= -(zoomRect.height() - originalRect.height()) / 2;
}
@Override
public void notifyObservers(List<ChartGestureObserver> observers) {
}
private float tempScale = MIN_ZOOM; //缩放比例 不得小于1
private int tempTranslateX; //以左上角为准,X轴位移的距离
private int tempTranslateY;//以左上角为准,y轴位移的距离
class OnChartGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public void onLongPress(MotionEvent e) {
super.onLongPress(e);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
translateX += distanceX;
translateY += distanceY;
notifyViewChanged();
return true;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
/**
* 飞滚
*/
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if(Math.abs(velocityX) >mMinimumVelocity || Math.abs(velocityY) >mMinimumVelocity) {
scroller.setFinalX(0);
scroller.setFinalY(0);
tempTranslateX = translateX;
tempTranslateY = translateY;
scroller.fling(0,0,(int)velocityX,(int)velocityY,-50000,50000
,-50000,50000);
isFling = true;
startFilingAnim(false);
}
return true;
}
//双击
@Override
public boolean onDoubleTap(MotionEvent e) {
if (isCanZoom) {
float oldZoom = zoom;
if (isScale) { //缩小
zoom = zoom / 1.5f;
if (zoom < 1) {
zoom = MIN_ZOOM;
isScale = false;
}
} else { //放大
zoom = zoom * 1.5f;
if (zoom > MAX_ZOOM) {
zoom = MAX_ZOOM;
isScale = true;
}
}
float factor = zoom / oldZoom;
resetTranslate(factor);
notifyObservers(observables);
}
return true;
}
//单击
@Override
public boolean onSingleTapUp(MotionEvent e) {
notifyViewChanged();
for (ChartGestureObserver observer : observables) {
observer.onClick(e.getX(), e.getY());
}
return true;
}
}
private Point startPoint = new Point(0, 0);
private Point endPoint = new Point();
private TimeInterpolator interpolator = new DecelerateInterpolator();
private PointEvaluator evaluator= new PointEvaluator();
/**
* 开始飞滚
* @param doubleWay 双向飞滚
*/
private void startFilingAnim(boolean doubleWay) {
int scrollX =Math.abs(scroller.getFinalX());
int scrollY =Math.abs(scroller.getFinalY());
if(doubleWay){
endPoint.set((int) (scroller.getFinalX() * flingRate),
(int) (scroller.getFinalY() * flingRate));
}else {
if (scrollX > scrollY) {
endPoint.set((int) (scroller.getFinalX() * flingRate), 0);
} else {
endPoint.set(0, (int) (scroller.getFinalY() * flingRate));
}
}
final ValueAnimator valueAnimator = ValueAnimator.ofObject(evaluator,startPoint,endPoint);
valueAnimator.setInterpolator(interpolator);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if(isFling) {
Point point = (Point) animation.getAnimatedValue();
translateX = tempTranslateX - point.x;
translateY = tempTranslateY - point.y;
notifyViewChanged();
}else{
animation.cancel();
}
}
});
int duration = (int)(Math.max(scrollX,scrollY)*flingRate)/2;
valueAnimator.setDuration(duration>300 ?300:duration);
valueAnimator.start();
}
public void notifyViewChanged(){
if(listener != null) {
listener.onTableChanged(translateX, translateY);
}
}
/**
* 缩放开始
*/
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
tempScale = this.zoom;
return true;
}
/**
* 正在缩放
*/
@Override
public boolean onScale(ScaleGestureDetector detector) {
float oldZoom = zoom;
float scale = detector.getScaleFactor();
this.zoom = (float) (tempScale * Math.pow(scale, 2));
float factor = zoom / oldZoom;
resetTranslate(factor);
notifyObservers(observables);
if (this.zoom > MAX_ZOOM) {
this.zoom = MAX_ZOOM;
return true;
} else if (this.zoom < 1) {
this.zoom = 1;
return true;
}
return false;
}
/**
* 缩放结束
*/
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
}
/**
* 重新计算偏移量
* * @param factor
*/
private void resetTranslate(float factor) {
translateX = (int) (translateX * factor);
translateY = (int) (translateY * factor);
}
/**
* 获取图片内容的缩放大小
*
* @param providerRect 内容的大小
* @return 缩放后内容的大小
*/
public Rect getZoomProviderRect(Rect providerRect) {
originalRect = providerRect;
Rect scaleRect = new Rect();
int oldw = providerRect.width();
int oldh = providerRect.height();
int multipleWidth = (int) (oldw *widthMultiple);
int newWidth = (int) (multipleWidth * zoom);
int newHeight = (int) (oldh * zoom);
int offsetX = (int) (oldw*(zoom-1))/2;
int offsetY =(int) (oldh*(zoom-1))/2;
int maxTranslateLeft = (int)Math.abs(oldw*(zoom-1) / 2);
int maxTranslateRight = newWidth - oldw - offsetX;
int maxTranslateY = Math.abs(newHeight - oldh) / 2;
if(translateX >maxTranslateRight){
translateX = maxTranslateRight;
}
if(translateX < -maxTranslateLeft){
translateX = -maxTranslateLeft;
}
if (Math.abs(translateY) > maxTranslateY) {
translateY = translateY > 0 ? maxTranslateY : -maxTranslateY;
}
scaleRect.left = providerRect.left - offsetX - translateX;
scaleRect.right=scaleRect.left+newWidth;
scaleRect.top = providerRect.top - offsetY - translateY;
scaleRect.bottom = scaleRect.top+newHeight;
zoomRect = scaleRect;
return scaleRect;
}
/**
* 获取宽的倍数
* <p>一旦设置倍数,宽度会变大相应倍数,这样就可以横向滑动了。</p>
*/
public float getWidthMultiple() {
return widthMultiple;
}
/**
* 设置宽的倍数
* <p>一旦设置倍数,宽度会变大相应倍数,这样就可以横向滑动了。</p>
* @param widthMultiple 宽的倍数
*/
public void setWidthMultiple(float widthMultiple) {
this.widthMultiple = widthMultiple;
}
/**
* 是否可以缩放
* @return 是否可以缩放
*/
public boolean isCanZoom() {
zoom = 1f;
return isCanZoom;
}
/**
* 设置是否可以缩放
* @param canZoom 是否可以缩放
*/
public void setCanZoom(boolean canZoom) {
isCanZoom = canZoom;
}
/**
* 获取当前缩放比例
* @return 缩放比例
*/
public float getZoom() {
return zoom;
}
/**
* 设置缩放滚动监听
* @return 缩放滚动监听
*/
public OnChartChangeListener getOnTableChangeListener() {
return listener;
}
/**
* 获取缩放滚动监听
* @param onTableChangeListener 缩放滚动监听
*/
public void setOnTableChangeListener(OnChartChangeListener onTableChangeListener) {
this.listener = onTableChangeListener;
}
}
package com.daivd.chart.matrix;
import android.animation.TypeEvaluator;
import android.graphics.Point;
/**
* Created by huang on 2017/11/3.
*/
public class PointEvaluator implements TypeEvaluator {
private Point point = new Point();
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
Point startPoint = (Point) startValue;
Point endPoint = (Point) endValue;
int x = (int) (startPoint.x + fraction * (endPoint.x - startPoint.x));
int y = (int) (startPoint.y + fraction * (endPoint.y - startPoint.y));
point.set(x,y);
return point;
}
}
package com.daivd.chart.matrix;
import android.graphics.Rect;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.ViewParent;
import com.daivd.chart.core.base.BaseChart;
/**
* Created by huang on 2017/10/10.
*/
public class RotateHelper implements ITouch {
private int mRadius;
/**
* 检测按下到抬起时旋转的角度
*/
private float mTmpAngle;
/**
* 检测按下到抬起时使用的时间
*/
private long mDownTime;
/**
* 判断是否正在自动滚动
*/
private boolean isFling;
/**
* 布局时的开始角度
*/
private double mStartAngle = 0;
/**
* 当每秒移动角度达到该值时,认为是快速移动
*/
private static final int FLINGABLE_VALUE = 300;
/**
* 如果移动角度达到该值,则屏蔽点击
*/
private static final int NOCLICK_VALUE = 3;
/**
* 当每秒移动角度达到该值时,认为是快速移动
*/
private int mFlingableValue = FLINGABLE_VALUE;
private Handler mHandler = new Handler();
/**
* 记录上一次的x,y坐标
*/
private float mLastX;
private float mLastY;
private boolean isRotate;
private Rect originRect;
/**
* 自动滚动的Runnable
*/
private AutoFlingRunnable mFlingRunnable;
private OnRotateListener listener;
public RotateHelper(OnRotateListener listener){
this.listener = listener;
}
@Override
public boolean handlerTouchEvent(MotionEvent event) {
if(!isRotate()){
return false;
}
float x = event.getX();
float y = event.getY();
// Log.e("TAG", "x = " + x + " , y = " + y);
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
mLastX = x;
mLastY = y;
mDownTime = System.currentTimeMillis();
mTmpAngle = 0;
// 如果当前已经在快速滚动
if (isFling)
{
// 移除快速滚动的回调
mHandler.removeCallbacks(mFlingRunnable);
isFling = false;
return true;
}
break;
case MotionEvent.ACTION_MOVE:
/**
* 获得开始的角度
*/
float start = getAngle(mLastX, mLastY);
/**
* 获得当前的角度
*/
float end = getAngle(x, y);
// Log.e("TAG", "start = " + start + " , end =" + end);
// 如果是一、四象限,则直接end-start,角度值都是正值
if (getQuadrant(x, y) == 1 || getQuadrant(x, y) == 4)
{
mStartAngle += end - start;
mTmpAngle += end - start;
} else
// 二、三象限,色角度值是付值
{
mStartAngle += start - end;
mTmpAngle += start - end;
}
// 重新布局
listener.onRotate(mStartAngle);
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_UP:
// 计算,每秒移动的角度
float anglePerSecond = mTmpAngle * 1000
/ (System.currentTimeMillis() - mDownTime);
// Log.e("TAG", anglePrMillionSecond + " , mTmpAngel = " +
// mTmpAngle);
// 如果达到该值认为是快速移动
if (Math.abs(anglePerSecond) > mFlingableValue && !isFling)
{
// post一个任务,去自动滚动
mHandler.post(mFlingRunnable = new AutoFlingRunnable(anglePerSecond));
return true;
}
// 如果当前旋转角度超过NOCLICK_VALUE屏蔽点击
if (Math.abs(mTmpAngle) > NOCLICK_VALUE)
{
return true;
}
break;
}
return true;
}
@Override
public void onDisallowInterceptEvent(BaseChart chart, MotionEvent event){
ViewParent parent = chart.getParent();
if (!isRotate() || originRect == null) {
parent.requestDisallowInterceptTouchEvent(false);
return;
}
switch (event.getAction()&MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if(containsPoint(event)){
parent.requestDisallowInterceptTouchEvent(true);
}else {
parent.requestDisallowInterceptTouchEvent(false);
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
parent.requestDisallowInterceptTouchEvent(false);
break;
}
}
public boolean containsPoint(MotionEvent event){
if(originRect != null) {
float x = event.getX();
float y = event.getY();
int centerY = originRect.centerY();
int centerX = originRect.centerX();
return x >= centerX - mRadius && x <= centerX + mRadius
&& y >= centerY - mRadius && y <= centerY + mRadius;
}
return false;
}
/**
* 自动滚动的任务
*
* @author zhy
*
*/
private class AutoFlingRunnable implements Runnable
{
private float angelPerSecond;
public AutoFlingRunnable(float velocity)
{
this.angelPerSecond = velocity;
}
public void run()
{
// 如果小于20,则停止
if ((int) Math.abs(angelPerSecond) < 20)
{
isFling = false;
return;
}
isFling = true;
// 不断改变mStartAngle,让其滚动,/30为了避免滚动太快
mStartAngle += (angelPerSecond / 30);
// 逐渐减小这个值
angelPerSecond /= 1.0666F;
mHandler.postDelayed(this, 30);
// 重新布局
listener.onRotate(mStartAngle);
}
}
/**
* 根据触摸的位置,计算角度
*
* @param xTouch
* @param yTouch
* @return
*/
private float getAngle(float xTouch, float yTouch)
{
double x = xTouch- originRect.left - (mRadius );
double y = yTouch- originRect.top - (mRadius );
return (float) (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
}
/**
* 根据当前位置计算象限
*
* @param x
* @param y
* @return
*/
private int getQuadrant(float x, float y)
{
int tmpX = (int) (x- originRect.left - mRadius );
int tmpY = (int) (y- originRect.top - mRadius );
if (tmpX >= 0)
{
return tmpY >= 0 ? 4 : 1;
} else
{
return tmpY >= 0 ? 3 : 2;
}
}
public interface OnRotateListener{
void onRotate(double angle);
}
public void setRadius(int radius) {
this.mRadius = radius;
}
public void setOriginRect(Rect originRect){
this.originRect = originRect;
}
public double getStartAngle() {
return mStartAngle;
}
public boolean isRotate() {
return isRotate;
}
public void setRotate(boolean rotate) {
isRotate = rotate;
}
}
package com.daivd.chart.provider;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.view.animation.Interpolator;
import com.daivd.chart.core.base.BaseChart;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.ColumnData;
import com.daivd.chart.listener.OnClickColumnListener;
import com.daivd.chart.matrix.MatrixHelper;
import com.daivd.chart.provider.component.mark.IMark;
import com.daivd.chart.provider.component.text.IText;
/**
* Created by huang on 2017/9/26.
*/
public abstract class BaseProvider<C extends ColumnData> implements IProvider<C> {
private float progress = 1;
protected PointF pointF;
protected IMark<C> markView;
private boolean isOpenMark;
private boolean isShowText =true;
protected ChartData<C> chartData;
private Rect providerRect;
private IText text;
protected OnClickColumnListener<C> onClickColumnListener;
@Override
public boolean calculation(ChartData<C> chartData) {
this.chartData = chartData;
return calculationChild(chartData);
}
public abstract boolean calculationChild(ChartData<C> chartData);
@Override
public void drawProvider(Canvas canvas, Rect rect, MatrixHelper helper, Paint paint) {
providerRect = rect;
matrixRectStart(canvas,rect);
Rect zoomRect = helper.getZoomProviderRect(rect);
drawProvider(canvas,zoomRect,rect,paint);
matrixRectEnd(canvas,rect);
}
protected void matrixRectStart(Canvas canvas, Rect rect){
canvas.save();
canvas.clipRect(rect);
}
protected void matrixRectEnd(Canvas canvas, Rect rect){
canvas.restore();
}
protected abstract void drawProvider(Canvas canvas, Rect zoomRect,Rect rect, Paint paint);
@Override
public void clickPoint(PointF point) {
pointF = point;
}
@Override
public void startAnim(final BaseChart chartView, int duration, Interpolator interpolator) {
ValueAnimator animator = ValueAnimator.ofFloat(0,1);
animator.setDuration(duration);
animator.setInterpolator(interpolator);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
progress = (float) animation.getAnimatedValue();
chartView.invalidate();
}
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
progress = 1;
chartView.invalidate();
}
@Override
public void onAnimationEnd(Animator animation) {
progress = 1;
chartView.invalidate();
}
});
animator.start();
}
public void drawPointText(Canvas canvas,double value,float x,float y,int position,int line,Paint paint){
if(text != null) {
String val = String.valueOf(value);
if (containsRect(x,y)) {
text.drawText(canvas,val,x,y,position,line,paint);
}
}
}
public boolean containsRect( float x,float y){
Rect rect = providerRect;
return y>= rect.top -1 && y<= rect.bottom+1
&& x>= rect.left-1 && x<= rect.right+1;
}
public boolean isOpenMark() {
return isOpenMark;
}
public void setOpenMark(boolean openMark) {
isOpenMark = openMark;
}
public abstract double[] setMaxMinValue(double maxMinValue, double minValue);
@Override
public void setMarkView(IMark markView) {
this.markView = markView;
}
protected float getAnimValue(float value){
return value*progress;
}
public Rect getProviderRect() {
return providerRect;
}
public float getProgress() {
return progress;
}
public boolean isShowText() {
return isShowText;
}
public void setShowText(boolean showText) {
isShowText = showText;
}
public void setOnClickColumnListener(OnClickColumnListener<C> onClickColumnListener) {
this.onClickColumnListener = onClickColumnListener;
}
public IText getText() {
return text;
}
public void setText(IText text) {
this.text = text;
}
}
package com.daivd.chart.provider;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.view.animation.Interpolator;
import com.daivd.chart.core.base.BaseChart;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.ColumnData;
import com.daivd.chart.listener.OnClickColumnListener;
import com.daivd.chart.provider.component.mark.IMark;
import com.daivd.chart.matrix.MatrixHelper;
/**
* Created by huang on 2017/9/26.
*/
public interface IProvider<C extends ColumnData> {
boolean calculation( ChartData<C> chartData);
void drawProvider(Canvas canvas, Rect rect, MatrixHelper helper, Paint paint);
void clickPoint(PointF point);
void startAnim(BaseChart chartView, int duration, Interpolator interpolator);
void setMarkView(IMark markView);
void setOnClickColumnListener(OnClickColumnListener<C> onClickColumnListener);
}
package com.daivd.chart.provider.barLine;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import com.daivd.chart.data.BarData;
/**柱状内容绘制
* Created by huang on 2017/9/26.
*/
public class Bar3DProvider extends BarProvider<BarData> {
/**
* 绘制柱
* @param canvas 画布
* @param rect 范围
* @param value 数值
* @param position 位置
* @param line 线位置
* @param paint 画笔
*/
@Override
protected void drawBar(Canvas canvas,Rect rect,double value,int position,int line,Paint paint){
canvas.drawRect(rect, paint);
float w = rect.right - rect.left;
float offsetY= w/2;
float offsetX = w/3f;
Path path = new Path();
path.moveTo(rect.left,rect.top);
path.lineTo(rect.left+offsetX,rect.top-offsetY);
path.lineTo(rect.right+offsetX,rect.top-offsetY);
path.lineTo(rect.right,rect.top);
path.close();
canvas.drawPath(path,paint);
path.reset();
path.moveTo(rect.right,rect.top);
path.lineTo(rect.right,rect.bottom);
path.lineTo(rect.right+offsetX,rect.bottom-offsetY);
path.lineTo(rect.right+offsetX,rect.top-offsetY);
path.close();
canvas.drawPath(path,paint);
drawPointText(canvas,value,(rect.right + rect.left) / 2, rect.top-offsetY,position,line, paint );
}
@Override
public double[] setMaxMinValue(double maxValue, double minValue) {
double dis = Math.abs(maxValue -minValue);
maxValue = maxValue + dis*0.4;
if(minValue >0){
minValue = 0;
}else{
minValue = minValue - dis*0.4;
}
return new double[]{maxValue,minValue};
}
}
package com.daivd.chart.provider.barLine;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import com.daivd.chart.data.BarLineData;
import com.daivd.chart.data.style.LineStyle;
import com.daivd.chart.exception.ChartException;
import com.daivd.chart.provider.component.line.BrokenLineModel;
import com.daivd.chart.provider.component.line.CurveLineModel;
import java.util.ArrayList;
import java.util.List;
/**状状图和线性图结合
* Created by huang on 2017/9/26.
*/
public class BarLineProvider extends BarProvider<BarLineData> {
private List<Float> pointX = new ArrayList<>();
private List<Float> pointY = new ArrayList<>();
private LineStyle lineStyle = new LineStyle();
@Override
public void drawProvider(Canvas canvas, Rect zoomRect, Rect rect, Paint paint) {
paint.setStyle(Paint.Style.FILL);
List<BarLineData> columnDataList = chartData.getColumnDataList();
int barColumnSize = getBarColumnSize();
int rowSize = chartData.getCharXDataList().size();
double perWidth = zoomRect.width()/(barColumnSize*rowSize);
double perBarWidth =perWidth - getCategoryPadding() / 2;
int columnSize = columnDataList.size();
int barPosition =-1;
for (int i = 0; i < columnSize; i++) {
BarLineData columnData = columnDataList.get(i);
if (!columnData.isDraw()) {
continue;
}
if(columnData.getModel() == BarLineData.BAR) {
barPosition++;
}
for (int j = 0; j < rowSize; j++) {
double value = columnData.getChartYDataList().get(j);
int top = (int) getStartY(zoomRect, value, columnData.getDirection());
if(columnData.getModel() == BarLineData.BAR) {
int left = (int) (((j * barColumnSize + barPosition) * perBarWidth)
+ j * getCategoryPadding() + zoomRect.left);
int right = (int) (left + perBarWidth) - getSeriesPadding();
int bottom = zoomRect.bottom;
paint.setColor(columnData.getColor());
Rect barRect = new Rect(left, top, right, bottom);
drawBar(canvas, barRect, value,i,j, paint);
}else{
float x = (float)(zoomRect.left+perWidth*(j+0.5));
drawLine(canvas,j== 0,j == rowSize-1,columnData,x,top,value,i,j,paint);
}
}
}
drawLevelLine(canvas, zoomRect, paint);
}
protected void drawLine(Canvas canvas, boolean isNewBar,boolean isLast, BarLineData columnData, float x,float y, double value,int position,int line, Paint paint) {
if(columnData.getModel() ==BarLineData.CURVE
|| columnData.getModel() ==BarLineData.BROKEN){
if(isNewBar){
pointX.clear();
pointY.clear();
}
pointX.add(x);
pointY.add(y);
drawPointText(canvas,value,x, y,position,line,paint);
if(isLast){
Path path;
if(columnData.getModel() ==BarLineData.CURVE){
path = new CurveLineModel().getLinePath(pointX,pointY);
}else{
path = new BrokenLineModel().getLinePath(pointX,pointY);
}
lineStyle.setColor(paint.getColor());
lineStyle.fillPaint(paint);
canvas.drawPath(path,paint);
}
}
}
protected int getBarColumnSize() {
List<BarLineData> lineDates = chartData.getColumnDataList();
int barSize = 0;
for(int i =0;i < lineDates.size();i++){
if(lineDates.get(i).getModel() == BarLineData.BAR){
barSize++;
}
}
if(barSize == 0){
throw new ChartException("There must be a set of bar data!");
}
return barSize;
}
public LineStyle getLineStyle() {
return lineStyle;
}
public void setLineStyle(LineStyle lineStyle) {
this.lineStyle = lineStyle;
}
}
package com.daivd.chart.provider.barLine;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import com.daivd.chart.data.BarData;
import com.daivd.chart.utils.ColorUtils;
import java.util.List;
/**
* 柱状内容绘制
* Created by huang on 2017/9/26.
*/
public class BarProvider<C extends BarData> extends BaseBarLineProvider<C> {
private int categoryPadding = 20;
private int seriesPadding = 10;
@Override
public void drawProvider(Canvas canvas, Rect zoomRect, Rect rect, Paint paint) {
paint.setStyle(Paint.Style.FILL);
paint.setTextAlign(Paint.Align.LEFT);
List<C> columnDataList = chartData.getColumnDataList();
int columnSize = columnDataList.size();
int rowSize = chartData.getCharXDataList().size();
double width = (zoomRect.width()-(columnSize+1)*categoryPadding) / (columnSize * rowSize);
PointF clickPoint = null;
int clickPosition = 0;
int clickColumnPosition = 0;
boolean isClickRect1 = (pointF != null && rect.contains((int) pointF.x, (int) pointF.y));
boolean isClickRect = false;
for (int i = 0; i < columnSize; i++) {
for (int j = 0; j < rowSize; j++) {
C columnData = columnDataList.get(i);
if (!columnData.isDraw()) {
continue;
}
double value = columnData.getChartYDataList().get(j);
int left = (int) (((j * columnSize + i) * width)
+ j * categoryPadding + zoomRect.left);
int right = (int) (left + width) - seriesPadding;
int top = (int) getStartY(zoomRect, value, columnData.getDirection());
int bottom = zoomRect.bottom;
paint.setColor(columnData.getColor());
if (isClickRect1 && isClickRect(left, right, top, bottom)) {
paint.setColor(ColorUtils.getDarkerColor(columnData.getColor()));
isClickRect = true;
clickPoint = new PointF((left + right) / 2, top);
clickPosition = j;
clickColumnPosition = i;
if (onClickColumnListener != null) {
onClickColumnListener.onClickColumn(columnData, j);
}
}
Rect barRect = new Rect(left, top, right, bottom);
drawBar(canvas, barRect, value,i,j, paint);
drawTip(canvas,left+barRect.width()/2,top,columnData,j);
}
}
drawLevelLine(canvas, zoomRect, paint);
if (isClickRect && containsRect(clickPoint.x, clickPoint.y)) {
drawCross(canvas, clickPoint.x, clickPoint.y, zoomRect, paint);
super.matrixRectEnd(canvas, rect);
drawMark(canvas,clickPoint.x, clickPoint.y,rect, clickPosition, clickColumnPosition);
}
}
@Override
protected void matrixRectEnd(Canvas canvas, Rect rect) {
}
protected void drawBar(Canvas canvas, Rect rect,double value, int position,int line,Paint paint) {
canvas.drawRect(rect, paint);
drawPointText(canvas, value, (rect.right + rect.left) / 2, rect.top, position,line,paint);
}
private void drawCross(Canvas canvas, float x, float y, Rect rect, Paint paint) {
if (isOpenCross() && getCross() != null) {
PointF pointF = new PointF(x, y);
getCross().drawCross(canvas, pointF, rect, paint);
}
}
protected boolean isClickRect(float left, float right, float top, float bottom) {
return pointF != null && pointF.x >= left && pointF.x <= right && pointF.y >= top && pointF.y <= bottom;
}
@Override
public double[] setMaxMinValue(double maxValue, double minValue) {
double dis = Math.abs(maxValue - minValue);
maxValue = maxValue + dis * 0.2;
if (minValue > 0) {
minValue = 0;
} else {
minValue = minValue - dis * 0.2;
}
return new double[]{maxValue, minValue};
}
public int getSeriesPadding() {
return seriesPadding;
}
public void setSeriesPadding(int seriesPadding) {
this.seriesPadding = seriesPadding;
}
public int getCategoryPadding() {
return categoryPadding;
}
public void setCategoryPadding(int categoryPadding) {
this.categoryPadding = categoryPadding;
}
}
package com.daivd.chart.provider.barLine;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import com.daivd.chart.component.base.IAxis;
import com.daivd.chart.data.BarData;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.ScaleData;
import com.daivd.chart.exception.ChartException;
import com.daivd.chart.provider.BaseProvider;
import com.daivd.chart.provider.component.cross.ICross;
import com.daivd.chart.provider.component.level.ILevel;
import com.daivd.chart.provider.component.tip.ITip;
import java.util.ArrayList;
import java.util.List;
/**线和柱状内容绘制
* Created by huang on 2017/9/26.
*/
public abstract class BaseBarLineProvider<C extends BarData> extends BaseProvider<C> {
private ICross cross;
private boolean isOpenCross;
protected ITip<C,?> tip;
private List<ILevel> levelLine = new ArrayList<>();
private float chartPercent = 1;
private boolean isFromBottom;
@Override
public boolean calculationChild( ChartData<C> chartData) {
this.chartData = chartData;
ScaleData scaleData =this.chartData.getScaleData();
List<C> columnDataList = chartData.getColumnDataList();
if(columnDataList == null || columnDataList.size() == 0){
return false;
}
scaleData.rowSize = chartData.getCharXDataList().size();
int columnSize = columnDataList.size();
for(int i = 0 ; i <columnSize; i++){
BarData columnData = columnDataList.get(i);
if(!columnData.isDraw()){
continue;
}
List<Double> chartYDataList = columnData.getChartYDataList();
if(chartYDataList == null || chartYDataList.size() == 0){
throw new ChartException("Please set up Column data");
}
// if(chartYDataList.size() != scaleData.rowSize){
// throw new ChartException("Column rows data inconsistency");
// }
double[] scale = getColumnScale(chartYDataList);
scale = setMaxMinValue(scale[0],scale[1]);
if(columnData.getDirection() == IAxis.AxisDirection.LEFT){
if(!scaleData.isLeftHasValue){
//asdfghjkl
scaleData.maxLeftValue = scale[0];
scaleData.minLeftValue = scale[1];
scaleData.isLeftHasValue = true;
}else{
//asdfghjkl
scaleData.maxLeftValue = Math.max( scaleData.maxLeftValue,scale[0]);
scaleData.minLeftValue = Math.min( scaleData.minLeftValue,scale[1]);
}
}else{
if(!scaleData.isRightHasValue){
scaleData.maxRightValue = scale[0];
scaleData.minRightValue= scale[1];
scaleData.isRightHasValue = true;
}else{
scaleData.maxRightValue = Math.max(scaleData.maxRightValue,scale[0]);
scaleData.minRightValue = Math.min(scaleData.minRightValue,scale[1]);
}
}
}
if(scaleData.maxLeftValue == 0){
scaleData.maxLeftValue = 18000;
}
return chartData.getScaleData().rowSize != 0;
}
private double[] getColumnScale(List<Double> values) {
double maxValue = 0;
double minValue =0;
int size = values.size();
for(int j= 0;j < size;j++) {
double d = values.get(j) ;
if(j == 0){
maxValue = d;
minValue = d;
}
if (maxValue < d){
maxValue = d;
}else if(minValue >d){
minValue = d;
}
}
return new double[] {maxValue,minValue};
}
protected float getStartY(Rect zoomRect, double value, int direction){
ScaleData scaleData = chartData.getScaleData();
double minValue = scaleData.getMinScaleValue(direction);
double totalScaleLength = scaleData.getTotalScaleLength(direction);
float length = (float) ((value - minValue) * zoomRect.height()*chartPercent / totalScaleLength);
return zoomRect.bottom-(isFromBottom?0:(1-chartPercent)/2*zoomRect.height()) - length;
}
/**
* 绘制水平线
*/
void drawLevelLine(Canvas canvas, Rect zoomRect, Paint paint){
if(levelLine.size() > 0) {
for(ILevel level:levelLine){
float levelY = getStartY(zoomRect,level.getValue(),level.getAxisDirection());
if(containsRect(getProviderRect().centerX(),levelY)) {
level.drawLevel(canvas, getProviderRect(), levelY, paint);
}
}
}
}
/**
*绘制提示
*/
void drawTip(Canvas canvas,float x, float y,C c,int position){
if(tip != null){
tip.drawTip(canvas,x,y,getProviderRect(),c,position);
}
}
void drawMark(Canvas canvas,float x, float y,Rect rect, int position, int columnPosition) {
if (markView != null && isOpenMark()) {
markView.drawMark(canvas,x, y, rect,chartData.getCharXDataList().get(position),
chartData.getColumnDataList().get(columnPosition), position);
}
}
public abstract double[] setMaxMinValue(double maxMinValue, double minValue);
public void addLevelLine(ILevel levelLine) {
this.levelLine.add(levelLine);
}
public boolean isOpenCross() {
return isOpenCross;
}
public void setOpenCross(boolean openCross) {
isOpenCross = openCross;
}
public ICross getCross() {
return cross;
}
public void setCross(ICross cross) {
this.cross = cross;
}
public List<ILevel> getLevelLine() {
return levelLine;
}
public ITip<C,?> getTip() {
return tip;
}
public void setTip(ITip<C,?> tip) {
this.tip = tip;
}
public float getChartPercent() {
return chartPercent;
}
public boolean isFromBottom() {
return isFromBottom;
}
public void setFromBottom(boolean fromBottom) {
isFromBottom = fromBottom;
}
public void setChartPercent(float chartPercent) {
this.chartPercent = chartPercent;
}
}
package com.daivd.chart.provider.barLine;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.Log;
import com.daivd.chart.data.LineData;
import com.daivd.chart.data.style.LineStyle;
import com.daivd.chart.provider.component.grid.IGrid;
import com.daivd.chart.provider.component.line.BrokenLineModel;
import com.daivd.chart.provider.component.line.ILineModel;
import com.daivd.chart.provider.component.path.IPath;
import com.daivd.chart.provider.component.path.LinePath;
import com.daivd.chart.provider.component.point.IPoint;
import com.daivd.chart.utils.ColorUtils;
import java.util.ArrayList;
import java.util.List;
/**
* 线内容绘制
* Created by huang on 2017/9/26.
*/
public class LineProvider extends BaseBarLineProvider<LineData> {
private LineStyle lineStyle = new LineStyle();
private IPoint point;
private int rowSize;
private boolean isArea; //是否打开面积图
private boolean isDrawLine = true;
private int filterPointTextCount = 7; //最多显示30个点文字
private ILineModel lineModel = new BrokenLineModel();
private IPath path;
private int perWidth;
private IGrid grid;
private boolean isStartZero = true;
private int areaAlpha = 125;
@Override
public void drawProvider(Canvas canvas, Rect zoomRect, Rect rect, Paint paint) {
List<LineData> columnDataList = chartData.getColumnDataList();//asdfghjkl
int columnSize = columnDataList.size();
rowSize = chartData.getCharXDataList().size();
int filter = rowSize / filterPointTextCount;
filter = filter < 1 ? 1 : filter;
if (grid != null) {
grid.drawClickBg(canvas, pointF, zoomRect, perWidth, paint);
}
for (int i = 0; i < columnSize; i++) {
LineData lineData = columnDataList.get(i);
paint.setColor(lineData.getColor());
if (!lineData.isDraw()) {
continue;
}
List<Float> pointX = new ArrayList<>();
List<Float> pointY = new ArrayList<>();
List<Double> chartYDataList = lineData.getChartYDataList();
for (int j = 0; j < chartYDataList.size(); j++) {
double value = chartYDataList.get(j);
float x = getStartX(zoomRect, j);
float y = getStartY(zoomRect, value, lineData.getDirection());
if (grid != null && i == 0) {
grid.drawGrid(canvas, x, zoomRect, perWidth, paint);
grid.drawColumnContent(canvas, j, zoomRect, rect, perWidth, paint);
}
pointX.add(x);
pointY.add(y);
if (j % filter == 0) {
drawPointText(canvas, value, x, y, j, i, paint);
}
}
canvas.save();
canvas.clipRect(rect);
drawLine(canvas, rect, zoomRect, paint, lineData, pointX, pointY);
drawTip(canvas, pointX, pointY, lineData);
canvas.restore();
drawPoint(canvas, pointX, pointY, lineData, paint);
}
drawLevelLine(canvas, zoomRect, paint);
drawClickCross(canvas, rect, zoomRect, paint);
}
private void drawLine(Canvas canvas, Rect rect, Rect zoomRect, Paint paint, LineData lineData, List<Float> pointX, List<Float> pointY) {
LineStyle style = lineData.getLineStyle();
style = style == null ? lineStyle : style;
style.fillPaint(paint);
paint.setColor(lineData.getColor());
if (isDrawLine) {
ILineModel model = lineData.getLineModel();
model = model == null ? lineModel : model;
for (int i = 0; i < pointY.size(); i++) {
Log.e("bbb", "前值:" + pointY.get(i));
pointY.set(i, pointY.get(i) - style.getWidth() / 2);
Log.e("bbb", "後值:" + pointY.get(i));
}
for (int i = 0; i < pointX.size(); i++) {
pointX.set(i, pointX.get(i) + style.getWidth() / 2);
}
Path path = model.getLinePath(pointX, pointY);
if (isArea) {
paint.setStyle(Paint.Style.FILL);
path.lineTo(rect.right, rect.bottom);
path.lineTo(rect.left, rect.bottom);
path.close();
int alphaColor = ColorUtils.changeAlpha(paint.getColor(), areaAlpha);
paint.setColor(alphaColor);
}
getPath().drawPath(canvas, zoomRect, path, perWidth, paint, getProgress());
}
}
@Override
protected void matrixRectEnd(Canvas canvas, Rect rect) {
}
@Override
protected void matrixRectStart(Canvas canvas, Rect rect) {
}
private float getStartX(Rect zoomRect, int position) {
if (isStartZero) {
perWidth = (zoomRect.width()) / (rowSize - 1);//得到每個x點之間的寬度
return (float) (position * perWidth + zoomRect.left);
} else {
perWidth = (zoomRect.width()) / rowSize;
return (float) (position * perWidth + perWidth / 2 + zoomRect.left);
}
}
private void drawClickCross(Canvas canvas, Rect rect, Rect zoomRect, Paint paint) {
if (pointF != null && (isOpenCross() || isOpenMark())) {
int minPositionX = 0, minPositionY = 0;
float centerX = 0, centerY = 0;
LineData clickLineData = null;
float minDisX = zoomRect.width();
for (int i = 0; i < rowSize; i++) {
float startX = getStartX(zoomRect, i);
float disX = Math.abs(pointF.x - startX);
if (disX < minDisX) {
minPositionX = i;
minDisX = disX;
centerX = startX;
} else {
break;
}
}
List<LineData> lineDates = chartData.getColumnDataList();
float minDisY = zoomRect.height();
boolean isHasLine = false;
for (int j = 0; j < lineDates.size(); j++) {
LineData lineData = lineDates.get(j);
if (!lineData.isDraw()) {
continue;
}
isHasLine = true;
double value;
if (minPositionX < lineData.getChartYDataList().size()) {
value = lineData.getChartYDataList().get(minPositionX);
} else {
break;
}
float startY = getStartY(zoomRect, value, lineData.getDirection());
float disY = Math.abs(pointF.y - startY);
if (disY < minDisY) {
centerY = startY;
minDisY = disY;
clickLineData = lineData;
minPositionY = j;
}
}
if (!isHasLine || !containsRect(centerX, centerY)) {
return;
}
if (onClickColumnListener != null) {
onClickColumnListener.onClickColumn(clickLineData, minPositionX);
}
if (isOpenCross() && getCross() != null) {
getCross().drawCross(canvas, new PointF(centerX, centerY), rect, paint);
}
drawMark(canvas, centerX, centerY, rect, minPositionX, minPositionY);
}
}
private void drawPoint(Canvas canvas, List<Float> pointX, List<Float> pointY, LineData lineData, Paint paint) {
IPoint linePoint = lineData.getPoint();
linePoint = linePoint == null ? point : linePoint;
if (linePoint != null) {
for (int i = 0; i < pointY.size(); i++) {
float x = pointX.get(i);
float y = pointY.get(i);
if (containsRect(x, y)) {
linePoint.drawPoint(canvas, x, y, i, false, paint);
}
}
}
}
private void drawTip(Canvas canvas, List<Float> pointX, List<Float> pointY, LineData lineData) {
if (tip != null) {
for (int i = 0; i < pointY.size(); i++) {
float x = pointX.get(i);
float y = pointY.get(i);
drawTip(canvas, x, y, lineData, i);
}
}
}
public LineStyle getLineStyle() {
return lineStyle;
}
@Override
public double[] setMaxMinValue(double maxValue, double minValue) {
double dis = Math.abs(maxValue - minValue);
maxValue = maxValue + dis * 0.3;
if (minValue > 0) {
minValue = 0;
} else {
minValue = minValue - dis * 0.3;
}
return new double[]{maxValue, minValue};
}
public IPath getPath() {
if (path == null) {
path = new LinePath();
}
return path;
}
public IGrid getGrid() {
return grid;
}
public void setGrid(IGrid grid) {
this.grid = grid;
}
public void setPath(IPath path) {
this.path = path;
}
public void setArea(boolean isArea) {
this.isArea = isArea;
}
/**
* 设置线模式
*
* @param lineModel
*/
public void setLineModel(ILineModel lineModel) {
this.lineModel = lineModel;
}
/**
* 设置是否绘制线
*
* @param drawLine 绘制线
*/
public void setDrawLine(boolean drawLine) {
isDrawLine = drawLine;
}
/**
* 过滤图表文本数量
* 当数据过多时,,来过滤文字显示,保持图表美观
*
* @return 过滤图表文本数量
*/
public int getFilterPointTextCount() {
return filterPointTextCount;
}
/**
* 过滤图表文本数量
* 当数据过多时,可以使用该方法,来过滤文字显示,保持图表美观
*
* @return
*/
public void setFilterPointTextCount(int filterPointTextCount) {
this.filterPointTextCount = filterPointTextCount;
}
public void setPoint(IPoint point) {
this.point = point;
}
/**
* 设置是否从0开始
*
* @return 从0开始
*/
public boolean isStartZero() {
return isStartZero;
}
/**
* 设置是否从0开始
*
* @param startZero 从0开始
*/
public void setStartZero(boolean startZero) {
isStartZero = startZero;
}
/**
* 获取面积图透明度
*
* @return 透明度 0-255
*/
public int getAreaAlpha() {
return areaAlpha;
}
/**
* 设置面积图的透明度
*
* @param areaAlpha 透明度 0-255
*/
public void setAreaAlpha(int areaAlpha) {
this.areaAlpha = areaAlpha;
}
}
package com.daivd.chart.provider.component.cross;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import com.daivd.chart.data.style.LineStyle;
/**
* Created by huang on 2017/10/19.
* 双方向
*/
public class DoubleDriCross implements ICross{
LineStyle crossStyle = new LineStyle();
@Override
public void drawCross(Canvas canvas, PointF pointF, Rect rect, Paint paint) {
crossStyle.fillPaint(paint);
canvas.drawLine(pointF.x, rect.top, pointF.x, rect.bottom, paint);
canvas.drawLine(rect.left, pointF.y, rect.right, pointF.y, paint);
}
public LineStyle getCrossStyle() {
return crossStyle;
}
public void setCrossStyle(LineStyle crossStyle) {
this.crossStyle = crossStyle;
}
}
package com.daivd.chart.provider.component.cross;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
/**
* Created by huang on 2017/10/19.
* 十字轴
*/
public interface ICross {
void drawCross(Canvas canvas, PointF pointF, Rect rect, Paint paint);
}
package com.daivd.chart.provider.component.cross;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import com.daivd.chart.data.style.LineStyle;
import com.daivd.chart.provider.component.point.IPoint;
import com.daivd.chart.provider.component.point.Point;
/**
* Created by huang on 2017/10/19.
* 竖轴方向
*/
public class VerticalCross implements ICross {
LineStyle crossStyle = new LineStyle();
IPoint point = new Point();
@Override
public void drawCross(Canvas canvas, PointF pointF, Rect rect, Paint paint) {
crossStyle.fillPaint(paint);
canvas.drawLine(pointF.x, rect.top, pointF.x, rect.bottom, paint);
if (point != null) {
point.drawPoint(canvas, pointF.x, pointF.y, 0, false, paint);
}
}
public IPoint getPoint() {
return point;
}
public void setPoint(IPoint point) {
this.point = point;
}
public LineStyle getCrossStyle() {
return crossStyle;
}
public void setCrossStyle(LineStyle crossStyle) {
this.crossStyle = crossStyle;
}
}
package com.daivd.chart.provider.component.grid;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
/**
* Created by huang on 2017/12/1.
*/
public interface IGrid {
/**
* 绘制网格
* @param canvas
* @param x
* @param rect
* @param perWidth
* @param paint
*/
void drawGrid(Canvas canvas, float x, Rect rect, int perWidth, Paint paint);
/**
* 绘制点击背景
* @param canvas
* @param pointF
* @param rect
* @param perWidth
* @param paint
*/
void drawClickBg(Canvas canvas, PointF pointF, Rect rect, int perWidth, Paint paint);
/**
* 绘制列内容
* @param canvas
* @param position
* @param rect
* @param perWidth
* @param paint
*/
void drawColumnContent(Canvas canvas, int position, Rect zoomRect, Rect rect, int perWidth, Paint paint);
}
package com.daivd.chart.provider.component.level;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
/**
* Created by huang on 2017/10/19.
*/
public interface ILevel {
int getAxisDirection();
void drawLevel(Canvas canvas, Rect rect, float y, Paint paint);
double getValue();
}
package com.daivd.chart.provider.component.level;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import com.daivd.chart.component.base.IAxis;
import com.daivd.chart.data.style.FontStyle;
import com.daivd.chart.data.style.LineStyle;
/**
* Created by huang on 2017/9/30.
* LevelLine
*/
public class LevelLine implements ILevel{
public static int left = 0;
public static int right = 1;
private LineStyle lineStyle = new LineStyle();
private double value;
private int textDirection = right;
private FontStyle textStyle = new FontStyle();
private int direction = IAxis.AxisDirection.LEFT;
public LevelLine(double value) {
this.value = value;
}
public LineStyle getLineStyle() {
return lineStyle;
}
public void setLineStyle(LineStyle lineStyle) {
this.lineStyle = lineStyle;
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
public int getTextDirection() {
return textDirection;
}
public void setTextDirection(int textDirection) {
this.textDirection = textDirection;
}
public FontStyle getTextStyle() {
return textStyle;
}
public int getAxisDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}
public void setTextStyle(FontStyle textStyle) {
this.textStyle = textStyle;
}
@Override
public void drawLevel(Canvas canvas, Rect rect, float y, Paint paint) {
getLineStyle().fillPaint(paint);
Path path = new Path();
path.moveTo(rect.left, y);
path.lineTo(rect.right, y);
canvas.drawPath(path, paint);
getTextStyle().fillPaint(paint);
float textHeight = paint.measureText("1", 0, 1);
float startX;
float startY = y - textHeight + getLineStyle().getWidth();
String levelLineValue = String.valueOf(getValue());
if (getTextDirection() == LevelLine.left) {
startX = rect.left;
} else {
startX = rect.right - textHeight * levelLineValue.length();
}
canvas.drawText(levelLineValue, startX, startY, paint);
}
}
package com.daivd.chart.provider.component.line;
import android.graphics.Path;
import java.util.List;
public class BrokenLineModel implements ILineModel {
@Override
public Path getLinePath(List<Float> pointX, List<Float> pointY) {
Path path = new Path();
for(int i = 0; i < pointY.size();i++){
float x = pointX.get(i);
float y = pointY.get(i);
if(i == 0){
path.moveTo(x,y);
}else{
path.lineTo(x,y);
}
}
return path;
}
}
package com.daivd.chart.provider.component.line;
import android.graphics.Path;
import java.util.LinkedList;
import java.util.List;
/**曲线内容绘制
* Created by huang on 2017/9/27.
*/
public class CurveLineModel implements ILineModel {
private final int STEP = 12;
@Override
public Path getLinePath(List<Float> pointX, List<Float> pointY) {
List<Cubic> calculate_x = calculate(pointX);
List<Cubic> calculate_y = calculate(pointY);
Path path = new Path();
if (null != calculate_x && null != calculate_y && calculate_y.size() >= calculate_x.size()) {
path.moveTo(calculate_x.get(0).eval(0), calculate_y.get(0).eval(0));
for (int i = 0; i < calculate_x.size(); i++) {
for (int j = 1; j <= STEP; j++) {
float u = j / (float) STEP;
path.lineTo(calculate_x.get(i).eval(u), calculate_y.get(i).eval(u));
}
}
}
return path;
}
/**
* 计算曲线.
* @param x
* @return
*/
private List<Cubic> calculate(List<Float> x) {
if (null != x && x.size() > 0) {
int n = x.size() - 1;
float[] gamma = new float[n + 1];
float[] delta = new float[n + 1];
float[] D = new float[n + 1];
int i;
gamma[0] = 1.0f / 2.0f;
for (i = 1; i < n; i++) {
gamma[i] = 1 / (4 - gamma[i - 1]);
}
gamma[n] = 1 / (2 - gamma[n - 1]);
delta[0] = 3 * (x.get(1) - x.get(0)) * gamma[0];
for (i = 1; i < n; i++) {
delta[i] = (3 * (x.get(i + 1) - x.get(i - 1)) - delta[i - 1]) * gamma[i];
}
delta[n] = (3 * (x.get(n) - x.get(n - 1)) - delta[n - 1]) * gamma[n];
D[n] = delta[n];
for (i = n - 1; i >= 0; i--) {
D[i] = delta[i] - gamma[i] * D[i + 1];
}
List<Cubic> cubicList = new LinkedList<>();
for (i = 0; i < n; i++) {
Cubic c = new Cubic(x.get(i), D[i], 3 * (x.get(i + 1) - x.get(i)) - 2 * D[i] - D[i + 1], 2 * (x.get(i) - x.get(i + 1)) + D[i] + D[i + 1]);
cubicList.add(c);
}
return cubicList;
}
return null;
}
private class Cubic {
float a, b, c, d; /* a + b*u + c*u^2 +d*u^3 */
Cubic(float a, float b, float c, float d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
/** evaluate cubic */
float eval(float u) {
return (((d * u) + c) * u + b) * u + a;
}
}
}
package com.daivd.chart.provider.component.line;
import android.graphics.Path;
import java.util.List;
/**
* Created by huang on 2017/10/15.
*/
public interface ILineModel {
Path getLinePath(List<Float> pointX, List<Float> pointY);
}
package com.daivd.chart.provider.component.mark;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import com.daivd.chart.provider.component.tip.SingleLineBubbleTip;
import com.daivd.chart.data.BarData;
import com.daivd.chart.utils.DensityUtils;
import com.david.chart.R;
/**
* Created by huang on 2017/9/28.
*/
public class BubbleMarkView<C extends BarData> implements IMark<C> {
private SingleLineBubbleTip<String> bubbleTip;
private Paint paint;
public BubbleMarkView(Context context) {
paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(DensityUtils.sp2px(context,13));
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
bubbleTip = new SingleLineBubbleTip<String>(context,R.mipmap.round_rect,R.mipmap.triangle,paint){
@Override
public boolean isShowTip(String s,int position) {
return true;
}
@Override
public String format(String s, int position) {
return s;
}
};
}
public Paint getPaint() {
return paint;
}
@Override
public void drawMark(Canvas canvas, float x, float y, Rect rect, String content, BarData data, int position) {
String text = content + data.getChartYDataList().get(position) + data.getUnit();
bubbleTip.drawTip(canvas, x, y, rect, text,position);
}
}
package com.daivd.chart.provider.component.mark;
import android.graphics.Canvas;
import android.graphics.Rect;
import com.daivd.chart.data.ColumnData;
/**
* Created by huang on 2017/9/28.
*/
public interface IMark<C extends ColumnData> {
/**
* 绘制Mark
*/
void drawMark(Canvas canvas,float x, float y,Rect rect, String content, C data, int position);
}
package com.daivd.chart.provider.component.path;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
/**
* Created by huang on 2017/11/30.
*/
public interface IPath {
void drawPath(Canvas canvas, Rect rect, Path path, int perWidth, Paint paint, float progress);
}
package com.daivd.chart.provider.component.path;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
/**
* Created by huang on 2017/11/30.
*/
public class LinePath implements IPath{
public void drawPath(Canvas canvas, Rect rect, Path path, int perWidth, Paint paint,float progress){
canvas.drawPath(path, paint);
}
}
package com.daivd.chart.provider.component.point;
/**
* Created by huang on 2017/12/13.
*/
public interface ILegendPoint extends IPoint{
float getWidth();
float getHeight();
}
package com.daivd.chart.provider.component.point;
import android.graphics.Canvas;
import android.graphics.Paint;
/**
* Created by huang on 2017/10/20.
*/
public interface IPoint {
void drawPoint(Canvas canvas, float x, float y, int position, boolean isShowDefaultColor, Paint paint);
}
package com.daivd.chart.provider.component.point;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.daivd.chart.data.style.PointStyle;
/**
* Created by huang on 2017/10/20.
*/
public class LegendPoint implements ILegendPoint {
private PointStyle pointStyle = new PointStyle();
public void drawPoint(Canvas canvas, float x, float y, int position,boolean isShowDefaultColor, Paint paint){
float w = pointStyle.getWidth();
if(isShowDefaultColor){
pointStyle.fillPaint(paint);
}else {
int oldColor =paint.getColor();
pointStyle.fillPaint(paint);
paint.setColor(oldColor);
}
if (pointStyle.getShape() == PointStyle.CIRCLE) {
canvas.drawCircle(x, y, w/2, paint);
} else if (pointStyle.getShape() == PointStyle.SQUARE) {
canvas.drawRect(x - w/2 , y - w/2 , x + w/2, y + w/2 , paint);
} else if (pointStyle.getShape() == PointStyle.RECT) {
canvas.drawRect(x - w * 2 / 3, y - w/2 , x + w * 2 / 3, y + w/2, paint);
}
}
@Override
public float getWidth() {
if(pointStyle.getShape() == PointStyle.RECT){
return pointStyle.getWidth() * 4/ 3;
}
return pointStyle.getWidth();
}
@Override
public float getHeight() {
return pointStyle.getWidth();
}
public PointStyle getPointStyle() {
return pointStyle;
}
}
package com.daivd.chart.provider.component.point;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.daivd.chart.data.style.PointStyle;
/**
* Created by huang on 2017/10/20.
*/
public class Point implements IPoint {
private PointStyle pointStyle = new PointStyle();
public void drawPoint(Canvas canvas,float x, float y,int position,boolean isShowDefaultColor, Paint paint){
float w = pointStyle.getWidth();
if(isShowDefaultColor){
pointStyle.fillPaint(paint);
}else {
int oldColor =paint.getColor();
pointStyle.fillPaint(paint);
paint.setColor(oldColor);
}
if (pointStyle.getShape() == PointStyle.CIRCLE) {
canvas.drawCircle(x, y, w/2, paint);
} else if (pointStyle.getShape() == PointStyle.SQUARE) {
canvas.drawRect(x - w/2 , y - w/2 , x + w/2, y + w/2 , paint);
} else if (pointStyle.getShape() == PointStyle.RECT) {
canvas.drawRect(x - w * 2 / 3, y - w/2 , x + w * 2 / 3, y + w/2, paint);
}
}
public PointStyle getPointStyle() {
return pointStyle;
}
}
package com.daivd.chart.provider.component.text;
import android.graphics.Canvas;
import android.graphics.Paint;
/**
* Created by huang on 2017/11/30.
*/
public interface IText {
void drawText(Canvas canvas, String value, float x, float y, int position, int line, Paint paint);
}
package com.daivd.chart.provider.component.tip;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.NinePatch;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import com.daivd.chart.utils.DensityUtils;
/**
* Created by huang on 2017/10/20.
* 气泡提示
*/
public abstract class BaseBubbleTip<C, S> implements ITip<C, S> {
public static final int INVALID = -1;
private Rect tipRect;
private Paint paint;
private int verticalPadding;
private int horizontalPadding;
// private Bitmap triangleBitmap;
private NinePatch ninePatch;
private boolean isReversal = false;
protected int deviation;
private float alpha;
private int colorFilter = INVALID;
public BaseBubbleTip(Context context, int backgroundDrawableID, int triangleDrawableID, Paint paint) {
tipRect = new Rect();
this.paint = paint;
// triangleBitmap = Bitmap.createBitmap(BitmapFactory.decodeResource(context.getResources(), triangleDrawableID));
if (ninePatch == null) {
Bitmap bmp_9 = BitmapFactory.decodeResource(context.getResources(),
backgroundDrawableID);
ninePatch = new NinePatch(bmp_9, bmp_9.getNinePatchChunk(), null);
}
verticalPadding = DensityUtils.dp2px(context, 5);
horizontalPadding = verticalPadding;
deviation = DensityUtils.dp2px(context, 5);
}
public void drawTip(Canvas canvas, float x, float y, Rect rect, C c, int position) {
if (isShowTip(c, position)) {
S content = format(c, position);
// int triangleWidth = triangleBitmap.getWidth();
// int triangleHeight = triangleBitmap.getHeight();
int triangleWidth = 0;
int triangleHeight = 0;
int textWidth = getTextWidth(content);
int textHeight = getTextHeight(content);
int w = textWidth + horizontalPadding * 2;
int h = textHeight + verticalPadding * 2;
tipRect.left = (int) x - w / 2;
tipRect.right = (int) x + w / 2;
tipRect.bottom = (int) y - triangleHeight + triangleWidth / 8;
tipRect.top = tipRect.bottom - h;
int tranX = 0;
if (x > rect.left && x < rect.right) {
if (tipRect.left < rect.left) {
tranX = rect.left - tipRect.left - triangleWidth / 2;
} else if (tipRect.right > rect.right) {
tranX = rect.right - tipRect.right + triangleWidth / 2;
}
if (tipRect.top < rect.top) {
showBottom(canvas, x, y, content, textWidth, textHeight, tranX);
} else if (tipRect.bottom > rect.bottom) {
showTop(canvas, x, y, content, textWidth, textHeight, tranX);
} else if (isReversal) {
showBottom(canvas, x, y, content, textWidth, textHeight, tranX);
} else {
showTop(canvas, x, y, content, textWidth, textHeight, tranX);
}
}
}
}
public abstract int getTextHeight(S content);
public abstract int getTextWidth(S content);
public abstract void drawText(Canvas canvas, Rect tipRect, S content, int textWidth, int textHeight, Paint paint);
private void showTop(Canvas canvas, float x, float y, S content, int textWidth, int textHeight, int tranX) {
canvas.save();
// int triangleWidth = triangleBitmap.getWidth();
// int triangleHeight = triangleBitmap.getHeight();
int triangleWidth = 0;
int triangleHeight = 0;
startColorFilter();
// paint.setShadowLayer(40, 10, 50, Color.BLACK);
// canvas.drawBitmap(triangleBitmap, x - triangleWidth / 2,
// y - triangleHeight, paint);
// paint.clearShadowLayer();
canvas.translate(tranX, 0);
ninePatch.draw(canvas, tipRect);
clearColorFilter();
drawText(canvas, tipRect, content, textWidth, textHeight, paint);
canvas.restore();
}
private void showBottom(Canvas canvas, float x, float y, S content, int textWidth, int textHeight, int tranX) {
canvas.save();
// int triangleWidth = triangleBitmap.getWidth();
// int triangleHeight = triangleBitmap.getHeight();
canvas.rotate(180, x, y);
startColorFilter();
// canvas.drawBitmap(triangleBitmap, x - triangleWidth / 2,
// y - triangleHeight, paint);
canvas.translate(-tranX, 0);
ninePatch.draw(canvas, tipRect);
clearColorFilter();
paint.setColorFilter(null);
canvas.rotate(180, tipRect.centerX(), tipRect.centerY());
drawText(canvas, tipRect, content, textWidth, textHeight, paint);
canvas.restore();
}
private void startColorFilter() {
if (colorFilter != INVALID) {
paint.setColorFilter(new PorterDuffColorFilter(colorFilter, PorterDuff.Mode.SRC_IN));
ninePatch.setPaint(paint);
paint.setAlpha((int) (alpha * 255));
}
}
private void clearColorFilter() {
if (colorFilter != INVALID) {
paint.setColorFilter(null);
paint.setAlpha(255);
}
}
public Paint getPaint() {
return paint;
}
public void setPaint(Paint paint) {
this.paint = paint;
}
public boolean isReversal() {
return isReversal;
}
public void setReversal(boolean reversal) {
isReversal = reversal;
}
public void setVerticalPadding(int verticalPadding) {
this.verticalPadding = verticalPadding;
}
public int getVerticalPadding() {
return verticalPadding;
}
public int getHorizontalPadding() {
return horizontalPadding;
}
public void setHorizontalPadding(int horizontalPadding) {
this.horizontalPadding = horizontalPadding;
}
public int getColorFilter() {
return colorFilter;
}
public void setColorFilter(int colorFilter) {
this.colorFilter = colorFilter;
}
public float getAlpha() {
return alpha;
}
public void setAlpha(float alpha) {
this.alpha = alpha;
}
}
package com.daivd.chart.provider.component.tip;
import android.graphics.Canvas;
import android.graphics.Rect;
/**
* Created by huang on 2017/10/20.
*/
public interface ITip<C,S> {
void drawTip(Canvas canvas, float x, float y, Rect rect, C content,int position);
boolean isShowTip(C c,int position);
S format(C c,int position);
}
package com.daivd.chart.provider.component.tip;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import com.daivd.chart.utils.DensityUtils;
/**
* Created by huang on 2017/10/20.
* 气泡提示
*/
public abstract class MultiLineBubbleTip<C> extends BaseBubbleTip<C, String[]> {
private int lineSpacing;
public MultiLineBubbleTip(Context context, int backgroundDrawableID, int triangleDrawableID, Paint paint) {
super(context, backgroundDrawableID, triangleDrawableID, paint);
lineSpacing = DensityUtils.dp2px(context, 3);
}
@Override
public int getTextHeight(String[] content) {
Paint.FontMetrics fontMetrics = getPaint().getFontMetrics();
int textHeight = (int) (fontMetrics.bottom - fontMetrics.top);
return (textHeight + lineSpacing) * content.length - lineSpacing;
}
@Override
public int getTextWidth(String[] content) {
int maxLength = 0;
for (int i = 0; i < content.length; i++) {
int length = (int) getPaint().measureText(content[i]);
if (length > maxLength) {
maxLength = length;
}
}
return maxLength;
}
@Override
public void drawText(Canvas canvas, Rect tipRect, String[] content, int textWidth, int textHeight, Paint paint) {
int lineHeight = textHeight / content.length;
for (int i = 0; i < content.length; i++) {
String c = content[i];
int bottom = tipRect.top + getVerticalPadding() + lineHeight + (lineHeight) * i - lineSpacing - deviation / 2;
int left = tipRect.centerX() - textWidth / 2;
canvas.drawText(c, left, bottom, paint);
}
}
}
package com.daivd.chart.provider.component.tip;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
/**
* Created by huang on 2017/10/20.
* 单行气泡提示
*/
public abstract class SingleLineBubbleTip<C> extends BaseBubbleTip<C,String> {
public SingleLineBubbleTip(Context context, int backgroundDrawableID, int triangleDrawableID, Paint paint){
super(context,backgroundDrawableID,triangleDrawableID,paint);
}
@Override
public int getTextHeight(String content) {
Paint.FontMetrics fontMetrics = getPaint().getFontMetrics();
return (int) (fontMetrics.bottom - fontMetrics.top);
}
@Override
public int getTextWidth(String content) {
return (int) getPaint().measureText(content);
}
@Override
public void drawText(Canvas canvas, Rect tipRect, String content, int textWidth,int textHeight, Paint paint) {
canvas.drawText(content,tipRect.centerX()-textWidth/2,tipRect.centerY()+textHeight/2-deviation/2,paint);
}
}
package com.daivd.chart.provider.pie;
import android.content.Context;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.PieData;
/**
* Created by huang on 2017/10/9.
* 3D饼图
* 试验中,未完成
*/
public class Pie3DProvider extends PieProvider {
private int borderWidth = 20;
//提供摄像头
private Camera camera = new Camera();
public Pie3DProvider(Context context){
//拉远摄像头Z轴
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float newZ = -displayMetrics.density * 6;
camera.setLocation(0,0,newZ);
}
@Override
public boolean calculationChild(ChartData<PieData> chartData) {
return true;
}
/**
* 变形开始
*
*/
@Override
protected void matrixRectStart(Canvas canvas, Rect rect) {
canvas.save();
camera.save();
canvas.translate(rect.centerX(),rect.centerY());
camera.rotateX(60);
camera.applyToCanvas(canvas);
canvas.translate(-rect.centerX(),-rect.centerY());
canvas.clipRect(rect);
if(rotateHelper != null && rotateHelper.isRotate()){
canvas.rotate((float) rotateHelper.getStartAngle(),rect.centerX(),rect.centerY());
}
}
@Override
protected void drawProvider(Canvas canvas, Rect zoomRect, Rect rect, Paint paint) {
super.drawProvider(canvas, zoomRect, rect, paint);
PointF centerPoint = getCenterPoint();
paint.setStrokeWidth(borderWidth);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.parseColor("#80FFFFFF"));
int radius = getCenterRadius();
canvas.drawCircle(centerPoint.x,centerPoint.y,radius*getCenterCirclePercent()+borderWidth/2,paint);
canvas.drawCircle(centerPoint.x,centerPoint.y,radius-borderWidth/2,paint);
}
/**
* 变形结束
*
*/
@Override
protected void matrixRectEnd(Canvas canvas, Rect rect) {
camera.restore();
super.matrixRectEnd(canvas, rect);
}
}
package com.daivd.chart.provider.pie;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.format.IFormat;
import com.daivd.chart.data.PieData;
import com.daivd.chart.data.style.FontStyle;
import com.daivd.chart.matrix.RotateHelper;
import com.daivd.chart.provider.BaseProvider;
import com.daivd.chart.utils.ColorUtils;
import java.util.List;
/**
* Created by huang on 2017/10/9.
*/
public class PieProvider extends BaseProvider<PieData> {
private RectF oval;
private int totalAngle = 360;
private PointF centerPoint;
private int centerRadius;
private double clickAngle = -1;
private final float startAngle = -90;
protected RotateHelper rotateHelper;
private FontStyle textStyle = new FontStyle();
private float centerCirclePercent = 0.3f;
private boolean isClick;
private IFormat<Double> valueFormat;
private PorterDuffXfermode porterDuffXfermode;
@Override
public boolean calculationChild(ChartData<PieData> chartData) {
return true;
}
/**
*变形开始
*/
@Override
protected void matrixRectStart(Canvas canvas, Rect rect) {
super.matrixRectStart(canvas, rect);
if(rotateHelper != null && rotateHelper.isRotate()){
canvas.rotate((float) rotateHelper.getStartAngle(),rect.centerX(),rect.centerY());
}
}
/**
* 绘制内容
*/
@Override
protected void drawProvider(Canvas canvas, Rect zoomRect, Rect rect, Paint paint) {
int layerId = canvas.saveLayer(rect.left,rect.top,rect.right,rect.bottom, null, Canvas.ALL_SAVE_FLAG);
float startAngle = this.startAngle;
float totalAngle = getAnimValue(this.totalAngle);
paint.setStyle(Paint.Style.FILL);
int h = zoomRect.height();
int w = zoomRect.width();
int maxRadius = Math.min(w/2, h/2);
int x = maxRadius / 10;
centerRadius = maxRadius - x;
if(oval == null) {
oval = new RectF(zoomRect.centerX() - centerRadius, zoomRect.centerY() - centerRadius,
zoomRect.centerX() + centerRadius, zoomRect.centerY() + centerRadius);
centerPoint = new PointF(zoomRect.centerX(), zoomRect.centerY());
}
if(rotateHelper != null){
rotateHelper.setRadius(centerRadius);
rotateHelper.setOriginRect(rect);
}
List<PieData> pieDataList = chartData.getColumnDataList();
float totalScores = 0f;
for (PieData pieData: pieDataList) {
totalScores += pieData.getChartYDataList();
}
for (int i = 0; i < pieDataList.size(); i++) {
PieData pieData = pieDataList.get(i);
double value = pieData.getChartYDataList();
float sweepAngle = (float) (totalAngle * value / totalScores);
if(pieData.isDraw()) {
paint.setColor(pieData.getColor());
if (clickAngle != -1 && clickAngle > startAngle && clickAngle < startAngle + sweepAngle) {
paint.setColor(ColorUtils.getDarkerColor(pieData.getColor()));
if(isClick && onClickColumnListener != null){
onClickColumnListener.onClickColumn(pieData,0);
isClick = false;
}
}
canvas.drawArc(oval, startAngle, sweepAngle, true, paint);
if(isShowText()) {
canvas.save();
canvas.rotate(startAngle + sweepAngle / 2 - this.startAngle, zoomRect.centerX(), zoomRect.centerY());
textStyle.fillPaint(paint);
int textHeight = (int) paint.measureText("1", 0, 1);
String val =valueFormat != null ?valueFormat.format(value):String.valueOf(value);
canvas.drawText(val, zoomRect.centerX() - val.length() * textHeight / 2, zoomRect.centerY() - maxRadius / 2, paint);
canvas.restore();
}
}
startAngle += sweepAngle;
}
//裁切中间圆
if(porterDuffXfermode == null){
porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT);
}
paint.setXfermode(porterDuffXfermode);
if(centerCirclePercent >0) {
paint.setColor(Color.TRANSPARENT);
canvas.drawCircle(rect.centerX(),rect.centerY(),centerRadius *centerCirclePercent,paint);
}
canvas.restoreToCount(layerId);
paint.setXfermode(null);
}
@Override
public double[] setMaxMinValue(double maxMinValue, double minValue) {
return new double[0];
}
@Override
public void clickPoint(PointF point) {
super.clickPoint(point);
if(centerPoint != null){
int x = (int) (point.x - centerPoint.x);
int y = (int) (point.y - centerPoint.y);
int z = (int) Math.sqrt(Math.pow(Math.abs(x), 2) + Math.pow(Math.abs(y), 2));
if (/*z >= centerRadius - circleBorder / 2 &&*/ z <= centerRadius + 20) {
double angle = Math.abs(Math.toDegrees(Math.atan((point.y - centerPoint.y) / (point.x - centerPoint.x))));
if (x >= 0 && y < 0) {
angle = 90 - angle;
} else if (x >= 0 && y >= 0) {
angle = 90 + angle;
} else if (x < 0 && y >= 0) {
angle = 270 - angle;
} else {
angle = 270 + angle;
}
angle = (angle -rotateHelper.getStartAngle())%360;
angle = angle <0 ? 360+angle:angle;
clickAngle = angle + startAngle;
isClick = true;
return;
}
clickAngle = -1;
}
}
public PointF getCenterPoint() {
return centerPoint;
}
public void setCenterPoint(PointF centerPoint) {
this.centerPoint = centerPoint;
}
public int getCenterRadius() {
return centerRadius;
}
public void setCenterRadius(int centerRadius) {
this.centerRadius = centerRadius;
}
public void setValueFormat(IFormat<Double> valueFormat) {
this.valueFormat = valueFormat;
}
public void setCenterCirclepercent(float centerCirclePercent) {
this.centerCirclePercent = centerCirclePercent;
}
public float getCenterCirclePercent() {
return centerCirclePercent;
}
public void setCenterCirclePercent(float centerCirclePercent) {
this.centerCirclePercent = centerCirclePercent;
}
public void setRotateHelper(RotateHelper rotateHelper) {
this.rotateHelper = rotateHelper;
}
}
package com.daivd.chart.provider.radar;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import com.daivd.chart.component.base.IAxis;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.format.IFormat;
import com.daivd.chart.data.BarData;
import com.daivd.chart.data.RadarData;
import com.daivd.chart.data.ScaleData;
import com.daivd.chart.data.style.FontStyle;
import com.daivd.chart.data.style.LineStyle;
import com.daivd.chart.exception.ChartException;
import com.daivd.chart.matrix.RotateHelper;
import com.daivd.chart.provider.BaseProvider;
import java.util.List;
/**
* Created by huang on 2017/10/9.
*雷达图内容绘制
*/
public class RadarProvider extends BaseProvider<RadarData> {
private int centerRadius;
private RotateHelper rotateHelper;
private FontStyle scaleStyle = new FontStyle();
private LineStyle lineStyle = new LineStyle();
protected LineStyle gridStyle = new LineStyle(); //网格样式
private int textHeight;
private boolean isShowScale;
private IFormat<Double> scaleFormat;
@Override
protected void matrixRectStart(Canvas canvas, Rect rect) {
super.matrixRectStart(canvas, rect);
if(rotateHelper != null && rotateHelper.isRotate()){
canvas.rotate((float) rotateHelper.getStartAngle(),rect.centerX(),rect.centerY());
}
}
@Override
protected void drawProvider(Canvas canvas, Rect zoomRect, Rect rect, Paint paint) {
int w = zoomRect.width();
int h = zoomRect.height();
int maxRadius = Math.min(w/2, h/2);
textHeight = (int) (paint.measureText("1",0,1));
scaleStyle.fillPaint(paint);
String oneXData = chartData.getCharXDataList().get(0);
int x = maxRadius / 10 + textHeight * oneXData.length();
centerRadius = maxRadius - x;
if(rotateHelper != null){
rotateHelper.setOriginRect(rect);
rotateHelper.setRadius(centerRadius);
}
drawRadarBorder(canvas,zoomRect,paint);
drawRadarLines(canvas,zoomRect,paint);
drawLinePath(canvas,zoomRect,paint);
drawQuadrantText(canvas,zoomRect,paint);
}
private void drawLinePath(Canvas canvas,Rect zoomRect,Paint paint){
List<String> charXDataList = chartData.getCharXDataList();
int count = charXDataList.size();
ScaleData scaleData = chartData.getScaleData();
List<RadarData> columnDataList = chartData.getColumnDataList();
double scaleLength = scaleData.getTotalScaleLength(IAxis.AxisDirection.LEFT);
float angle = (float) (Math.PI*2/count);
Path path = new Path();
lineStyle.fillPaint(paint);
for(int i = 0;i <columnDataList.size();i++){
BarData columnData = columnDataList.get(i);
if(columnData.isDraw()) {
paint.setColor(columnData.getColor());
path.reset();
for (int j = 0; j < columnData.getChartYDataList().size(); j++) {
double value = columnData.getChartYDataList().get(j);
float curR = getAnimValue((float) ( value * centerRadius / scaleLength));
if (j == 0) {
path.moveTo(zoomRect.centerX() + curR, zoomRect.centerY());
} else {
//根据半径,计算出蜘蛛丝上每个点的坐标
float x = (float) (zoomRect.centerX() + curR * Math.cos(angle * j));
float y = (float) (zoomRect.centerY() + curR * Math.sin(angle * j));
path.lineTo(x, y);
}
}
path.close();
canvas.drawPath(path, paint);
}
}
}
private void drawRadarBorder(Canvas canvas,Rect zoomRect,Paint paint){
List<String> charXDataList = chartData.getCharXDataList();
int count = charXDataList.size();
float angle = (float) (Math.PI*2/count);
ScaleData scaleData = chartData.getScaleData();
List<Double> scaleList= scaleData.getScaleList(IAxis.AxisDirection.LEFT);
double maxScale = scaleData.getMaxScaleValue(IAxis.AxisDirection.LEFT);
Path path = new Path();
for(int i = 0;i < scaleList.size();i++){
path.reset();
double value = scaleList.get(i);
float curR = (float)(value*centerRadius/maxScale);
for(int j = 0; j <count;j++){
float y;
float x;
if(j==0){
x = zoomRect.centerX()+curR;
y = zoomRect.centerY();
path.moveTo(x,y);
}else{
//根据半径,计算出蜘蛛丝上每个点的坐标
x= (float) (zoomRect.centerX()+curR*Math.cos(angle*j));
y = (float) (zoomRect.centerY()+curR*Math.sin(angle*j));
path.lineTo(x,y);
}
}
gridStyle.fillPaint(paint);
path.close();
canvas.drawPath(path,paint);
scaleStyle.fillPaint(paint);
int textHeight = (int) paint.measureText("1",0,1);
if(isShowScale) {
String valueStr = getFormatValue(value);
canvas.drawText(valueStr, zoomRect.centerX() - textHeight*valueStr.length()/2 , (float)( zoomRect.centerY() - curR*Math.sin(Math.PI/3)), paint);
}
}
}
private String getFormatValue(double value){
return scaleFormat !=null ? scaleFormat.format(value):String.valueOf(value);
}
/**
* 绘制象限文字
* @param canvas
*/
private void drawQuadrantText(Canvas canvas,Rect zoomRect,Paint paint){
scaleStyle.fillPaint(paint);
List<String> charXDataList = chartData.getCharXDataList();
int count = charXDataList.size();
float angle = (float) (Math.PI*2/count);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float fontHeight = fontMetrics.descent - fontMetrics.ascent;
for(int i=0;i<count;i++){
String xData = charXDataList.get(i);
float x = (float) (zoomRect.centerX()+(centerRadius+fontHeight/2)*Math.cos(angle*i));
float y = (float) (zoomRect.centerY()+(centerRadius+fontHeight/2)*Math.sin(angle*i));
if(angle*i>=0&&angle*i<=Math.PI/2){//第4象限
canvas.drawText(xData, x,y,paint);
}else if(angle*i>=3*Math.PI/2&&angle*i<=Math.PI*2){//第3象限
canvas.drawText(xData, x,y,paint);
}else if(angle*i>Math.PI/2&&angle*i<=Math.PI){//第2象限
float dis = paint.measureText(xData);//文本长度
canvas.drawText(xData, x-dis,y,paint);
}else if(angle*i>=Math.PI&&angle*i<3*Math.PI/2){//第1象限
float dis = paint.measureText(xData);//文本长度
canvas.drawText(xData, x-dis,y,paint);
}
}
}
/**
* 绘制直线
*/
private void drawRadarLines(Canvas canvas,Rect zoomRect,Paint paint){
gridStyle.fillPaint(paint);
Path path = new Path();
int count = chartData.getCharXDataList().size();
float angle = (float) (Math.PI*2/count);
for(int i=0;i<count;i++){
path.reset();
path.moveTo(zoomRect.centerX(), zoomRect.centerY());
float x = (float) (zoomRect.centerX()+centerRadius*Math.cos(angle*i));
float y = (float) (zoomRect.centerY()+centerRadius*Math.sin(angle*i));
path.lineTo(x, y);
canvas.drawPath(path, paint);
}
}
/* @Override
public void clickPoint(PointF point) {
super.clickPoint(point);
if(centerPoint != null){
int x = (int) (point.x - centerPoint.x);
int y = (int) (point.y - centerPoint.y);
int z = (int) Math.sqrt(Math.pow(Math.abs(x), 2) + Math.pow(Math.abs(y), 2));
if (*//*z >= centerRadius - circleBorder / 2 &&*//* z <= centerRadius + 20) {
double angle = Math.abs(Math.toDegrees(Math.atan((point.y - centerPoint.y) / (point.x - centerPoint.x))));
if (x >= 0 && y < 0) {
angle = 90 - angle;
} else if (x >= 0 && y >= 0) {
angle = 90 + angle;
} else if (x < 0 && y >= 0) {
angle = 270 - angle;
} else {
angle = 270 + angle;
}
angle = (angle -rotateHelper.getStartAngle())%360;
angle = angle <0 ? 360+angle:angle;
clickAngle = angle + startAngle;
return;
}
clickAngle = -1;
}
}*/
@Override
public boolean calculationChild( ChartData<RadarData> chartData) {
this.chartData = chartData;
ScaleData scaleData =this.chartData.getScaleData();
List<RadarData> columnDatas = chartData.getColumnDataList();
if(columnDatas == null || columnDatas.size() == 0){
return false;
}
int columnSize = columnDatas.size();
for(int i = 0 ; i <columnSize; i++){
BarData columnData = columnDatas.get(i);
if(!columnData.isDraw()){
continue;
}
List<Double> datas = columnData.getChartYDataList();
if(datas == null || datas.size() == 0){
throw new ChartException("Please set up Column data");
}
scaleData.rowSize = datas.size();
if(datas.size() != scaleData.rowSize){
throw new ChartException("Column rows data inconsistency");
}
double[] scale = getColumnScale(datas);
scale = setMaxMinValue(scale[0],scale[1]);
if(columnData.getDirection() == IAxis.AxisDirection.LEFT){
if(!scaleData.isLeftHasValue){
scaleData.maxLeftValue = scale[0];
scaleData.minLeftValue = scale[1];
scaleData.isLeftHasValue = true;
}else{
scaleData.maxLeftValue = Math.max( scaleData.maxLeftValue,scale[0]);
scaleData.minLeftValue = Math.min( scaleData.minLeftValue,scale[1]);
}
}else{
if(!scaleData.isRightHasValue){
scaleData.maxRightValue = scale[0];
scaleData.minRightValue= scale[1];
scaleData.isRightHasValue = true;
}else{
scaleData.maxRightValue = Math.max(scaleData.maxRightValue,scale[0]);
scaleData.minRightValue = Math.min(scaleData.minRightValue,scale[1]);
}
}
}
if(chartData.getScaleData().rowSize == 0){
return false;
}
return true;
}
@Override
public double[] setMaxMinValue(double maxValue, double minValue) {
double dis = Math.abs(maxValue -minValue);
maxValue = maxValue + dis*0.2;
if(minValue >0){
minValue = 0;
}else{
minValue = minValue - dis*0.2;
}
return new double[]{maxValue,minValue};
}
private double[] getColumnScale(List<Double> values) {
double maxValue = 0;
double minValue =0;
int size = values.size();
for(int j= 0;j < size;j++) {
double d = values.get(j) ;
if(j == 0){
maxValue = d;
minValue = d;
}
if (maxValue < d){
maxValue = d;
}else if(minValue >d){
minValue = d;
}
}
return new double[] {maxValue,minValue};
}
public FontStyle getScaleStyle() {
return scaleStyle;
}
public LineStyle getLineStyle() {
return lineStyle;
}
public LineStyle getGridStyle() {
return gridStyle;
}
public void setRotateHelper(RotateHelper rotateHelper) {
this.rotateHelper = rotateHelper;
}
public void setScaleFormat(IFormat<Double> scaleFormat) {
this.scaleFormat = scaleFormat;
}
public void setShowScale(boolean showScale) {
isShowScale = showScale;
}
}
package com.daivd.chart.provider.rose;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import com.daivd.chart.component.base.IAxis;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.format.IFormat;
import com.daivd.chart.data.BarData;
import com.daivd.chart.data.RoseData;
import com.daivd.chart.data.ScaleData;
import com.daivd.chart.data.style.FontStyle;
import com.daivd.chart.data.style.LineStyle;
import com.daivd.chart.exception.ChartException;
import com.daivd.chart.matrix.RotateHelper;
import com.daivd.chart.provider.BaseProvider;
import java.util.List;
/**
* Created by huang on 2017/10/9.
*/
public class RoseProvider extends BaseProvider<RoseData> {
private int centerRadius;
private RotateHelper rotateHelper;
private FontStyle scaleStyle = new FontStyle();
private LineStyle lineStyle = new LineStyle();
private float startAngle=0;
protected LineStyle gridStyle = new LineStyle(); //网格样式
private int textHeight;
private boolean isShowScale;
private IFormat<Double> scaleFormat;
@Override
protected void matrixRectStart(Canvas canvas, Rect rect) {
super.matrixRectStart(canvas, rect);
if (rotateHelper != null && rotateHelper.isRotate()) {
canvas.rotate((float) rotateHelper.getStartAngle(), rect.centerX(), rect.centerY());
}
}
@Override
protected void drawProvider(Canvas canvas, Rect zoomRect, Rect rect, Paint paint) {
int w = zoomRect.width();
int h = zoomRect.height();
int maxRadius = Math.min(w / 2, h / 2);
textHeight = (int) (paint.measureText("1", 0, 1));
scaleStyle.fillPaint(paint);
String oneXData = chartData.getCharXDataList().get(0);
int x = maxRadius / 10 + textHeight * oneXData.length();
centerRadius = maxRadius - x;
if (rotateHelper != null) {
rotateHelper.setOriginRect(rect);
rotateHelper.setRadius(centerRadius);
}
drawRadarBorder(canvas, zoomRect, paint);
drawRadarLines(canvas, zoomRect, paint);
drawLinePath(canvas, zoomRect, rect, paint);
drawQuadrantText(canvas, zoomRect, paint);
drawScale(canvas,zoomRect,paint);
}
private void drawLinePath(Canvas canvas, Rect zoomRect, Rect rect, Paint paint) {
List<String> charXDataList = chartData.getCharXDataList();
int count = charXDataList.size();
ScaleData scaleData = chartData.getScaleData();
List<RoseData> columnDataList = chartData.getColumnDataList();
double maxScale = scaleData.getMaxScaleValue(IAxis.AxisDirection.LEFT);
float angle = 360f / count;
startAngle = angle/2;
paint.setStyle(Paint.Style.FILL);
for (int j = 0; j < count; j++) {
double value = 0;
for (BarData lineData :columnDataList) {
if(lineData.isDraw()) {
value += lineData.getChartYDataList().get(j);
}
}
for (int i = columnDataList.size() - 1; i >= 0; i--) {
BarData lineData = columnDataList.get(i);
if(lineData.isDraw()) {
float curR = getAnimValue((float) (value * centerRadius / maxScale));
RectF rectF = new RectF(zoomRect.centerX() - curR, zoomRect.centerY() - curR, zoomRect.centerX() + curR, zoomRect.centerY() + curR);
paint.setColor(lineData.getColor());
canvas.drawArc(rectF, angle * j + angle / 6 - startAngle - 90, angle - angle / 6, true, paint);
value -= lineData.getChartYDataList().get(j);
}
}
}
}
private void drawRadarBorder(Canvas canvas, Rect zoomRect, Paint paint) {
gridStyle.fillPaint(paint);
canvas.drawCircle(zoomRect.centerX(), zoomRect.centerY(), centerRadius, paint);
canvas.drawCircle(zoomRect.centerX(), zoomRect.centerY(), centerRadius / 2, paint);
}
private void drawScale(Canvas canvas, Rect zoomRect, Paint paint){
double maxScale = chartData.getScaleData().getMaxScaleValue(IAxis.AxisDirection.LEFT);
if(isShowScale) {
scaleStyle.fillPaint(paint);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float fontHeight = fontMetrics.descent - fontMetrics.ascent;
canvas.drawText(getFormatValue(maxScale),
zoomRect.centerX(), zoomRect.centerY() - centerRadius+fontHeight, paint);
canvas.drawText(getFormatValue(maxScale/2),
zoomRect.centerX(),zoomRect.centerY()-centerRadius/2+fontHeight,paint);
}
}
/**
* 绘制象限文字
*
* @param canvas
*/
private void drawQuadrantText(Canvas canvas, Rect zoomRect, Paint paint) {
scaleStyle.fillPaint(paint);
List<String> charXDataList = chartData.getCharXDataList();
int count = charXDataList.size();
float angle = (float) (Math.PI*2/count);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float fontHeight = fontMetrics.descent - fontMetrics.ascent;
for(int i=0;i<count;i++){
float realAngle = (float) (angle*i - Math.PI/2);
String xData = charXDataList.get(i);
float x = (float) (zoomRect.centerX()+(centerRadius+fontHeight/2)*Math.cos(realAngle));
float y = (float) (zoomRect.centerY()+(centerRadius+fontHeight/2)*Math.sin(realAngle))+5;
if(realAngle>=0&&realAngle<=Math.PI/2){//第4象限
canvas.drawText(xData, x,y,paint);
}else if(realAngle<0){//第3象限
canvas.drawText(xData, x,y,paint);
}else if(realAngle>Math.PI/2&&realAngle<=Math.PI){//第2象限
float dis = paint.measureText(xData);//文本长度
canvas.drawText(xData, x-dis,y,paint);
}else if(realAngle>=Math.PI&&realAngle<3*Math.PI/2){//第1象限
float dis = paint.measureText(xData);//文本长度
canvas.drawText(xData, x-dis,y,paint);
}
}
}
/**
* 绘制直线
*/
private void drawRadarLines(Canvas canvas, Rect zoomRect, Paint paint) {
gridStyle.fillPaint(paint);
Path path = new Path();
int count = chartData.getCharXDataList().size();
float angle = (float) (Math.PI * 2 / count);
for (int i = 0; i < count; i++) {
path.reset();
path.moveTo(zoomRect.centerX(), zoomRect.centerY());
float x = (float) (zoomRect.centerX() + centerRadius * Math.cos(angle * i-Math.PI/2));
float y = (float) (zoomRect.centerY() + centerRadius * Math.sin(angle * i-Math.PI/2));
path.lineTo(x, y);
canvas.drawPath(path, paint);
}
}
private String getFormatValue(double value){
return scaleFormat !=null ? scaleFormat.format(value):String.valueOf(value);
}
/* @Override
public void clickPoint(PointF point) {
super.clickPoint(point);
if(centerPoint != null){
int x = (int) (point.x - centerPoint.x);
int y = (int) (point.y - centerPoint.y);
int z = (int) Math.sqrt(Math.pow(Math.abs(x), 2) + Math.pow(Math.abs(y), 2));
if (*//*z >= centerRadius - circleBorder / 2 &&*//* z <= centerRadius + 20) {
double angle = Math.abs(Math.toDegrees(Math.atan((point.y - centerPoint.y) / (point.x - centerPoint.x))));
if (x >= 0 && y < 0) {
angle = 90 - angle;
} else if (x >= 0 && y >= 0) {
angle = 90 + angle;
} else if (x < 0 && y >= 0) {
angle = 270 - angle;
} else {
angle = 270 + angle;
}
angle = (angle -rotateHelper.getStartAngle())%360;
angle = angle <0 ? 360+angle:angle;
clickAngle = angle + startAngle;
return;
}
clickAngle = -1;
}
}*/
void setSelection(int position) {
}
@Override
public boolean calculationChild(ChartData<RoseData> chartData) {
this.chartData = chartData;
ScaleData scaleData = this.chartData.getScaleData();
scaleData.maxLeftValue = 0;
List<RoseData> columnDatas = chartData.getColumnDataList();
if (columnDatas == null || columnDatas.size() == 0) {
return false;
}
int columnSize = columnDatas.size();
for (int j = 0; j < chartData.getCharXDataList().size(); j++) {
float maxValue = 0;
for (int i = 0; i < columnSize; i++) {
BarData columnData = columnDatas.get(i);
if (!columnData.isDraw()) {
continue;
}
List<Double> datas = columnData.getChartYDataList();
if (datas == null || datas.size() == 0) {
throw new ChartException("Please set up Column data");
}
scaleData.rowSize = datas.size();
if (datas.size() != scaleData.rowSize) {
throw new ChartException("Column rows data inconsistency");
}
double value = datas.get(j);
if (value < 0) {
throw new ChartException("The value cannot be <0");
}
maxValue += value;
}
if (!scaleData.isLeftHasValue) {
scaleData.maxLeftValue = maxValue;
scaleData.isLeftHasValue = true;
} else {
scaleData.maxLeftValue = Math.max(maxValue, scaleData.maxLeftValue);
}
}
scaleData.maxLeftValue = setMaxMinValue(scaleData.maxLeftValue, 0)[0];
return true;
}
@Override
public double[] setMaxMinValue ( double maxValue, double minValue){
double dis = Math.abs(maxValue - minValue);
maxValue = maxValue + dis * 0.5;
return new double[]{maxValue, minValue};
}
public FontStyle getScaleStyle() {
return scaleStyle;
}
public LineStyle getLineStyle() {
return lineStyle;
}
public LineStyle getGridStyle() {
return gridStyle;
}
public void setRotateHelper(RotateHelper rotateHelper) {
this.rotateHelper = rotateHelper;
}
public void setScaleFormat(IFormat<Double> scaleFormat) {
this.scaleFormat = scaleFormat;
}
public void setShowScale(boolean showScale) {
isShowScale = showScale;
}
}
package com.daivd.chart.utils;
import android.graphics.Color;
/**
* Created by huang on 2017/9/28.
*/
public class ColorUtils {
public static int getDarkerColor(int color){
float[] hsv = new float[3];
Color.colorToHSV(color, hsv); // convert to hsv
// make darker
hsv[1] = hsv[1] + 0.1f; // more saturation
hsv[2] = hsv[2] - 0.1f; // less brightness
int darkerColor = Color.HSVToColor(hsv);
return darkerColor ;
}
public static int getBrighterColor(int color){
float[] hsv = new float[3];
Color.colorToHSV(color, hsv); // convert to hsv
hsv[1] = hsv[1] - 0.1f; // less saturation
hsv[2] = hsv[2] + 0.1f; // more brightness
int darkerColor = Color.HSVToColor(hsv);
return darkerColor ;
}
/**
* 修改颜色透明度
* @param color
* @param alpha
* @return
*/
public static int changeAlpha(int color, int alpha) {
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
return Color.argb(alpha, red, green, blue);
}
}
package com.daivd.chart.utils;
import android.content.Context;
import android.util.TypedValue;
//常用单位转换的辅助类
public class DensityUtils {
private DensityUtils() {
/* cannot be instantiated */
throw new UnsupportedOperationException("cannot be instantiated");
}
/**
* dp转px
*
* @param context
* @return
*/
public static int dp2px(Context context, float dpVal)
{
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, context.getResources().getDisplayMetrics());
}
/**
* sp转px
*
* @param context
* @return
*/
public static int sp2px(Context context, float spVal)
{
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spVal, context.getResources().getDisplayMetrics());
}
/**
* px转dp
*
* @param context
* @param pxVal
* @return
*/
public static float px2dp(Context context, float pxVal)
{
final float scale = context.getResources().getDisplayMetrics().density;
return (pxVal / scale);
}
/**
* px转sp
*
* @param pxVal
* @return
*/
public static float px2sp(Context context, float pxVal)
{
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
}
}
\ No newline at end of file
package com.daivd.chart.utils;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import com.daivd.chart.data.style.FontStyle;
/**
* Created by huang on 2017/11/1.
*/
public class DrawUtils {
public static int getTextHeight(FontStyle style, Paint paint){
style.fillPaint(paint);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
return (int) (fontMetrics.descent - fontMetrics.ascent);
}
public static int getTextHeight(Paint paint){
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
return (int) (fontMetrics.descent - fontMetrics.ascent);
}
public static float getTextCenterY(int centerY,Paint paint){
return centerY-((paint.descent() + paint.ascent()) / 2);
}
public static boolean isMixRect(Rect rect,int left,int top,int right,int bottom){
return rect.bottom>= top && rect.right >= left && rect.top <bottom && rect.left< right;
}
public static boolean isClick(int left, int top, int right, int bottom, PointF clickPoint){
return clickPoint.x >= left && clickPoint.x <=right && clickPoint.y>=top && clickPoint.y <=bottom;
}
public static boolean isMixHorizontalRect(Rect rect,int left,int right){
return rect.right >= left && rect.left<= right;
}
public static boolean isVerticalMixRect(Rect rect,int top,int bottom){
return rect.bottom>= top && rect.top <=bottom;
}
}
<vector android:height="24dp" android:viewportHeight="1024.0"
android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#4096EE" android:pathData="M846.4,359.1c137.9,84.4 138.2,220.9 0,305.5l-523.7,320.4C184.9,1069.4 73.1,1006.2 73.1,845.9V178C73.1,16.7 184.5,-45.9 322.7,38.7l523.7,320.5z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>
<resources>
<string name="app_name">Smartchart</string>
</resources>
...@@ -54,7 +54,5 @@ dependencies { ...@@ -54,7 +54,5 @@ dependencies {
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
implementation 'cn.bingoogolapple:bga-progressbar:1.0.1'//进度条 implementation 'cn.bingoogolapple:bga-progressbar:1.0.1'//进度条
//報表圖
implementation project(':chart')
implementation files('libs/nineoldandroids-2.4.0.jar') implementation files('libs/nineoldandroids-2.4.0.jar')
} }
package com.gingersoft.gsa.cloud.main.mvp.model.bean;
/**
* Created by Wyh on 2020/3/7.
* 首頁側邊欄菜單
*/
public class MainSideMenuBean {
private Long id;
public int functionIcon;
private String functionName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public int getFunctionIcon() {
return functionIcon;
}
public void setFunctionIcon(int functionIcon) {
this.functionIcon = functionIcon;
}
public String getFunctionName() {
return functionName;
}
public void setFunctionName(String functionName) {
this.functionName = functionName;
}
public MainSideMenuBean(int functionIcon, String functionName) {
this.functionIcon = functionIcon;
this.functionName = functionName;
}
public MainSideMenuBean() {
}
}
...@@ -7,7 +7,6 @@ import android.text.TextUtils; ...@@ -7,7 +7,6 @@ import android.text.TextUtils;
import android.util.SparseArray; import android.util.SparseArray;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import com.billy.cc.core.component.CC; import com.billy.cc.core.component.CC;
...@@ -20,8 +19,10 @@ import com.gingersoft.gsa.cloud.main.R; ...@@ -20,8 +19,10 @@ import com.gingersoft.gsa.cloud.main.R;
import com.gingersoft.gsa.cloud.main.R2; import com.gingersoft.gsa.cloud.main.R2;
import com.gingersoft.gsa.cloud.main.di.component.DaggerNewMainComponent; import com.gingersoft.gsa.cloud.main.di.component.DaggerNewMainComponent;
import com.gingersoft.gsa.cloud.main.mvp.contract.NewMainContract; import com.gingersoft.gsa.cloud.main.mvp.contract.NewMainContract;
import com.gingersoft.gsa.cloud.main.mvp.model.bean.MainSideMenuBean;
import com.gingersoft.gsa.cloud.main.mvp.presenter.NewMainPresenter; import com.gingersoft.gsa.cloud.main.mvp.presenter.NewMainPresenter;
import com.gingersoft.gsa.cloud.main.mvp.ui.adapter.MainOrderingAdapter; import com.gingersoft.gsa.cloud.main.mvp.ui.adapter.MainOrderingAdapter;
import com.gingersoft.gsa.cloud.main.mvp.ui.adapter.MainSideMenuAdapter;
import com.gingersoft.gsa.cloud.main.mvp.ui.fragment.MainTopFragment; import com.gingersoft.gsa.cloud.main.mvp.ui.fragment.MainTopFragment;
import com.gingersoft.gsa.cloud.main.mvp.ui.view.SlidingMenu; import com.gingersoft.gsa.cloud.main.mvp.ui.view.SlidingMenu;
import com.gingersoft.gsa.cloud.ui.bean.mode.LoginBean; import com.gingersoft.gsa.cloud.ui.bean.mode.LoginBean;
...@@ -39,6 +40,7 @@ import androidx.annotation.NonNull; ...@@ -39,6 +40,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView; import butterknife.BindView;
import butterknife.BindViews; import butterknife.BindViews;
...@@ -60,6 +62,8 @@ import static com.jess.arms.utils.Preconditions.checkNotNull; ...@@ -60,6 +62,8 @@ import static com.jess.arms.utils.Preconditions.checkNotNull;
* ================================================ * ================================================
*/ */
public class NewMainActivity extends BaseActivity<NewMainPresenter> implements NewMainContract.View, View.OnClickListener { public class NewMainActivity extends BaseActivity<NewMainPresenter> implements NewMainContract.View, View.OnClickListener {
@BindView(R2.id.rv_side_menu)
RecyclerView mRvSideMenu;
@BindView(R2.id.rv_ordering_meals) @BindView(R2.id.rv_ordering_meals)
RecyclerView rvOrdering;//點餐 RecyclerView rvOrdering;//點餐
@BindView(R2.id.rv_management) @BindView(R2.id.rv_management)
...@@ -80,8 +84,6 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N ...@@ -80,8 +84,6 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N
TextView tvRestaurantName; TextView tvRestaurantName;
@BindView(R2.id.tv_username) @BindView(R2.id.tv_username)
TextView tvUserName; TextView tvUserName;
@BindView(R2.id.ll_switch_server)
LinearLayout switchServer;
@BindView(R2.id.tv_store_name) @BindView(R2.id.tv_store_name)
TextView tvStoreName; TextView tvStoreName;
...@@ -92,9 +94,6 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N ...@@ -92,9 +94,6 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N
@BindViews({R2.id.tv_function_name1, R2.id.tv_function_name2, R2.id.tv_function_name3}) @BindViews({R2.id.tv_function_name1, R2.id.tv_function_name2, R2.id.tv_function_name3})
TextView[] mTvFunctionNames; TextView[] mTvFunctionNames;
@BindView(R2.id.ll_clearance)
LinearLayout ll_clearance;
private RxPermissions mRxPermissions; private RxPermissions mRxPermissions;
@Override @Override
...@@ -122,9 +121,12 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N ...@@ -122,9 +121,12 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N
public void initData(@Nullable Bundle savedInstanceState) { public void initData(@Nullable Bundle savedInstanceState) {
mPresenter.requestExternalStoragePermission(); mPresenter.requestExternalStoragePermission();
//初始化側邊欄菜單項
initSideMenu();
FragmentManager fragmentManager = getSupportFragmentManager(); FragmentManager fragmentManager = getSupportFragmentManager();
mainTopFragment = (MainTopFragment) fragmentManager.findFragmentById(R.id.main_top_fragment); mainTopFragment = (MainTopFragment) fragmentManager.findFragmentById(R.id.main_top_fragment);
switchServer.setVisibility(BuildConfig.DEBUG ? View.VISIBLE : View.GONE);
tvStoreName.setText(GsaCloudApplication.getRestaurantName(mContext)); tvStoreName.setText(GsaCloudApplication.getRestaurantName(mContext));
refresh.setOnPullListener(new QMUIPullRefreshLayout.OnPullListener() { refresh.setOnPullListener(new QMUIPullRefreshLayout.OnPullListener() {
@Override @Override
...@@ -150,6 +152,39 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N ...@@ -150,6 +152,39 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N
setTitleInfo(); setTitleInfo();
} }
/**
* 初始化側邊欄菜單項
*/
private void initSideMenu() {
mRvSideMenu.setLayoutManager(new LinearLayoutManager(mContext));
List<MainSideMenuBean> mainSideMenuBeans = new ArrayList<>();
mainSideMenuBeans.add(new MainSideMenuBean(R.drawable.ic_mall_center, "商城中心"));
mainSideMenuBeans.add(new MainSideMenuBean(R.drawable.ic_about_us, "關於我們"));
mainSideMenuBeans.add(new MainSideMenuBean(R.drawable.ic_password, "修改密碼"));
mainSideMenuBeans.add(new MainSideMenuBean(R.drawable.ic_setting, "清機"));
mainSideMenuBeans.add(new MainSideMenuBean(R.drawable.ic_setting, "設置"));
if (BuildConfig.DEBUG) {
mainSideMenuBeans.add(new MainSideMenuBean(R.drawable.ic_setting, "切換環境"));
}
MainSideMenuAdapter adapter = new MainSideMenuAdapter(mainSideMenuBeans);
mRvSideMenu.setAdapter(adapter);
adapter.setOnItemClickListener((adapter1, view, position) -> {
switch (mainSideMenuBeans.get(position).getFunctionName()) {
case "切換環境":
//切換環境
CC.obtainBuilder("User.Component.Login")
.setActionName("switchServer")
.build()
.call();
finish();
break;
case "清機":
launchActivity(new Intent(mContext, SettlementActivity.class));
break;
}
});
}
public void onFinishRefresh() { public void onFinishRefresh() {
refresh.finishRefresh(); refresh.finishRefresh();
} }
...@@ -163,23 +198,23 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N ...@@ -163,23 +198,23 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N
// return; // return;
// } // }
List<Function> functions = new ArrayList<>(); List<Function> functions = new ArrayList<>();
functions.add(new Function((long) 150,0,5,"點餐",0)); functions.add(new Function((long) 150, 0, 5, "點餐", 0));
functions.add(new Function((long) 138,150,5,"餐臺模式",0)); functions.add(new Function((long) 138, 150, 5, "餐臺模式", R.drawable.ic_dining_table_mode));
functions.add(new Function((long) 139,150,5,"外送模式",0)); functions.add(new Function((long) 139, 150, 5, "外送模式", R.drawable.ic_delivery_mode));
functions.add(new Function((long) 140,150,5,"外賣模式",0)); functions.add(new Function((long) 140, 150, 5, "外賣模式", R.drawable.ic_outsourcing_model));
functions.add(new Function((long) 141,150,5,"預點餐模式",0)); functions.add(new Function((long) 141, 150, 5, "預點餐模式", R.drawable.ic_pre_order_mode));
functions.add(new Function((long) 151,0,5,"管理",0)); functions.add(new Function((long) 151, 0, 5, "管理", 0));
functions.add(new Function((long) 142,151,5,"餐牌管理",0)); functions.add(new Function((long) 142, 151, 5, "餐牌管理", R.drawable.ic_meals_menu_management));
functions.add(new Function((long) 143,151,5,"餐臺管理",0)); functions.add(new Function((long) 143, 151, 5, "餐臺管理", R.drawable.ic_dining_table_management));
functions.add(new Function((long) 144,151,5,"打印管理",0)); functions.add(new Function((long) 144, 151, 5, "打印管理", R.drawable.ic_print_management));
functions.add(new Function((long) 145,151,5,"支付管理",0)); functions.add(new Function((long) 145, 151, 5, "支付管理", R.drawable.ic_pay_management));
functions.add(new Function((long) 146,151,5,"折扣管理",0)); functions.add(new Function((long) 146, 151, 5, "折扣管理", R.drawable.ic_discount_management));
functions.add(new Function((long) 152,0,5,"員工",0)); functions.add(new Function((long) 152, 0, 5, "員工", 0));
functions.add(new Function((long) 147,152,5,"員工管理",0)); functions.add(new Function((long) 147, 152, 5, "員工管理", R.drawable.ic_staff_management));
functions.add(new Function((long) 148,152,5,"權限管理",0)); functions.add(new Function((long) 148, 152, 5, "權限管理", R.drawable.ic_authority_management));
functions.add(new Function((long) 149,152,5,"操作記錄",0)); functions.add(new Function((long) 149, 152, 5, "操作記錄", R.drawable.ic_operation_record));
//將功能列表數據分組 //將功能列表數據分組
SparseArray<String> parents = new SparseArray<>(); SparseArray<String> parents = new SparseArray<>();
SparseArray<List<Function>> funMap = new SparseArray<>(); SparseArray<List<Function>> funMap = new SparseArray<>();
...@@ -347,7 +382,7 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N ...@@ -347,7 +382,7 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N
finish(); finish();
} }
@OnClick({R2.id.layout_login_out, R2.id.iv_personal_center,R2.id.tv_restaurant_name,R2.id.ll_clearance}) @OnClick({R2.id.layout_login_out, R2.id.iv_personal_center,R2.id.tv_restaurant_name})
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if (v.getId() == R.id.layout_login_out) { if (v.getId() == R.id.layout_login_out) {
...@@ -357,15 +392,6 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N ...@@ -357,15 +392,6 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N
slideMenu.toggle(); slideMenu.toggle();
} else if (v.getId() == R.id.tv_restaurant_name) { } else if (v.getId() == R.id.tv_restaurant_name) {
showChooseRestaurantDialog(); showChooseRestaurantDialog();
} else if (v.getId() == R.id.ll_switch_server) {
//切換環境
CC.obtainBuilder("User.Component.Login")
.setActionName("switchServer")
.build()
.call();
finish();
} else if (v.getId() == R.id.ll_clearance) {
launchActivity(new Intent(this,SettlementActivity.class));
} }
} }
......
...@@ -24,7 +24,7 @@ public class MainOrderingAdapter extends BaseQuickAdapter<Function, BaseViewHold ...@@ -24,7 +24,7 @@ public class MainOrderingAdapter extends BaseQuickAdapter<Function, BaseViewHold
@Override @Override
protected void convert(BaseViewHolder helper, Function item) { protected void convert(BaseViewHolder helper, Function item) {
// helper.setImageResource(R.id.iv_main_home_item_function_icon, item.getImageURL()); helper.setImageResource(R.id.iv_main_home_item_function_icon, item.getIcRes());
helper.setText(R.id.tv_main_home_item_function_name, item.getResName()); helper.setText(R.id.tv_main_home_item_function_name, item.getResName());
} }
} }
package com.gingersoft.gsa.cloud.main.mvp.ui.adapter;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.gingersoft.gsa.cloud.main.R;
import com.gingersoft.gsa.cloud.main.mvp.model.bean.MainSideMenuBean;
import java.util.List;
import androidx.annotation.Nullable;
/**
* Created by Wyh on 2020/3/7.
*/
public class MainSideMenuAdapter extends BaseQuickAdapter<MainSideMenuBean, BaseViewHolder> {
public MainSideMenuAdapter(@Nullable List<MainSideMenuBean> data) {
super(R.layout.item_main_side_menu, data);
}
@Override
protected void convert(BaseViewHolder helper, MainSideMenuBean item) {
helper.setImageResource(R.id.iv_function_icon, item.getFunctionIcon());
helper.setText(R.id.tv_function_name, item.getFunctionName());
}
}
package com.gingersoft.gsa.cloud.main.mvp.ui.fragment; package com.gingersoft.gsa.cloud.main.mvp.ui.fragment;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources;
import android.graphics.DashPathEffect;
import android.os.Bundle; import android.os.Bundle;
import android.os.Message; import android.os.Message;
import android.view.LayoutInflater; import android.view.LayoutInflater;
...@@ -10,16 +8,6 @@ import android.view.View; ...@@ -10,16 +8,6 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import com.daivd.chart.component.axis.HorizontalAxis;
import com.daivd.chart.component.axis.VerticalAxis;
import com.daivd.chart.component.base.IAxis;
import com.daivd.chart.core.LineChart;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.LineData;
import com.daivd.chart.data.style.FontStyle;
import com.daivd.chart.data.style.LineStyle;
import com.daivd.chart.data.style.PointStyle;
import com.daivd.chart.provider.component.point.Point;
import com.gingersoft.gsa.cloud.base.application.GsaCloudApplication; import com.gingersoft.gsa.cloud.base.application.GsaCloudApplication;
import com.gingersoft.gsa.cloud.base.utils.time.TimePickerUtils; import com.gingersoft.gsa.cloud.base.utils.time.TimePickerUtils;
import com.gingersoft.gsa.cloud.base.utils.time.TimeUtils; import com.gingersoft.gsa.cloud.base.utils.time.TimeUtils;
...@@ -32,13 +20,18 @@ import com.gingersoft.gsa.cloud.main.mvp.model.bean.BusinessBean; ...@@ -32,13 +20,18 @@ import com.gingersoft.gsa.cloud.main.mvp.model.bean.BusinessBean;
import com.gingersoft.gsa.cloud.main.mvp.model.bean.HomeTurnoverBean; import com.gingersoft.gsa.cloud.main.mvp.model.bean.HomeTurnoverBean;
import com.gingersoft.gsa.cloud.main.mvp.presenter.BusinessReportPresenter; import com.gingersoft.gsa.cloud.main.mvp.presenter.BusinessReportPresenter;
import com.gingersoft.gsa.cloud.main.mvp.ui.adapter.BusinessInfoAdapter; import com.gingersoft.gsa.cloud.main.mvp.ui.adapter.BusinessInfoAdapter;
import com.gingersoft.gsa.cloud.main.mvp.ui.view.CustomMarkView; import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger.AAChartModel;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger.AAChartView;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger.AASeriesElement;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartLineDashStyleType;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartType;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AATools.AAGradientColor;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AATools.AALinearGradientDirection;
import com.jess.arms.base.BaseFragment; import com.jess.arms.base.BaseFragment;
import com.jess.arms.di.component.AppComponent; import com.jess.arms.di.component.AppComponent;
import com.jess.arms.utils.ArmsUtils; import com.jess.arms.utils.ArmsUtils;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -71,7 +64,7 @@ import static com.jess.arms.utils.Preconditions.checkNotNull; ...@@ -71,7 +64,7 @@ import static com.jess.arms.utils.Preconditions.checkNotNull;
public class BusinessReportFragment extends BaseFragment<BusinessReportPresenter> implements BusinessReportContract.View, View.OnClickListener { public class BusinessReportFragment extends BaseFragment<BusinessReportPresenter> implements BusinessReportContract.View, View.OnClickListener {
@BindView(R2.id.report_business_chart) @BindView(R2.id.report_business_chart)
LineChart mLineChart; AAChartView mLineChart;
@BindView(R2.id.rv_business_details) @BindView(R2.id.rv_business_details)
RecyclerView mBusinessDetails; RecyclerView mBusinessDetails;
@BindView(R2.id.tv_restaurant_name) @BindView(R2.id.tv_restaurant_name)
...@@ -106,7 +99,7 @@ public class BusinessReportFragment extends BaseFragment<BusinessReportPresenter ...@@ -106,7 +99,7 @@ public class BusinessReportFragment extends BaseFragment<BusinessReportPresenter
@Override @Override
public void initData(@Nullable Bundle savedInstanceState) { public void initData(@Nullable Bundle savedInstanceState) {
//獲取一段時間內的營業信息,默認獲取七天的數據 //獲取一段時間內的營業信息,默認獲取七天的數據
mPresenter.getRestaurantBusinessInfo(GsaCloudApplication.getRestaurantId(mContext) +"", TimeUtils.getOldDate(-6), TimeUtils.getOldDate(0)); mPresenter.getRestaurantBusinessInfo(GsaCloudApplication.getRestaurantId(mContext) + "", TimeUtils.getOldDate(-6), TimeUtils.getOldDate(0));
mRestaurantName.setText(GsaCloudApplication.getRestaurantName(mContext)); mRestaurantName.setText(GsaCloudApplication.getRestaurantName(mContext));
mTvStartTime.setText(TimeUtils.getOldDate(-6)); mTvStartTime.setText(TimeUtils.getOldDate(-6));
...@@ -188,107 +181,75 @@ public class BusinessReportFragment extends BaseFragment<BusinessReportPresenter ...@@ -188,107 +181,75 @@ public class BusinessReportFragment extends BaseFragment<BusinessReportPresenter
*/ */
@Override @Override
public void loadChart(Map<String, HomeTurnoverBean.DataBean> data) { public void loadChart(Map<String, HomeTurnoverBean.DataBean> data) {
Resources res = getResources(); Object[] chartData = new Object[7];
FontStyle.setDefaultTextSpSize(mContext, 12);
List<String> chartYDataList = new ArrayList<>(); String[] xData = new String[7];
for (int i = 0; i < 7; i++) { for (int i = 0; i < 7; i++) {
chartYDataList.add(TimeUtils.getDistanceDate(-6 + i, Calendar.DATE, TimeUtils.DEFAULT_DATE_MD)); xData[i] = TimeUtils.getDistanceDate(-6 + i, Calendar.DATE, TimeUtils.DEFAULT_DATE_MD);
} }
List<LineData> ColumnDatas = new ArrayList<>();
double yAxisTickInterval = 0;
//第一條線 //第一條線
ArrayList<Double> tempList1 = new ArrayList<>(); for (int i = 0; i < 7; i++) {
for (int i = 0; i < chartYDataList.size(); i++) {
//通過今年年份+月份+日期,獲取對應的對象 //通過今年年份+月份+日期,獲取對應的對象
HomeTurnoverBean.DataBean bean = data.get(TimeUtils.getDistanceDate(0, Calendar.YEAR, DEFAULT_DATE_Y) + chartYDataList.get(i)); HomeTurnoverBean.DataBean bean = data.get(TimeUtils.getDistanceDate(0, Calendar.YEAR, DEFAULT_DATE_Y) + xData[i]);
if (bean != null && bean.getBusiness_amount() != null) { if (bean != null && bean.getBusiness_amount() != null) {
tempList1.add(Double.parseDouble(bean.getBusiness_amount())); chartData[i] = Integer.parseInt(bean.getBusiness_amount());
yAxisTickInterval = Math.max(yAxisTickInterval, Integer.parseInt(bean.getBusiness_amount()));
} else { } else {
tempList1.add(0d); chartData[i] = 0;
} }
} }
AAChartModel aaChartModel = configureColorfulGradientSplineChart(xData, chartData, (int) (yAxisTickInterval / 6));
if (yAxisTickInterval == 0) {
aaChartModel.yAxisMax(18000f);
aaChartModel.yAxisTickInterval(3000);
} else {
aaChartModel.yAxisMax(null);
}
mLineChart.aa_drawChartWithChartModel(aaChartModel);
}
/**
* @param todayData 今天的數據
* @param yAxisTickInterval y軸間隔
* @return
*/
AAChartModel configureColorfulGradientSplineChart(String[] xData, Object[] todayData, int yAxisTickInterval) {
Object[][] stopsArr = {
{0.00, "#018EF2"},
};//颜色字符串设置支持十六进制类型和 rgba 类型
Map linearGradientColor = AAGradientColor.linearGradient(
AALinearGradientDirection.ToLeft,
stopsArr
);//颜色字符串设置支持十六进制类型和 rgba 类型
final LineData columnData1 = new LineData("今日", "", getResources().getColor(R.color.theme_color), tempList1); return new AAChartModel()
columnData1.setLineStyle(new LineStyle(mContext, 5, getResources().getColor(R.color.theme_color))); .chartType(AAChartType.Spline)
ColumnDatas.add(columnData1); .title("")
.subtitle("")
ChartData<LineData> chartData2 = new ChartData<>("Line chart", chartYDataList, ColumnDatas); .yAxisTitle("")
//設置曲線圖樣式 .axesTextColor("#777777")
mLineChart.setLineModel(LineChart.CURVE_MODEL); .axesTextSize(9)
//獲取左側垂直軸線 .legendEnabled(false)
VerticalAxis verticalAxis = mLineChart.getLeftVerticalAxis(); .markerRadius(0f)
//獲取橫向軸線 .categories(xData)
HorizontalAxis horizontalAxis = mLineChart.getHorizontalAxis(); .yAxisLineWidth(0.5f)
//右側軸線 .xAxisLineWidth(0.5f)
VerticalAxis rightAxis = mLineChart.getRightVerticalAxis(); .yAxisTickInterval(yAxisTickInterval)
//設置右側軸線不顯示 .gridLineColor("#8CA0B3")
rightAxis.setDisplay(false); .yAxisMin(0f)
//设置竖轴方向在左側 .gridLineDashStyle(AAChartLineDashStyleType.ShortDash)
verticalAxis.setAxisDirection(IAxis.AxisDirection.LEFT); .dataLabelsFontColor("#777777")
verticalAxis.setStartZero(true); .yAxisLineColor("#018EF2")
//设置网格 .series(new AASeriesElement[]{
verticalAxis.setDrawGrid(true); new AASeriesElement()
//设置横轴方向 .name("今天")
horizontalAxis.setAxisDirection(IAxis.AxisDirection.BOTTOM); .lineWidth(4f)
//不顯示網格 .color(linearGradientColor)
horizontalAxis.setDrawGrid(false); .data(todayData)
horizontalAxis.getAxisStyle().setWidth(mContext, 1).setColor(res.getColor(R.color.theme_color)); }
//设置线条样式 );
verticalAxis.getAxisStyle().setWidth(mContext, 1).setColor(res.getColor(R.color.theme_color));
//設置網格虛線樣式
DashPathEffect effects = new DashPathEffect(new float[]{1, 2, 4, 8}, 1);
verticalAxis.setGridStyle(new LineStyle(0.5f, res.getColor(R.color.report_dotted_line_color)));
verticalAxis.getGridStyle().setEffect(effects);
FontStyle scaleStyle = new FontStyle(mContext, 9, res.getColor(R.color.report_left_scale));
scaleStyle.setScalePadding(30);
horizontalAxis.setScaleStyle(scaleStyle);
verticalAxis.setScaleStyle(scaleStyle);
mLineChart.setZoom(false);
//开启十字架
mLineChart.getProvider().setOpenCross(true);
//關閉硬件加速
mLineChart.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
//开启MarkView
mLineChart.getProvider().setOpenMark(true);
//设置MarkView
mLineChart.getProvider().setMarkView(new CustomMarkView(columnData1));
//设置显示点
Point point = new Point();
point.getPointStyle().setShape(PointStyle.CIRCLE);
//设置显示点的样式
mLineChart.getProvider().setPoint(point);
//设置显示标题
mLineChart.setShowChartName(false);
//底部不顯示顏色代表的意思
mLineChart.getLegend().setDisplay(false);
mLineChart.getMatrixHelper().setWidthMultiple(0.9f);
mLineChart.getHorizontalAxis().setRotateAngle(0);//設置底部文字旋轉角度
mLineChart.setFirstAnim(false);
mLineChart.setChartData(chartData2);
mLineChart.setOnClickColumnListener((lineData, pos) -> {
// Paint paint = new Paint();
// paint.setAntiAlias(true);
// paint.setTextSize(DensityUtils.sp2px(mContext, 13));
// paint.setStyle(Paint.Style.FILL);
// paint.setColor(Color.WHITE);
// MultiLineBubbleTip tip = new MultiLineBubbleTip<LineData>(mContext,
// R.mipmap.round_rect, R.mipmap.triangle, paint) {
// @Override
// public boolean isShowTip(LineData lineData, int position) {
// return position == pos;
// }
//
// @Override
// public String[] format(LineData lineData, int position) {
// String title = lineData.getName();
// String value = lineData.getChartYDataList().get(position) + lineData.getUnit();
// return new String[]{title, value};
// }
// };
// tip.setColorFilter(Color.parseColor("#FA8072"));
// tip.setAlpha(0.8f);
// mLineChart.getProvider().setTip(tip);
// mLineChart.invalidate();
});
} }
@Override @Override
......
package com.gingersoft.gsa.cloud.main.mvp.ui.fragment; package com.gingersoft.gsa.cloud.main.mvp.ui.fragment;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources;
import android.graphics.DashPathEffect;
import android.os.Bundle; import android.os.Bundle;
import android.os.Message; import android.os.Message;
import android.util.SparseArray; import android.util.SparseArray;
...@@ -12,16 +10,6 @@ import android.view.ViewGroup; ...@@ -12,16 +10,6 @@ import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.daivd.chart.component.axis.HorizontalAxis;
import com.daivd.chart.component.axis.VerticalAxis;
import com.daivd.chart.component.base.IAxis;
import com.daivd.chart.core.LineChart;
import com.daivd.chart.data.ChartData;
import com.daivd.chart.data.LineData;
import com.daivd.chart.data.style.FontStyle;
import com.daivd.chart.data.style.LineStyle;
import com.daivd.chart.data.style.PointStyle;
import com.daivd.chart.provider.component.point.Point;
import com.gingersoft.gsa.cloud.base.application.GsaCloudApplication; import com.gingersoft.gsa.cloud.base.application.GsaCloudApplication;
import com.gingersoft.gsa.cloud.base.utils.MoneyUtil; import com.gingersoft.gsa.cloud.base.utils.MoneyUtil;
import com.gingersoft.gsa.cloud.base.utils.time.TimeUtils; import com.gingersoft.gsa.cloud.base.utils.time.TimeUtils;
...@@ -35,12 +23,17 @@ import com.gingersoft.gsa.cloud.main.mvp.model.bean.MainOrderInfoChartBean; ...@@ -35,12 +23,17 @@ import com.gingersoft.gsa.cloud.main.mvp.model.bean.MainOrderInfoChartBean;
import com.gingersoft.gsa.cloud.main.mvp.presenter.MainTopPresenter; import com.gingersoft.gsa.cloud.main.mvp.presenter.MainTopPresenter;
import com.gingersoft.gsa.cloud.main.mvp.ui.activity.NewMainActivity; import com.gingersoft.gsa.cloud.main.mvp.ui.activity.NewMainActivity;
import com.gingersoft.gsa.cloud.main.mvp.ui.activity.ReportActivity; import com.gingersoft.gsa.cloud.main.mvp.ui.activity.ReportActivity;
import com.gingersoft.gsa.cloud.main.mvp.ui.view.CustomMarkView; import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger.AAChartModel;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger.AAChartView;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger.AASeriesElement;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartLineDashStyleType;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartType;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AATools.AAGradientColor;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AATools.AALinearGradientDirection;
import com.jess.arms.base.BaseFragment; import com.jess.arms.base.BaseFragment;
import com.jess.arms.di.component.AppComponent; import com.jess.arms.di.component.AppComponent;
import com.jess.arms.utils.ArmsUtils; import com.jess.arms.utils.ArmsUtils;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -66,9 +59,9 @@ import static com.jess.arms.utils.Preconditions.checkNotNull; ...@@ -66,9 +59,9 @@ import static com.jess.arms.utils.Preconditions.checkNotNull;
* ================================================ * ================================================
*/ */
public class MainTopFragment extends BaseFragment<MainTopPresenter> implements MainTopContract.View, View.OnClickListener { public class MainTopFragment extends BaseFragment<MainTopPresenter> implements MainTopContract.View, View.OnClickListener {
// line_chart_view private AAChartModel aaChartModel;
@BindView(R2.id.line_chart_view) @BindView(R2.id.line_chart_view)
LineChart lineChart; AAChartView lineChart;
@BindView(R2.id.tv_today_amount) @BindView(R2.id.tv_today_amount)
TextView tvTurnover;//今日營業額 TextView tvTurnover;//今日營業額
@BindView(R2.id.tv_today_time) @BindView(R2.id.tv_today_time)
...@@ -255,12 +248,68 @@ public class MainTopFragment extends BaseFragment<MainTopPresenter> implements M ...@@ -255,12 +248,68 @@ public class MainTopFragment extends BaseFragment<MainTopPresenter> implements M
} }
} }
/**
* @param todayData 今天的數據
* @param yesterdayData 昨天的數據
* @param yAxisTickInterval y軸間隔
* @return
*/
AAChartModel configureColorfulGradientSplineChart(Object[] todayData, Object[] yesterdayData, int yAxisTickInterval) {
Object[][] stopsArr = {
{0.00, "#018EF2"},
};//颜色字符串设置支持十六进制类型和 rgba 类型
Object[][] stopsArr2 = {
{1.00, "#FFCC8F"}
};//颜色字符串设置支持十六进制类型和 rgba 类型
Map linearGradientColor = AAGradientColor.linearGradient(
AALinearGradientDirection.ToLeft,
stopsArr
);//颜色字符串设置支持十六进制类型和 rgba 类型
Map linearGradientColor2 = AAGradientColor.linearGradient(
AALinearGradientDirection.ToLeft,
stopsArr2
);//颜色字符串设置支持十六进制类型和 rgba 类型
return new AAChartModel()
.chartType(AAChartType.Spline)
.title("")
.subtitle("")
.yAxisTitle("")
.axesTextColor("#777777")
.axesTextSize(9)
.legendEnabled(false)
.categories(new String[]{"00:00", "01:00", "02:00", "03:00", "04:00", "05:00", "06:00", "07:00", "08:00", "09:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", "17:00", "18:00", "19:00", "20:00", "21:00", "22:00", "23:00", "24:00"})
.yAxisLineWidth(0.5f)
.xAxisLineWidth(0.5f)
.xAxisTickInterval(4)
.yAxisTickInterval(yAxisTickInterval)
.markerRadius(0f)
.yAxisMin(0f)
.gridLineColor("#FF8CA0B3")
.gridLineDashStyle(AAChartLineDashStyleType.ShortDash)
.dataLabelsFontColor("#777777")
.yAxisLineColor("#018EF2")
.series(new AASeriesElement[]{
new AASeriesElement()
.name("昨日")
.lineWidth(4f)
.color(linearGradientColor2)
.data(yesterdayData),
new AASeriesElement()
.name("今日")
.lineWidth(4f)
.color(linearGradientColor)
.data(todayData)
}
);
}
@Override @Override
public void loadChart(List<MainOrderInfoChartBean.DataBean> dataBeans) { public void loadChart(List<MainOrderInfoChartBean.DataBean> dataBeans) {
((NewMainActivity)getActivity()).onFinishRefresh(); ((NewMainActivity) getActivity()).onFinishRefresh();//結束刷新
Resources res = getResources(); Object[] todayData = new Object[24];//今天的數據
FontStyle.setDefaultTextSpSize(mContext, 12); Object[] yesterdayData = new Object[24];//昨天的數據
//存儲今天的線條數據 //存儲今天的線條數據
SparseArray<MainOrderInfoChartBean.DataBean.ItemsBean> dataBeanMap = new SparseArray<>(); SparseArray<MainOrderInfoChartBean.DataBean.ItemsBean> dataBeanMap = new SparseArray<>();
SparseArray<MainOrderInfoChartBean.DataBean.ItemsBean> yesterdayArrays = new SparseArray<>(); SparseArray<MainOrderInfoChartBean.DataBean.ItemsBean> yesterdayArrays = new SparseArray<>();
...@@ -278,122 +327,33 @@ public class MainTopFragment extends BaseFragment<MainTopPresenter> implements M ...@@ -278,122 +327,33 @@ public class MainTopFragment extends BaseFragment<MainTopPresenter> implements M
} }
} }
} }
List<LineData> ColumnDatas = new ArrayList<>(); double maxAmount = 0;//最大金額,y軸顯示七個數,最大金額除以7,得到間隔數字
//第一條線
ArrayList<Double> tempList1 = new ArrayList<>();
final LineData columnData1 = new LineData("今日", "", getResources().getColor(R.color.theme_color), tempList1);
columnData1.setLineStyle(new LineStyle(mContext, 5, getResources().getColor(R.color.theme_color)));
//第二條線
ArrayList<Double> humidityList = new ArrayList<>();
LineData columnData2 = new LineData("昨日", "", getResources().getColor(R.color.today_line), humidityList);
columnData2.setLineStyle(new LineStyle(mContext, 5, getResources().getColor(R.color.today_line)));
//X軸數據,固定不變
List<String> chartYDataList = new ArrayList<>();
for (int i = 0; i < 24; i++) { for (int i = 0; i < 24; i++) {
if (i < 10) {
chartYDataList.add("0" + i + ":00");
} else {
chartYDataList.add(i + ":00");
}
//添加今天的數據 //添加今天的數據
if (dataBeanMap.get(i) != null) { if (dataBeanMap.get(i) != null) {
tempList1.add(dataBeanMap.get(i).getAmount()); todayData[i] = dataBeanMap.get(i).getAmount();
maxAmount = Math.max(maxAmount, dataBeanMap.get(i).getAmount());
} else { } else {
tempList1.add(0d); todayData[i] = 0d;
} }
//添加昨天的數據 //添加昨天的數據
if (yesterdayArrays.get(i) != null) { if (yesterdayArrays.get(i) != null) {
humidityList.add(yesterdayArrays.get(i).getAmount()); yesterdayData[i] = yesterdayArrays.get(i).getAmount();
maxAmount = Math.max(maxAmount, yesterdayArrays.get(i).getAmount());
} else { } else {
humidityList.add(0d); yesterdayData[i] = 0d;
} }
} }
ColumnDatas.add(columnData2);
ColumnDatas.add(columnData1);
ChartData<LineData> chartData2 = new ChartData<>("Line chart", chartYDataList, ColumnDatas);
//設置曲線圖樣式
lineChart.setLineModel(LineChart.CURVE_MODEL);
//獲取左側垂直軸線
VerticalAxis verticalAxis = lineChart.getLeftVerticalAxis();
//獲取橫向軸線
HorizontalAxis horizontalAxis = lineChart.getHorizontalAxis();
//右側軸線
VerticalAxis rightAxis = lineChart.getRightVerticalAxis();
//設置右側軸線不顯示
rightAxis.setDisplay(false);
//设置竖轴方向在左側
verticalAxis.setAxisDirection(IAxis.AxisDirection.LEFT);
verticalAxis.setStartZero(true);
// verticalAxis.setMaxValue(18000);
//设置网格
verticalAxis.setDrawGrid(true);
//设置横轴方向
horizontalAxis.setAxisDirection(IAxis.AxisDirection.BOTTOM);
//不顯示網格
horizontalAxis.setDrawGrid(false);
horizontalAxis.getAxisStyle().setWidth(mContext, 1).setColor(res.getColor(R.color.theme_color));
//设置线条样式
verticalAxis.getAxisStyle().setWidth(mContext, 1).setColor(res.getColor(R.color.theme_color));
//設置網格虛線樣式
DashPathEffect effects = new DashPathEffect(new float[]{1, 2, 4, 8}, 1);
verticalAxis.setGridStyle(new LineStyle(0.5f, res.getColor(R.color.report_dotted_line_color)));
verticalAxis.getGridStyle().setEffect(effects);
FontStyle scaleStyle = new FontStyle(mContext, 9, res.getColor(R.color.report_left_scale));
scaleStyle.setScalePadding(30);
horizontalAxis.setScaleStyle(scaleStyle);
verticalAxis.setScaleStyle(scaleStyle);
lineChart.setZoom(false);
//开启十字架
lineChart.getProvider().setOpenCross(true);
//關閉硬件加速
lineChart.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
//开启MarkView
lineChart.getProvider().setOpenMark(true);
//设置MarkView
lineChart.getProvider().setMarkView(new CustomMarkView(columnData1, columnData2));
//设置显示点
Point point = new Point();
point.getPointStyle().setShape(PointStyle.CIRCLE);
//设置显示点的样式
lineChart.getProvider().setPoint(point);
//设置显示标题
lineChart.setShowChartName(false);
//底部不顯示顏色代表的意思
lineChart.getLegend().setDisplay(false);
// lineChart.getMatrixHelper().setWidthMultiple(1f);
lineChart.getMatrixHelper().setCanZoom(false);
lineChart.getHorizontalAxis().setRotateAngle(0);//設置底部文字旋轉角度
lineChart.setFirstAnim(true);
lineChart.setChartData(chartData2);
lineChart.setOnClickColumnListener((lineData, pos) -> {
// Paint paint = new Paint();
// paint.setAntiAlias(true);
// paint.setTextSize(DensityUtils.sp2px(mContext, 13));
// paint.setStyle(Paint.Style.FILL);
// paint.setColor(Color.WHITE);
// MultiLineBubbleTip tip = new MultiLineBubbleTip<LineData>(mContext,
// R.mipmap.round_rect, R.mipmap.triangle, paint) {
// @Override
// public boolean isShowTip(LineData lineData, int position) {
// return position == pos;
// }
//
// @Override
// public String[] format(LineData lineData, int position) {
// String title = lineData.getName();
// String value = lineData.getChartYDataList().get(position) + lineData.getUnit();
// return new String[]{title, value};
// }
// };
// tip.setColorFilter(Color.parseColor("#FA8072"));
// tip.setAlpha(0.8f);
// lineChart.getProvider().setTip(tip);
// lineChart.invalidate();
});
//初始化曲線圖
aaChartModel = configureColorfulGradientSplineChart(todayData, yesterdayData, (int) (maxAmount / 6));
if (maxAmount == 0) {
aaChartModel.yAxisMax(18000f);
aaChartModel.yAxisTickInterval(3000);
} else {
aaChartModel.yAxisMax(null);
}
lineChart.aa_drawChartWithChartModel(aaChartModel);
} }
private int getTrendImg(double amount) { private int getTrendImg(double amount) {
......
package com.gingersoft.gsa.cloud.main.mvp.ui.view; //package com.gingersoft.gsa.cloud.main.mvp.ui.view;
//
//
import android.graphics.Canvas; //import android.graphics.Canvas;
import android.graphics.Color; //import android.graphics.Color;
import android.graphics.Paint; //import android.graphics.Paint;
import android.graphics.Rect; //import android.graphics.Rect;
import android.graphics.RectF; //import android.graphics.RectF;
//
import com.daivd.chart.data.BarData; //import com.daivd.chart.data.BarData;
import com.daivd.chart.data.LineData; //import com.daivd.chart.data.LineData;
import com.daivd.chart.provider.component.mark.IMark; //import com.daivd.chart.provider.component.mark.IMark;
//
/** ///**
* Created by huang on 2017/9/28. // * Created by huang on 2017/9/28.
*/ // */
//
public class CustomMarkView<C extends BarData> implements IMark<C> { //public class CustomMarkView<C extends BarData> implements IMark<C> {
private Paint paint; // private Paint paint;
private int mTodayColor = Color.parseColor("#018EF2"); // private int mTodayColor = Color.parseColor("#018EF2");
private int mYesterDayColor = Color.parseColor("#FFCC8F"); // private int mYesterDayColor = Color.parseColor("#FFCC8F");
private LineData columnData; // private LineData columnData;
private LineData columnData2; // private LineData columnData2;
//
public CustomMarkView(LineData columnData) { // public CustomMarkView(LineData columnData) {
this.columnData = columnData; // this.columnData = columnData;
initPaint(); // initPaint();
} // }
//
public CustomMarkView(LineData columnData, LineData columnData2) { // public CustomMarkView(LineData columnData, LineData columnData2) {
this.columnData = columnData; // this.columnData = columnData;
this.columnData2 = columnData2; // this.columnData2 = columnData2;
initPaint(); // initPaint();
} // }
//
private void initPaint() { // private void initPaint() {
paint = new Paint(); // paint = new Paint();
paint.setAntiAlias(true); // paint.setAntiAlias(true);
paint.setTextSize(34); // paint.setTextSize(34);
paint.setStyle(Paint.Style.FILL); // paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor("#333333")); // paint.setColor(Color.parseColor("#333333"));
} // }
//
public CustomMarkView setTodayColor() { // public CustomMarkView setTodayColor() {
return this; // return this;
} // }
//
public Paint getPaint() { // public Paint getPaint() {
return paint; // return paint;
} // }
//
public int getTextHeight() { // public int getTextHeight() {
Paint.FontMetrics fontMetrics = getPaint().getFontMetrics(); // Paint.FontMetrics fontMetrics = getPaint().getFontMetrics();
return (int) (fontMetrics.bottom - fontMetrics.top); // return (int) (fontMetrics.bottom - fontMetrics.top);
} // }
//
//
public int getTextWidth(String content) { // public int getTextWidth(String content) {
return (int) getPaint().measureText(content); // return (int) getPaint().measureText(content);
} // }
//
private int verticalPadding = 15; // private int verticalPadding = 15;
private int horizontalPadding = 15; // private int horizontalPadding = 15;
private int contentInterval = 7;//內容空隙 // private int contentInterval = 7;//內容空隙
private int ovalWidth = 23;//圓點的寬度 // private int ovalWidth = 23;//圓點的寬度
//
@Override // @Override
public void drawMark(Canvas canvas, float x, float y, Rect rect, String content, BarData d, int position) { // public void drawMark(Canvas canvas, float x, float y, Rect rect, String content, BarData d, int position) {
float rectWidth = 0;//矩形寬度 // float rectWidth = 0;//矩形寬度
float rectHeight = 0;//矩形高度 // float rectHeight = 0;//矩形高度
int row = 0; // int row = 0;
float textHeight = getTextHeight(); // float textHeight = getTextHeight();
String content1 = null, content2 = null; // String content1 = null, content2 = null;
if (columnData != null && columnData.getName() != null && position <= columnData.getChartYDataList().size()) { // if (columnData != null && columnData.getName() != null && position <= columnData.getChartYDataList().size()) {
content1 = columnData.getName() + columnData.getChartYDataList().get(position); // content1 = columnData.getName() + columnData.getChartYDataList().get(position);
} // }
if (columnData2 != null && columnData2.getChartYDataList() != null && position <= columnData2.getChartYDataList().size()) { // if (columnData2 != null && columnData2.getChartYDataList() != null && position <= columnData2.getChartYDataList().size()) {
content2 = columnData2.getName() + columnData2.getChartYDataList().get(position); // content2 = columnData2.getName() + columnData2.getChartYDataList().get(position);
} // }
if (content != null) { // if (content != null) {
row++; // row++;
rectWidth = Math.max(rectWidth, getTextWidth(content)); // rectWidth = Math.max(rectWidth, getTextWidth(content));
} // }
if (content1 != null) { // if (content1 != null) {
row++; // row++;
rectWidth = Math.max(rectWidth, getTextWidth(content1)); // rectWidth = Math.max(rectWidth, getTextWidth(content1));
} // }
if (content2 != null) { // if (content2 != null) {
row++; // row++;
rectWidth = Math.max(rectWidth, getTextWidth(content2)); // rectWidth = Math.max(rectWidth, getTextWidth(content2));
} // }
//矩形寬度=圓點寬度+圓點與內容的間距+左右間距 // //矩形寬度=圓點寬度+圓點與內容的間距+左右間距
rectWidth += ovalWidth + contentInterval + horizontalPadding * 2; // rectWidth += ovalWidth + contentInterval + horizontalPadding * 2;
//矩形高度=三行文字的高度+三行文字中間是兩行間距+上下間距 // //矩形高度=三行文字的高度+三行文字中間是兩行間距+上下間距
rectHeight = getTextHeight() * row + contentInterval * 2 + verticalPadding * 2; // rectHeight = getTextHeight() * row + contentInterval * 2 + verticalPadding * 2;
float selfWidth = rectWidth / 2; // float selfWidth = rectWidth / 2;
float selfHeight = rectHeight / 2; // float selfHeight = rectHeight / 2;
//
RectF rectf = new RectF(x - selfWidth, y - selfHeight, x + selfWidth, y + selfHeight); // RectF rectf = new RectF(x - selfWidth, y - selfHeight, x + selfWidth, y + selfHeight);
//判斷在有效範圍內 // //判斷在有效範圍內
if (x > rect.left && x < rect.right) { // if (x > rect.left && x < rect.right) {
if (rectf.left < rect.left) { // if (rectf.left < rect.left) {
rectf.left = rect.left; // rectf.left = rect.left;
rectf.right = rect.left + rectWidth; // rectf.right = rect.left + rectWidth;
} // }
if (rectf.right > rect.right) { // if (rectf.right > rect.right) {
rectf.right = rect.right; // rectf.right = rect.right;
rectf.left = rect.right - rectWidth; // rectf.left = rect.right - rectWidth;
} // }
} // }
//設置陰影 // //設置陰影
paint.setShadowLayer(10, 0, 0, Color.parseColor("#33000000")); //第一个参数是阴影扩散半径,紧接着的2个参数是阴影在X和Y方向的偏移量,最后一个参数是颜色 // paint.setShadowLayer(10, 0, 0, Color.parseColor("#33000000")); //第一个参数是阴影扩散半径,紧接着的2个参数是阴影在X和Y方向的偏移量,最后一个参数是颜色
paint.setColor(Color.parseColor("#FFFFFF")); // paint.setColor(Color.parseColor("#FFFFFF"));
canvas.drawRoundRect(rectf, 8, 8, paint); // canvas.drawRoundRect(rectf, 8, 8, paint);
//清除陰影 // //清除陰影
paint.clearShadowLayer(); // paint.clearShadowLayer();
//繪製時間 // //繪製時間
paint.setColor(Color.parseColor("#333333")); // paint.setColor(Color.parseColor("#333333"));
if (content != null) { // if (content != null) {
canvas.drawText(content, rectf.left + horizontalPadding + ovalWidth + contentInterval, rectf.top + verticalPadding + textHeight, paint); // canvas.drawText(content, rectf.left + horizontalPadding + ovalWidth + contentInterval, rectf.top + verticalPadding + textHeight, paint);
} // }
float ovalHeight = (textHeight - ovalWidth) / 2;//圓和文字上下空隙,為了居中顯示 // float ovalHeight = (textHeight - ovalWidth) / 2;//圓和文字上下空隙,為了居中顯示
if (content2 != null) { // if (content2 != null) {
canvas.drawText(content2, rectf.left + horizontalPadding + ovalWidth + contentInterval, rectf.top + verticalPadding + contentInterval + textHeight * 2, paint); // canvas.drawText(content2, rectf.left + horizontalPadding + ovalWidth + contentInterval, rectf.top + verticalPadding + contentInterval + textHeight * 2, paint);
paint.setColor(columnData2.getLineStyle().getColor()); // paint.setColor(columnData2.getLineStyle().getColor());
RectF yesterDayOvalRect = new RectF(rectf.left + horizontalPadding, rectf.top + verticalPadding + contentInterval + textHeight + ovalWidth - ovalHeight, rectf.left + horizontalPadding + ovalWidth, rectf.top + verticalPadding + contentInterval + textHeight + ovalWidth * 2 - ovalHeight); // RectF yesterDayOvalRect = new RectF(rectf.left + horizontalPadding, rectf.top + verticalPadding + contentInterval + textHeight + ovalWidth - ovalHeight, rectf.left + horizontalPadding + ovalWidth, rectf.top + verticalPadding + contentInterval + textHeight + ovalWidth * 2 - ovalHeight);
canvas.drawOval(yesterDayOvalRect, paint); // canvas.drawOval(yesterDayOvalRect, paint);
} // }
if (content1 != null) { // if (content1 != null) {
paint.setColor(Color.parseColor("#333333")); // paint.setColor(Color.parseColor("#333333"));
canvas.drawText(content1, rectf.left + horizontalPadding + ovalWidth + contentInterval, rectf.top + verticalPadding + contentInterval * 2 + textHeight * row, paint); // canvas.drawText(content1, rectf.left + horizontalPadding + ovalWidth + contentInterval, rectf.top + verticalPadding + contentInterval * 2 + textHeight * row, paint);
paint.setColor(columnData.getLineStyle().getColor()); // paint.setColor(columnData.getLineStyle().getColor());
RectF yesterDayOvalRect = new RectF(rectf.left + horizontalPadding, rectf.top + verticalPadding + contentInterval * 2 + (textHeight * (row - 1)) + ovalWidth - ovalHeight, rectf.left + horizontalPadding + ovalWidth, rectf.top + verticalPadding + contentInterval * 2 + (textHeight * (row - 1)) + ovalWidth * 2 - ovalHeight); // RectF yesterDayOvalRect = new RectF(rectf.left + horizontalPadding, rectf.top + verticalPadding + contentInterval * 2 + (textHeight * (row - 1)) + ovalWidth - ovalHeight, rectf.left + horizontalPadding + ovalWidth, rectf.top + verticalPadding + contentInterval * 2 + (textHeight * (row - 1)) + ovalWidth * 2 - ovalHeight);
canvas.drawOval(yesterDayOvalRect, paint); // canvas.drawOval(yesterDayOvalRect, paint);
} // }
} // }
} //}
...@@ -8,10 +8,11 @@ import android.view.ViewGroup; ...@@ -8,10 +8,11 @@ import android.view.ViewGroup;
import android.widget.HorizontalScrollView; import android.widget.HorizontalScrollView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import com.daivd.chart.utils.DensityUtils;
import com.jess.arms.utils.ArmsUtils; import com.jess.arms.utils.ArmsUtils;
import com.nineoldandroids.view.ViewHelper; import com.nineoldandroids.view.ViewHelper;
import static com.qmuiteam.qmui.util.QMUIDisplayHelper.dp2px;
/** /**
* des :SlidingMenu 侧边栏 侧滑菜单 * des :SlidingMenu 侧边栏 侧滑菜单
*/ */
...@@ -50,7 +51,7 @@ public class SlidingMenu extends HorizontalScrollView { ...@@ -50,7 +51,7 @@ public class SlidingMenu extends HorizontalScrollView {
// } // }
// } // }
// a.recycle(); // a.recycle();
mMenuRightPadding = DensityUtils.dp2px(context, 140); mMenuRightPadding = dp2px(context, 140);
} }
@Override @Override
......
...@@ -9,7 +9,8 @@ ...@@ -9,7 +9,8 @@
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="horizontal"><!-- 側邊欄內容--> android:orientation="horizontal">
<!-- 側邊欄內容-->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
...@@ -50,142 +51,10 @@ ...@@ -50,142 +51,10 @@
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="@dimen/sp_20" /> android:textSize="@dimen/sp_20" />
<LinearLayout <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent" android:id="@+id/rv_side_menu"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_37"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="@dimen/dp_29"
android:layout_height="@dimen/dp_27"
android:layout_marginLeft="@dimen/dp_18"
android:src="@drawable/ic_mall_center" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_14"
android:text="商城中心"
android:textColor="@color/white"
android:textSize="@dimen/sp_17" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_28"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="@dimen/dp_29"
android:layout_height="@dimen/dp_27"
android:layout_marginLeft="@dimen/dp_18"
android:src="@drawable/ic_about_us" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_14"
android:text="關於我們"
android:textColor="@color/white"
android:textSize="@dimen/sp_17" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_28"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="@dimen/dp_29"
android:layout_height="@dimen/dp_27"
android:layout_marginLeft="@dimen/dp_18"
android:src="@drawable/ic_password" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_14"
android:text="修改密碼"
android:textColor="@color/white"
android:textSize="@dimen/sp_17" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_switch_server"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_28"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="@dimen/dp_29"
android:layout_height="@dimen/dp_27"
android:layout_marginLeft="@dimen/dp_18"
android:src="@drawable/ic_password" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_14"
android:text="切換環境"
android:textColor="@color/white"
android:textSize="@dimen/sp_17" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_marginTop="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_28"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="@dimen/dp_29"
android:layout_height="@dimen/dp_27"
android:layout_marginLeft="@dimen/dp_18"
android:src="@drawable/ic_setting" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_14"
android:text="設置"
android:textColor="@color/white"
android:textSize="@dimen/sp_17" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_clearance"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_28"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="@dimen/dp_29"
android:layout_height="@dimen/dp_27"
android:layout_marginLeft="@dimen/dp_18"
android:src="@drawable/ic_setting" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_14"
android:text="清機"
android:textColor="@color/white"
android:textSize="@dimen/sp_17" />
</LinearLayout>
<View
android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" /> android:layout_weight="1" />
......
...@@ -73,11 +73,11 @@ ...@@ -73,11 +73,11 @@
android:textSize="@dimen/sp_10" /> android:textSize="@dimen/sp_10" />
</LinearLayout> </LinearLayout>
<com.daivd.chart.core.LineChart <com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger.AAChartView
android:id="@+id/report_business_chart" android:id="@+id/report_business_chart"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/dp_130" android:layout_height="@dimen/dp_150"
android:layout_marginTop="@dimen/dp_17" /> android:layout_marginTop="@dimen/dp_10" />
</LinearLayout> </LinearLayout>
</com.lihang.ShadowLayout> </com.lihang.ShadowLayout>
......
...@@ -27,8 +27,8 @@ ...@@ -27,8 +27,8 @@
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="@dimen/sp_12" android:textSize="@dimen/sp_12"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintRight_toRightOf="parent"/> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
android:id="@+id/tv_today_amount" android:id="@+id/tv_today_amount"
...@@ -106,19 +106,26 @@ ...@@ -106,19 +106,26 @@
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_compare_today_text" /> app:layout_constraintTop_toBottomOf="@id/tv_compare_today_text" />
<!-- com.daivd.chart.core.LineChart-->
<com.daivd.chart.core.LineChart <com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger.AAChartView
android:id="@+id/line_chart_view" android:id="@+id/line_chart_view"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="160dp" android:layout_height="0dp"
android:layout_marginLeft="@dimen/dp_10" android:layout_marginLeft="@dimen/dp_5"
android:layout_marginTop="@dimen/dp_10" android:layout_marginTop="@dimen/dp_10"
android:layout_marginRight="@dimen/dp_10" android:layout_marginRight="@dimen/dp_10"
android:paddingRight="@dimen/dp_10"
app:layout_constraintLeft_toLeftOf="@id/cv_white_bg" app:layout_constraintLeft_toLeftOf="@id/cv_white_bg"
app:layout_constraintRight_toRightOf="@id/cv_white_bg" app:layout_constraintRight_toRightOf="@id/cv_white_bg"
app:layout_constraintBottom_toTopOf="@id/tv_more_report"
app:layout_constraintTop_toBottomOf="@id/tv_today_time" /> app:layout_constraintTop_toBottomOf="@id/tv_today_time" />
<!-- <com.example.anan.AAChartCore.AAChartCoreLib.AAChartConfiger.AAChartView-->
<!-- android:id="@+id/AAChartView"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent" />-->
<TextView <TextView
android:id="@+id/tv_more_report" android:id="@+id/tv_more_report"
android:layout_width="wrap_content" android:layout_width="wrap_content"
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="@dimen/dp_18"
android:paddingTop="@dimen/dp_20">
<ImageView
android:id="@+id/iv_function_icon"
android:layout_width="@dimen/dp_29"
android:layout_height="@dimen/dp_27"
android:src="@drawable/ic_mall_center" />
<TextView
android:id="@+id/tv_function_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_14"
android:text="商城中心"
android:textColor="@color/white"
android:textSize="@dimen/sp_17" />
</LinearLayout>
\ No newline at end of file
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=3.0,user-scalable = no">
<title>AAChartKit-Swift</title>
<script src="AAHighchartsLib.js">
</script>
<script src="AAHighchartsMore.js">
</script>
<script src="AAFunnel.js">
</script>
<script src="AAEasing.js">
</script>
<script src="AAChartView.js" >
</script>
<style>
*{
-webkit-user-select: none;
user-select: none;
}
</style>
</head>
<body>
<div id="container" style="width:100%; height: 100%;"></div>
</div>
</body>
</html>
var aaGlobalChart;
function loadTheHighChartView (sender,receivedWidth, receivedHeight) {
var aaOptions = JSON.parse(sender);
if (aaOptions.xAxisArray) {
aaOptions.xAxis = aaOptions.xAxisArray
}
if (aaOptions.yAxisArray) {
aaOptions.yAxis = aaOptions.yAxisArray
}
aaOptions.credits = {enabled:false};
if (aaOptions.plotOptions) {
configurePlotOptions(aaOptions);
}
configureOptionsFormatters(aaOptions);
aaGlobalChart = Highcharts.chart('container', aaOptions);
//全局配置(可通过全局配置设置主题)https://api.hcharts.cn/highcharts#Highcharts.setOptions
};
function configurePlotOptions(aaOptions) {
var aaPlotOptions = aaOptions.plotOptions;
var animation = aaPlotOptions.series.animation;
if (animation) {//懒调用(只有在 AAChartModel 实例对象设置了 animationType 属性值的时候才会调用设置动画类型的函数,否则不调用)
var animationEasingType = animation.easing;
animation.easing = configureTheChartAnimationEasingType(animationEasingType);
}
// 添加鼠标事件
if (aaOptions.touchEventEnabled == true && aaPlotOptions.series) {
configureChartTouchEvent(aaPlotOptions);
}
}
function configureChartTouchEvent(aaPlotOptions) {
var mouseOverFunc = function(){
var message = {
name: this.series.name,
y :this.y,
x: this.x,
category: this.category,
offset: {plotX:this.plotX,plotY:this.plotY},
index: this.index,
};
var messageStr = JSON.stringify(message);
window.androidObject.androidMethod(messageStr);
};
var seriesPoint = {
events:{
mouseOver: mouseOverFunc,
}
};
aaPlotOptions.series.point = seriesPoint;
}
function configureOptionsFormatters(aaOptions) {
if (aaOptions.tooltip
&& aaOptions.tooltip.formatter) {
aaOptions.tooltip.formatter = eval(aaOptions.tooltip.formatter);
}
if (aaOptions.xAxis
&& aaOptions.xAxis.labels
&& aaOptions.xAxis.labels.formatter) {
aaOptions.xAxis.labels.formatter = eval(aaOptions.xAxis.labels.formatter);
}
if (aaOptions.yAxis
&& aaOptions.yAxis.labels
&& aaOptions.yAxis.labels.formatter) {
aaOptions.yAxis.labels.formatter = eval(aaOptions.yAxis.labels.formatter);
}
}
function onlyRefreshTheChartDataWithSeries(receivedSeries, animation) {
var receivedSeriesArr = JSON.parse(receivedSeries);
var seriesArrLength = receivedSeriesArr.length;
for (var i = 0; i < seriesArrLength; i++) {
var receivedSeriesElementData = receivedSeriesArr[i].data;
// 获取series
var seriesElement = aaGlobalChart.series[i];
// 执行只刷新数据的函数
seriesElement.setData(receivedSeriesElementData, false);
}
var animationBool = (animation == "true") ? true:false;
aaGlobalChart.redraw(animationBool);
}
function updateChart(optionsStr, redraw) {
var options = JSON.parse(optionsStr);
aaGlobalChart.update(options,redraw);
}
function addPointToChartSeries(elementIndex, optionsStr, redraw, shift, animation) {
var options = JSON.parse(optionsStr);
var redrawBool = (redraw == "true") ? true:false;
var shiftBool = (shift == "true") ? true:false;
var animationBool = (animation == "true") ? true:false;
var seriesElement = aaGlobalChart.series[elementIndex];
seriesElement.addPoint(options, redrawBool, shiftBool, animationBool);
}
//pragma mark -- setter method
function setTheChartViewContentWidth(receivedWidth) {
var container = document.getElementById('container'); //获得元素
container.style.width = receivedWidth; //设置宽度
aaGlobalChart.reflow();
}
function setTheChartViewContentHeight(receivedHeight) {
var container = document.getElementById('container'); //获得元素
container.style.height = receivedHeight; //设置高度
aaGlobalChart.reflow();
}
function setChartSeriesHidden(hidden) {
for (var i = 0; i < aaGlobalChart.series.length; i++) {
var seriesElement = aaGlobalChart.series[i];
if (hidden == true) {
seriesElement.hide();
} else {
seriesElement.show();
}
}
}
function showTheSeriesElementContentWithIndex(elementIndex) {
var seriesElement = aaGlobalChart.series[elementIndex];
seriesElement.show();
}
function hideTheSeriesElementContentWithIndex(elementIndex) {
var seriesElement = aaGlobalChart.series[elementIndex];
seriesElement.hide();
}
function addElementToChartSeriesWithElement(elementStr) {
var seriesElement = JSON.parse(elementStr);
aaGlobalChart.addSeries(seriesElement);
}
function removeElementFromChartSeriesWithElementIndex(elementIndex) {
var seriesElement = aaGlobalChart.series[elementIndex];
if (seriesElement) {
seriesElement.remove(true);
}
}
function evaluateTheJavaScriptStringFunction(jsStringFunction) {
eval(jsStringFunction);
}
\ No newline at end of file
function configureTheChartAnimationEasingType(easingType){var animationObject={easeInQuad:function(pos){return Math.pow(pos,2)},easeOutQuad:function(pos){return -(Math.pow((pos-1),2)-1)},easeInOutQuad:function(pos){if((pos/=0.5)<1){return 0.5*Math.pow(pos,2)}return -0.5*((pos-=2)*pos-2)},easeInCubic:function(pos){return Math.pow(pos,3)},easeOutCubic:function(pos){return(Math.pow((pos-1),3)+1)},easeInOutCubic:function(pos){if((pos/=0.5)<1){return 0.5*Math.pow(pos,3)}return 0.5*(Math.pow((pos-2),3)+2)},easeInQuart:function(pos){return Math.pow(pos,4)},easeOutQuart:function(pos){return -(Math.pow((pos-1),4)-1)},easeInOutQuart:function(pos){if((pos/=0.5)<1){return 0.5*Math.pow(pos,4)}return -0.5*((pos-=2)*Math.pow(pos,3)-2)},easeInQuint:function(pos){return Math.pow(pos,5)},easeOutQuint:function(pos){return(Math.pow((pos-1),5)+1)},easeInOutQuint:function(pos){if((pos/=0.5)<1){return 0.5*Math.pow(pos,5)}return 0.5*(Math.pow((pos-2),5)+2)},easeInSine:function(pos){return -Math.cos(pos*(Math.PI/2))+1},easeOutSine:function(pos){return Math.sin(pos*(Math.PI/2))},easeInOutSine:function(pos){return(-0.5*(Math.cos(Math.PI*pos)-1))},easeInExpo:function(pos){return(pos===0)?0:Math.pow(2,10*(pos-1))},easeOutExpo:function(pos){return(pos===1)?1:-Math.pow(2,-10*pos)+1},easeInOutExpo:function(pos){if(pos===0){return 0}if(pos===1){return 1}if((pos/=0.5)<1){return 0.5*Math.pow(2,10*(pos-1))}return 0.5*(-Math.pow(2,-10*--pos)+2)},easeInCirc:function(pos){return -(Math.sqrt(1-(pos*pos))-1)},easeOutCirc:function(pos){return Math.sqrt(1-Math.pow((pos-1),2))},easeInOutCirc:function(pos){if((pos/=0.5)<1){return -0.5*(Math.sqrt(1-pos*pos)-1)}return 0.5*(Math.sqrt(1-(pos-=2)*pos)+1)},easeOutBounce:function(pos){if((pos)<(1/2.75)){return(7.5625*pos*pos)}else{if(pos<(2/2.75)){return(7.5625*(pos-=(1.5/2.75))*pos+0.75)}else{if(pos<(2.5/2.75)){return(7.5625*(pos-=(2.25/2.75))*pos+0.9375)}else{return(7.5625*(pos-=(2.625/2.75))*pos+0.984375)}}}},easeInBack:function(pos){var s=1.70158;return(pos)*pos*((s+1)*pos-s)},easeOutBack:function(pos){var s=1.70158;return(pos=pos-1)*pos*((s+1)*pos+s)+1},easeInOutBack:function(pos){var s=1.70158;if((pos/=0.5)<1){return 0.5*(pos*pos*(((s*=(1.525))+1)*pos-s))}return 0.5*((pos-=2)*pos*(((s*=(1.525))+1)*pos+s)+2)},elastic:function(pos){return -1*Math.pow(4,-8*pos)*Math.sin((pos*6-1)*(2*Math.PI)/2)+1},swingFromTo:function(pos){var s=1.70158;return((pos/=0.5)<1)?0.5*(pos*pos*(((s*=(1.525))+1)*pos-s)):0.5*((pos-=2)*pos*(((s*=(1.525))+1)*pos+s)+2)},swingFrom:function(pos){var s=1.70158;return pos*pos*((s+1)*pos-s)},swingTo:function(pos){var s=1.70158;return(pos-=1)*pos*((s+1)*pos+s)+1},bounce:function(pos){if(pos<(1/2.75)){return(7.5625*pos*pos)}else{if(pos<(2/2.75)){return(7.5625*(pos-=(1.5/2.75))*pos+0.75)}else{if(pos<(2.5/2.75)){return(7.5625*(pos-=(2.25/2.75))*pos+0.9375)}else{return(7.5625*(pos-=(2.625/2.75))*pos+0.984375)}}}},bouncePast:function(pos){if(pos<(1/2.75)){return(7.5625*pos*pos)}else{if(pos<(2/2.75)){return 2-(7.5625*(pos-=(1.5/2.75))*pos+0.75)}else{if(pos<(2.5/2.75)){return 2-(7.5625*(pos-=(2.25/2.75))*pos+0.9375)}else{return 2-(7.5625*(pos-=(2.625/2.75))*pos+0.984375)}}}},easeFromTo:function(pos){if((pos/=0.5)<1){return 0.5*Math.pow(pos,4)}return -0.5*((pos-=2)*Math.pow(pos,3)-2)},easeFrom:function(pos){return Math.pow(pos,4)},easeTo:function(pos){return Math.pow(pos,0.25)}};return animationObject[easingType]};
\ No newline at end of file
/*
Highcharts JS v7.1.1 (2019-04-09)
Highcharts funnel module
(c) 2010-2019 Torstein Honsi
License: www.highcharts.com/license
*/
(function(b){"object"===typeof module&&module.exports?(b["default"]=b,module.exports=b):"function"===typeof define&&define.amd?define("highcharts/modules/funnel",["highcharts"],function(d){b(d);b.Highcharts=d;return b}):b("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(b){function d(b,d,x,C){b.hasOwnProperty(d)||(b[d]=C.apply(null,x))}b=b?b._modules:{};d(b,"modules/funnel.src.js",[b["parts/Globals.js"]],function(b){var d=b.seriesType,x=b.seriesTypes,C=b.noop,H=b.pick;d("funnel","pie",
{animation:!1,center:["50%","50%"],width:"90%",neckWidth:"30%",height:"100%",neckHeight:"25%",reversed:!1,size:!0,dataLabels:{connectorWidth:1},states:{select:{color:"#cccccc",borderColor:"#000000"}}},{animate:C,translate:function(){var a=function(b,a){return/%$/.test(b)?a*parseInt(b,10)/100:parseInt(b,10)},b=0,f=this.chart,e=this.options,h=e.reversed,l=e.ignoreHiddenPoint,c=f.plotWidth,f=f.plotHeight,d=0,q=e.center,g=a(q[0],c),k=a(q[1],f),x=a(e.width,c),r,y,t=a(e.height,f),z=a(e.neckWidth,c),G=a(e.neckHeight,
f),A=k-t/2+t-G,a=this.data,D,E,I="left"===e.dataLabels.position?1:0,B,m,F,u,n,w,p;this.getWidthAt=y=function(b){var a=k-t/2;return b>A||t===G?z:z+(x-z)*(1-(b-a)/(t-G))};this.getX=function(b,a,c){return g+(a?-1:1)*(y(h?2*k-b:b)/2+c.labelDistance)};this.center=[g,k,t];this.centerX=g;a.forEach(function(a){l&&!1===a.visible||(b+=a.y)});a.forEach(function(a){p=null;E=b?a.y/b:0;m=k-t/2+d*t;n=m+E*t;r=y(m);B=g-r/2;F=B+r;r=y(n);u=g-r/2;w=u+r;m>A?(B=u=g-z/2,F=w=g+z/2):n>A&&(p=n,r=y(A),u=g-r/2,w=u+r,n=A);h&&
(m=2*k-m,n=2*k-n,null!==p&&(p=2*k-p));D=["M",B,m,"L",F,m,w,n];null!==p&&D.push(w,p,u,p);D.push(u,n,"Z");a.shapeType="path";a.shapeArgs={d:D};a.percentage=100*E;a.plotX=g;a.plotY=(m+(p||n))/2;a.tooltipPos=[g,a.plotY];a.dlBox={x:u,y:m,topWidth:F-B,bottomWidth:w-u,height:Math.abs(H(n,p)-m)};a.slice=C;a.half=I;l&&!1===a.visible||(d+=E)})},sortByAngle:function(a){a.sort(function(a,b){return a.plotY-b.plotY})},drawDataLabels:function(){var a=this.data,b=this.options.dataLabels.distance,f,e,h,d=a.length,
c,v;for(this.center[2]-=2*b;d--;)h=a[d],e=(f=h.half)?1:-1,v=h.plotY,h.labelDistance=H(h.options.dataLabels&&h.options.dataLabels.distance,b),this.maxLabelDistance=Math.max(h.labelDistance,this.maxLabelDistance||0),c=this.getX(v,f,h),h.labelPosition={natural:{x:0,y:v},"final":{},alignment:f?"right":"left",connectorPosition:{breakAt:{x:c+(h.labelDistance-5)*e,y:v},touchingSliceAt:{x:c+h.labelDistance*e,y:v}}};x[this.options.dataLabels.inside?"column":"pie"].prototype.drawDataLabels.call(this)},alignDataLabel:function(a,
d,f,e,h){var l=a.series;e=l.options.reversed;var c=a.dlBox||a.shapeArgs,v=f.align,q=f.verticalAlign,g=l.center[1],l=l.getWidthAt((e?2*g-a.plotY:a.plotY)-c.height/2+d.height),l="middle"===q?(c.topWidth-c.bottomWidth)/4:(l-c.bottomWidth)/2,g=c.y,k=c.x;"middle"===q?g=c.y-c.height/2+d.height/2:"top"===q&&(g=c.y-c.height+d.height+f.padding);if("top"===q&&!e||"bottom"===q&&e||"middle"===q)"right"===v?k=c.x-f.padding+l:"left"===v&&(k=c.x+f.padding-l);e={x:k,y:e?g-c.height:g,width:c.bottomWidth,height:c.height};
f.verticalAlign="bottom";b.Series.prototype.alignDataLabel.call(this,a,d,f,e,h);a.isLabelJustified&&a.contrastColor&&d.css({color:a.contrastColor})}});d("pyramid","funnel",{neckWidth:"0%",neckHeight:"0%",reversed:!0})});d(b,"masters/modules/funnel.src.js",[],function(){})});
//# sourceMappingURL=funnel.js.map
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
Highcharts JS v7.1.1 (2019-04-09)
(c) 2009-2018 Torstein Honsi
License: www.highcharts.com/license
*/
(function(r){"object"===typeof module&&module.exports?(r["default"]=r,module.exports=r):"function"===typeof define&&define.amd?define("highcharts/highcharts-more",["highcharts"],function(y){r(y);r.Highcharts=y;return r}):r("undefined"!==typeof Highcharts?Highcharts:void 0)})(function(r){function y(a,p,l,e){a.hasOwnProperty(p)||(a[p]=e.apply(null,l))}r=r?r._modules:{};y(r,"parts-more/Pane.js",[r["parts/Globals.js"]],function(a){function p(b,f){this.init(b,f)}var l=a.CenteredSeriesMixin,e=a.extend,
h=a.merge,b=a.splat;e(p.prototype,{coll:"pane",init:function(b,f){this.chart=f;this.background=[];f.pane.push(this);this.setOptions(b)},setOptions:function(b){this.options=h(this.defaultOptions,this.chart.angular?{background:{}}:void 0,b)},render:function(){var a=this.options,f=this.options.background,c=this.chart.renderer;this.group||(this.group=c.g("pane-group").attr({zIndex:a.zIndex||0}).add());this.updateCenter();if(f)for(f=b(f),a=Math.max(f.length,this.background.length||0),c=0;c<a;c++)f[c]&&
this.axis?this.renderBackground(h(this.defaultBackgroundOptions,f[c]),c):this.background[c]&&(this.background[c]=this.background[c].destroy(),this.background.splice(c,1))},renderBackground:function(b,f){var c="animate",a={"class":"highcharts-pane "+(b.className||"")};this.chart.styledMode||e(a,{fill:b.backgroundColor,stroke:b.borderColor,"stroke-width":b.borderWidth});this.background[f]||(this.background[f]=this.chart.renderer.path().add(this.group),c="attr");this.background[f][c]({d:this.axis.getPlotBandPath(b.from,
b.to,b)}).attr(a)},defaultOptions:{center:["50%","50%"],size:"85%",startAngle:0},defaultBackgroundOptions:{shape:"circle",borderWidth:1,borderColor:"#cccccc",backgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[0,"#ffffff"],[1,"#e6e6e6"]]},from:-Number.MAX_VALUE,innerRadius:0,to:Number.MAX_VALUE,outerRadius:"105%"},updateCenter:function(b){this.center=(b||this.axis||{}).center=l.getCenter.call(this)},update:function(b,f){h(!0,this.options,b);h(!0,this.chart.options.pane,b);this.setOptions(this.options);
this.render();this.chart.axes.forEach(function(b){b.pane===this&&(b.pane=null,b.update({},f))},this)}});a.Pane=p});y(r,"parts-more/RadialAxis.js",[r["parts/Globals.js"]],function(a){var p=a.addEvent,l=a.Axis,e=a.extend,h=a.merge,b=a.noop,g=a.pick,f=a.pInt,c=a.Tick,t=a.wrap,w=a.correctFloat,x,d,q=l.prototype,n=c.prototype;x={getOffset:b,redraw:function(){this.isDirty=!1},render:function(){this.isDirty=!1},setScale:b,setCategories:b,setTitle:b};d={defaultRadialGaugeOptions:{labels:{align:"center",x:0,
y:null},minorGridLineWidth:0,minorTickInterval:"auto",minorTickLength:10,minorTickPosition:"inside",minorTickWidth:1,tickLength:10,tickPosition:"inside",tickWidth:2,title:{rotation:0},zIndex:2},defaultRadialXOptions:{gridLineWidth:1,labels:{align:null,distance:15,x:0,y:null,style:{textOverflow:"none"}},maxPadding:0,minPadding:0,showLastLabel:!1,tickLength:0},defaultRadialYOptions:{gridLineInterpolation:"circle",labels:{align:"right",x:-3,y:-2},showLastLabel:!1,title:{x:4,text:null,rotation:90}},setOptions:function(d){d=
this.options=h(this.defaultOptions,this.defaultRadialOptions,d);d.plotBands||(d.plotBands=[]);a.fireEvent(this,"afterSetOptions")},getOffset:function(){q.getOffset.call(this);this.chart.axisOffset[this.side]=0},getLinePath:function(d,b){d=this.center;var k=this.chart,m=g(b,d[2]/2-this.offset);this.isCircular||void 0!==b?(b=this.chart.renderer.symbols.arc(this.left+d[0],this.top+d[1],m,m,{start:this.startAngleRad,end:this.endAngleRad,open:!0,innerR:0}),b.xBounds=[this.left+d[0]],b.yBounds=[this.top+
d[1]-m]):(b=this.postTranslate(this.angleRad,m),b=["M",d[0]+k.plotLeft,d[1]+k.plotTop,"L",b.x,b.y]);return b},setAxisTranslation:function(){q.setAxisTranslation.call(this);this.center&&(this.transA=this.isCircular?(this.endAngleRad-this.startAngleRad)/(this.max-this.min||1):this.center[2]/2/(this.max-this.min||1),this.minPixelPadding=this.isXAxis?this.transA*this.minPointOffset:0)},beforeSetTickPositions:function(){if(this.autoConnect=this.isCircular&&void 0===g(this.userMax,this.options.max)&&w(this.endAngleRad-
this.startAngleRad)===w(2*Math.PI))this.max+=this.categories&&1||this.pointRange||this.closestPointRange||0},setAxisSize:function(){q.setAxisSize.call(this);this.isRadial&&(this.pane.updateCenter(this),this.isCircular&&(this.sector=this.endAngleRad-this.startAngleRad),this.len=this.width=this.height=this.center[2]*g(this.sector,1)/2)},getPosition:function(d,b){return this.postTranslate(this.isCircular?this.translate(d):this.angleRad,g(this.isCircular?b:this.translate(d),this.center[2]/2)-this.offset)},
postTranslate:function(d,b){var k=this.chart,m=this.center;d=this.startAngleRad+d;return{x:k.plotLeft+m[0]+Math.cos(d)*b,y:k.plotTop+m[1]+Math.sin(d)*b}},getPlotBandPath:function(d,b,k){var m=this.center,q=this.startAngleRad,n=m[2]/2,u=[g(k.outerRadius,"100%"),k.innerRadius,g(k.thickness,10)],v=Math.min(this.offset,0),c=/%$/,a,w;a=this.isCircular;"polygon"===this.options.gridLineInterpolation?u=this.getPlotLinePath(d).concat(this.getPlotLinePath(b,!0)):(d=Math.max(d,this.min),b=Math.min(b,this.max),
a||(u[0]=this.translate(d),u[1]=this.translate(b)),u=u.map(function(d){c.test(d)&&(d=f(d,10)*n/100);return d}),"circle"!==k.shape&&a?(d=q+this.translate(d),b=q+this.translate(b)):(d=-Math.PI/2,b=1.5*Math.PI,w=!0),u[0]-=v,u[2]-=v,u=this.chart.renderer.symbols.arc(this.left+m[0],this.top+m[1],u[0],u[0],{start:Math.min(d,b),end:Math.max(d,b),innerR:g(u[1],u[0]-u[2]),open:w}),a&&(a=(b+d)/2,v=this.left+m[0]+m[2]/2*Math.cos(a),u.xBounds=a>-Math.PI/2&&a<Math.PI/2?[v,this.chart.plotWidth]:[0,v],u.yBounds=
[this.top+m[1]+m[2]/2*Math.sin(a)],u.yBounds[0]+=a>-Math.PI&&0>a||a>Math.PI?-10:10));return u},getPlotLinePath:function(d,b){var k=this,m=k.center,q=k.chart,n=k.getPosition(d),u,v,a;k.isCircular?a=["M",m[0]+q.plotLeft,m[1]+q.plotTop,"L",n.x,n.y]:"circle"===k.options.gridLineInterpolation?(d=k.translate(d),a=k.getLinePath(0,d)):(q.xAxis.forEach(function(d){d.pane===k.pane&&(u=d)}),a=[],d=k.translate(d),m=u.tickPositions,u.autoConnect&&(m=m.concat([m[0]])),b&&(m=[].concat(m).reverse()),m.forEach(function(k,
m){v=u.getPosition(k,d);a.push(m?"L":"M",v.x,v.y)}));return a},getTitlePosition:function(){var d=this.center,b=this.chart,k=this.options.title;return{x:b.plotLeft+d[0]+(k.x||0),y:b.plotTop+d[1]-{high:.5,middle:.25,low:0}[k.align]*d[2]+(k.y||0)}}};p(l,"init",function(b){var q=this,k=this.chart,m=k.angular,n=k.polar,u=this.isXAxis,a=m&&u,c,f=k.options;b=b.userOptions.pane||0;b=this.pane=k.pane&&k.pane[b];if(m){if(e(this,a?x:d),c=!u)this.defaultRadialOptions=this.defaultRadialGaugeOptions}else n&&(e(this,
d),this.defaultRadialOptions=(c=u)?this.defaultRadialXOptions:h(this.defaultYAxisOptions,this.defaultRadialYOptions));m||n?(this.isRadial=!0,k.inverted=!1,f.chart.zoomType=null,k.labelCollectors.push(function(){if(q.isRadial&&q.tickPositions&&!0!==q.options.labels.allowOverlap)return q.tickPositions.map(function(d){return q.ticks[d]&&q.ticks[d].label}).filter(function(d){return!!d})})):this.isRadial=!1;b&&c&&(b.axis=this);this.isCircular=c});p(l,"afterInit",function(){var d=this.chart,b=this.options,
k=this.pane,m=k&&k.options;d.angular&&this.isXAxis||!k||!d.angular&&!d.polar||(this.angleRad=(b.angle||0)*Math.PI/180,this.startAngleRad=(m.startAngle-90)*Math.PI/180,this.endAngleRad=(g(m.endAngle,m.startAngle+360)-90)*Math.PI/180,this.offset=b.offset||0)});p(l,"autoLabelAlign",function(d){this.isRadial&&(d.align=void 0,d.preventDefault())});p(c,"afterGetPosition",function(d){this.axis.getPosition&&e(d.pos,this.axis.getPosition(this.pos))});p(c,"afterGetLabelPosition",function(d){var b=this.axis,
k=this.label,m=b.options.labels,q=m.y,n,u=20,a=m.align,c=(b.translate(this.pos)+b.startAngleRad+Math.PI/2)/Math.PI*180%360;b.isRadial&&(n=b.getPosition(this.pos,b.center[2]/2+g(m.distance,-25)),"auto"===m.rotation?k.attr({rotation:c}):null===q&&(q=b.chart.renderer.fontMetrics(k.styles&&k.styles.fontSize).b-k.getBBox().height/2),null===a&&(b.isCircular?(this.label.getBBox().width>b.len*b.tickInterval/(b.max-b.min)&&(u=0),a=c>u&&c<180-u?"left":c>180+u&&c<360-u?"right":"center"):a="center",k.attr({align:a})),
d.pos.x=n.x+m.x,d.pos.y=n.y+q)});t(n,"getMarkPath",function(d,b,k,m,q,n,a){var u=this.axis;u.isRadial?(d=u.getPosition(this.pos,u.center[2]/2+m),b=["M",b,k,"L",d.x,d.y]):b=d.call(this,b,k,m,q,n,a);return b})});y(r,"parts-more/AreaRangeSeries.js",[r["parts/Globals.js"]],function(a){var p=a.pick,l=a.extend,e=a.isArray,h=a.defined,b=a.seriesType,g=a.seriesTypes,f=a.Series.prototype,c=a.Point.prototype;b("arearange","area",{lineWidth:1,threshold:null,tooltip:{pointFormat:'\x3cspan style\x3d"color:{series.color}"\x3e\u25cf\x3c/span\x3e {series.name}: \x3cb\x3e{point.low}\x3c/b\x3e - \x3cb\x3e{point.high}\x3c/b\x3e\x3cbr/\x3e'},
trackByArea:!0,dataLabels:{align:null,verticalAlign:null,xLow:0,xHigh:0,yLow:0,yHigh:0}},{pointArrayMap:["low","high"],toYData:function(b){return[b.low,b.high]},pointValKey:"low",deferTranslatePolar:!0,highToXY:function(b){var a=this.chart,c=this.xAxis.postTranslate(b.rectPlotX,this.yAxis.len-b.plotHigh);b.plotHighX=c.x-a.plotLeft;b.plotHigh=c.y-a.plotTop;b.plotLowX=b.plotX},translate:function(){var b=this,a=b.yAxis,c=!!b.modifyValue;g.area.prototype.translate.apply(b);b.points.forEach(function(d){var q=
d.low,n=d.high,u=d.plotY;null===n||null===q?(d.isNull=!0,d.plotY=null):(d.plotLow=u,d.plotHigh=a.translate(c?b.modifyValue(n,d):n,0,1,0,1),c&&(d.yBottom=d.plotHigh))});this.chart.polar&&this.points.forEach(function(d){b.highToXY(d);d.tooltipPos=[(d.plotHighX+d.plotLowX)/2,(d.plotHigh+d.plotLow)/2]})},getGraphPath:function(b){var a=[],c=[],d,q=g.area.prototype.getGraphPath,n,u,v;v=this.options;var k=this.chart.polar&&!1!==v.connectEnds,m=v.connectNulls,f=v.step;b=b||this.points;for(d=b.length;d--;)n=
b[d],n.isNull||k||m||b[d+1]&&!b[d+1].isNull||c.push({plotX:n.plotX,plotY:n.plotY,doCurve:!1}),u={polarPlotY:n.polarPlotY,rectPlotX:n.rectPlotX,yBottom:n.yBottom,plotX:p(n.plotHighX,n.plotX),plotY:n.plotHigh,isNull:n.isNull},c.push(u),a.push(u),n.isNull||k||m||b[d-1]&&!b[d-1].isNull||c.push({plotX:n.plotX,plotY:n.plotY,doCurve:!1});b=q.call(this,b);f&&(!0===f&&(f="left"),v.step={left:"right",center:"center",right:"left"}[f]);a=q.call(this,a);c=q.call(this,c);v.step=f;v=[].concat(b,a);this.chart.polar||
"M"!==c[0]||(c[0]="L");this.graphPath=v;this.areaPath=b.concat(c);v.isArea=!0;v.xMap=b.xMap;this.areaPath.xMap=b.xMap;return v},drawDataLabels:function(){var b=this.points,a=b.length,c,d=[],q=this.options.dataLabels,n,u,v=this.chart.inverted,k,m;e(q)?1<q.length?(k=q[0],m=q[1]):(k=q[0],m={enabled:!1}):(k=l({},q),k.x=q.xHigh,k.y=q.yHigh,m=l({},q),m.x=q.xLow,m.y=q.yLow);if(k.enabled||this._hasPointLabels){for(c=a;c--;)if(n=b[c])u=k.inside?n.plotHigh<n.plotLow:n.plotHigh>n.plotLow,n.y=n.high,n._plotY=
n.plotY,n.plotY=n.plotHigh,d[c]=n.dataLabel,n.dataLabel=n.dataLabelUpper,n.below=u,v?k.align||(k.align=u?"right":"left"):k.verticalAlign||(k.verticalAlign=u?"top":"bottom");this.options.dataLabels=k;f.drawDataLabels&&f.drawDataLabels.apply(this,arguments);for(c=a;c--;)if(n=b[c])n.dataLabelUpper=n.dataLabel,n.dataLabel=d[c],delete n.dataLabels,n.y=n.low,n.plotY=n._plotY}if(m.enabled||this._hasPointLabels){for(c=a;c--;)if(n=b[c])u=m.inside?n.plotHigh<n.plotLow:n.plotHigh>n.plotLow,n.below=!u,v?m.align||
(m.align=u?"left":"right"):m.verticalAlign||(m.verticalAlign=u?"bottom":"top");this.options.dataLabels=m;f.drawDataLabels&&f.drawDataLabels.apply(this,arguments)}if(k.enabled)for(c=a;c--;)if(n=b[c])n.dataLabels=[n.dataLabelUpper,n.dataLabel].filter(function(d){return!!d});this.options.dataLabels=q},alignDataLabel:function(){g.column.prototype.alignDataLabel.apply(this,arguments)},drawPoints:function(){var b=this.points.length,c,e;f.drawPoints.apply(this,arguments);for(e=0;e<b;)c=this.points[e],c.origProps=
{plotY:c.plotY,plotX:c.plotX,isInside:c.isInside,negative:c.negative,zone:c.zone,y:c.y},c.lowerGraphic=c.graphic,c.graphic=c.upperGraphic,c.plotY=c.plotHigh,h(c.plotHighX)&&(c.plotX=c.plotHighX),c.y=c.high,c.negative=c.high<(this.options.threshold||0),c.zone=this.zones.length&&c.getZone(),this.chart.polar||(c.isInside=c.isTopInside=void 0!==c.plotY&&0<=c.plotY&&c.plotY<=this.yAxis.len&&0<=c.plotX&&c.plotX<=this.xAxis.len),e++;f.drawPoints.apply(this,arguments);for(e=0;e<b;)c=this.points[e],c.upperGraphic=
c.graphic,c.graphic=c.lowerGraphic,a.extend(c,c.origProps),delete c.origProps,e++},setStackedPoints:a.noop},{setState:function(){var b=this.state,a=this.series,f=a.chart.polar;h(this.plotHigh)||(this.plotHigh=a.yAxis.toPixels(this.high,!0));h(this.plotLow)||(this.plotLow=this.plotY=a.yAxis.toPixels(this.low,!0));a.stateMarkerGraphic&&(a.lowerStateMarkerGraphic=a.stateMarkerGraphic,a.stateMarkerGraphic=a.upperStateMarkerGraphic);this.graphic=this.upperGraphic;this.plotY=this.plotHigh;f&&(this.plotX=
this.plotHighX);c.setState.apply(this,arguments);this.state=b;this.plotY=this.plotLow;this.graphic=this.lowerGraphic;f&&(this.plotX=this.plotLowX);a.stateMarkerGraphic&&(a.upperStateMarkerGraphic=a.stateMarkerGraphic,a.stateMarkerGraphic=a.lowerStateMarkerGraphic,a.lowerStateMarkerGraphic=void 0);c.setState.apply(this,arguments)},haloPath:function(){var b=this.series.chart.polar,a=[];this.plotY=this.plotLow;b&&(this.plotX=this.plotLowX);this.isInside&&(a=c.haloPath.apply(this,arguments));this.plotY=
this.plotHigh;b&&(this.plotX=this.plotHighX);this.isTopInside&&(a=a.concat(c.haloPath.apply(this,arguments)));return a},destroyElements:function(){["lowerGraphic","upperGraphic"].forEach(function(b){this[b]&&(this[b]=this[b].destroy())},this);this.graphic=null;return c.destroyElements.apply(this,arguments)}})});y(r,"parts-more/AreaSplineRangeSeries.js",[r["parts/Globals.js"]],function(a){var p=a.seriesType;p("areasplinerange","arearange",null,{getPointSpline:a.seriesTypes.spline.prototype.getPointSpline})});
y(r,"parts-more/ColumnRangeSeries.js",[r["parts/Globals.js"]],function(a){var p=a.defaultPlotOptions,l=a.merge,e=a.noop,h=a.pick,b=a.seriesType,g=a.seriesTypes.column.prototype;b("columnrange","arearange",l(p.column,p.arearange,{pointRange:null,marker:null,states:{hover:{halo:!1}}}),{translate:function(){var b=this,c=b.yAxis,a=b.xAxis,e=a.startAngleRad,p,d=b.chart,q=b.xAxis.isRadial,n=Math.max(d.chartWidth,d.chartHeight)+999,u;g.translate.apply(b);b.points.forEach(function(v){var k=v.shapeArgs,m=
b.options.minPointLength,f,g;v.plotHigh=u=Math.min(Math.max(-n,c.translate(v.high,0,1,0,1)),n);v.plotLow=Math.min(Math.max(-n,v.plotY),n);g=u;f=h(v.rectPlotY,v.plotY)-u;Math.abs(f)<m?(m-=f,f+=m,g-=m/2):0>f&&(f*=-1,g-=f);q?(p=v.barX+e,v.shapeType="path",v.shapeArgs={d:b.polarArc(g+f,g,p,p+v.pointWidth)}):(k.height=f,k.y=g,v.tooltipPos=d.inverted?[c.len+c.pos-d.plotLeft-g-f/2,a.len+a.pos-d.plotTop-k.x-k.width/2,f]:[a.left-d.plotLeft+k.x+k.width/2,c.pos-d.plotTop+g+f/2,f])})},directTouch:!0,trackerGroups:["group",
"dataLabelsGroup"],drawGraph:e,getSymbol:e,crispCol:function(){return g.crispCol.apply(this,arguments)},drawPoints:function(){return g.drawPoints.apply(this,arguments)},drawTracker:function(){return g.drawTracker.apply(this,arguments)},getColumnMetrics:function(){return g.getColumnMetrics.apply(this,arguments)},pointAttribs:function(){return g.pointAttribs.apply(this,arguments)},animate:function(){return g.animate.apply(this,arguments)},polarArc:function(){return g.polarArc.apply(this,arguments)},
translate3dPoints:function(){return g.translate3dPoints.apply(this,arguments)},translate3dShapes:function(){return g.translate3dShapes.apply(this,arguments)}},{setState:g.pointClass.prototype.setState})});y(r,"parts-more/ColumnPyramidSeries.js",[r["parts/Globals.js"]],function(a){var p=a.pick,l=a.seriesType,e=a.seriesTypes.column.prototype;l("columnpyramid","column",{},{translate:function(){var a=this,b=a.chart,g=a.options,f=a.dense=2>a.closestPointRange*a.xAxis.transA,f=a.borderWidth=p(g.borderWidth,
f?0:1),c=a.yAxis,l=g.threshold,w=a.translatedThreshold=c.getThreshold(l),x=p(g.minPointLength,5),d=a.getColumnMetrics(),q=d.width,n=a.barW=Math.max(q,1+2*f),u=a.pointXOffset=d.offset;b.inverted&&(w-=.5);g.pointPadding&&(n=Math.ceil(n));e.translate.apply(a);a.points.forEach(function(d){var k=p(d.yBottom,w),m=999+Math.abs(k),f=Math.min(Math.max(-m,d.plotY),c.len+m),m=d.plotX+u,e=n/2,v=Math.min(f,k),k=Math.max(f,k)-v,h,B,t,z,r,C;d.barX=m;d.pointWidth=q;d.tooltipPos=b.inverted?[c.len+c.pos-b.plotLeft-
f,a.xAxis.len-m-e,k]:[m+e,f+c.pos-b.plotTop,k];f=l+(d.total||d.y);"percent"===g.stacking&&(f=l+(0>d.y)?-100:100);f=c.toPixels(f,!0);h=b.plotHeight-f-(b.plotHeight-w);B=e*(v-f)/h;t=e*(v+k-f)/h;h=m-B+e;B=m+B+e;z=m+t+e;t=m-t+e;r=v-x;C=v+k;0>d.y&&(r=v,C=v+k+x);b.inverted&&(z=b.plotWidth-v,h=f-(b.plotWidth-w),B=e*(f-z)/h,t=e*(f-(z-k))/h,h=m+e+B,B=h-2*B,z=m-t+e,t=m+t+e,r=v,C=v+k-x,0>d.y&&(C=v+k+x));d.shapeType="path";d.shapeArgs={x:h,y:r,width:B-h,height:k,d:["M",h,r,"L",B,r,z,C,t,C,"Z"]}})}})});y(r,"parts-more/GaugeSeries.js",
[r["parts/Globals.js"]],function(a){var p=a.isNumber,l=a.merge,e=a.pick,h=a.pInt,b=a.Series,g=a.seriesType,f=a.TrackerMixin;g("gauge","line",{dataLabels:{borderColor:"#cccccc",borderRadius:3,borderWidth:1,crop:!1,defer:!1,enabled:!0,verticalAlign:"top",y:15,zIndex:2},dial:{},pivot:{},tooltip:{headerFormat:""},showInLegend:!1},{angular:!0,directTouch:!0,drawGraph:a.noop,fixedBox:!0,forceDL:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],translate:function(){var b=this.yAxis,a=this.options,
f=b.center;this.generatePoints();this.points.forEach(function(c){var d=l(a.dial,c.dial),q=h(e(d.radius,80))*f[2]/200,n=h(e(d.baseLength,70))*q/100,u=h(e(d.rearLength,10))*q/100,v=d.baseWidth||3,k=d.topWidth||1,m=a.overshoot,g=b.startAngleRad+b.translate(c.y,null,null,null,!0);p(m)?(m=m/180*Math.PI,g=Math.max(b.startAngleRad-m,Math.min(b.endAngleRad+m,g))):!1===a.wrap&&(g=Math.max(b.startAngleRad,Math.min(b.endAngleRad,g)));g=180*g/Math.PI;c.shapeType="path";c.shapeArgs={d:d.path||["M",-u,-v/2,"L",
n,-v/2,q,-k/2,q,k/2,n,v/2,-u,v/2,"z"],translateX:f[0],translateY:f[1],rotation:g};c.plotX=f[0];c.plotY=f[1]})},drawPoints:function(){var b=this,a=b.chart,f=b.yAxis.center,g=b.pivot,d=b.options,q=d.pivot,n=a.renderer;b.points.forEach(function(q){var c=q.graphic,k=q.shapeArgs,m=k.d,f=l(d.dial,q.dial);c?(c.animate(k),k.d=m):(q.graphic=n[q.shapeType](k).attr({rotation:k.rotation,zIndex:1}).addClass("highcharts-dial").add(b.group),a.styledMode||q.graphic.attr({stroke:f.borderColor||"none","stroke-width":f.borderWidth||
0,fill:f.backgroundColor||"#000000"}))});g?g.animate({translateX:f[0],translateY:f[1]}):(b.pivot=n.circle(0,0,e(q.radius,5)).attr({zIndex:2}).addClass("highcharts-pivot").translate(f[0],f[1]).add(b.group),a.styledMode||b.pivot.attr({"stroke-width":q.borderWidth||0,stroke:q.borderColor||"#cccccc",fill:q.backgroundColor||"#000000"}))},animate:function(b){var a=this;b||(a.points.forEach(function(b){var c=b.graphic;c&&(c.attr({rotation:180*a.yAxis.startAngleRad/Math.PI}),c.animate({rotation:b.shapeArgs.rotation},
a.options.animation))}),a.animate=null)},render:function(){this.group=this.plotGroup("group","series",this.visible?"visible":"hidden",this.options.zIndex,this.chart.seriesGroup);b.prototype.render.call(this);this.group.clip(this.chart.clipRect)},setData:function(a,f){b.prototype.setData.call(this,a,!1);this.processData();this.generatePoints();e(f,!0)&&this.chart.redraw()},hasData:function(){return!!this.points.length},drawTracker:f&&f.drawTrackerPoint},{setState:function(b){this.state=b}})});y(r,
"parts-more/BoxPlotSeries.js",[r["parts/Globals.js"]],function(a){var p=a.noop,l=a.pick,e=a.seriesType,h=a.seriesTypes;e("boxplot","column",{threshold:null,tooltip:{pointFormat:'\x3cspan style\x3d"color:{point.color}"\x3e\u25cf\x3c/span\x3e \x3cb\x3e {series.name}\x3c/b\x3e\x3cbr/\x3eMaximum: {point.high}\x3cbr/\x3eUpper quartile: {point.q3}\x3cbr/\x3eMedian: {point.median}\x3cbr/\x3eLower quartile: {point.q1}\x3cbr/\x3eMinimum: {point.low}\x3cbr/\x3e'},whiskerLength:"50%",fillColor:"#ffffff",lineWidth:1,
medianWidth:2,whiskerWidth:2},{pointArrayMap:["low","q1","median","q3","high"],toYData:function(b){return[b.low,b.q1,b.median,b.q3,b.high]},pointValKey:"high",pointAttribs:function(){return{}},drawDataLabels:p,translate:function(){var b=this.yAxis,a=this.pointArrayMap;h.column.prototype.translate.apply(this);this.points.forEach(function(f){a.forEach(function(a){null!==f[a]&&(f[a+"Plot"]=b.translate(f[a],0,1,0,1))})})},drawPoints:function(){var b=this,a=b.options,f=b.chart,c=f.renderer,e,h,p,d,q,n,
u=0,v,k,m,I,E=!1!==b.doQuartiles,F,D=b.options.whiskerLength;b.points.forEach(function(g){var t=g.graphic,B=t?"animate":"attr",w=g.shapeArgs,x={},r={},A={},y={},G=g.color||b.color;void 0!==g.plotY&&(v=w.width,k=Math.floor(w.x),m=k+v,I=Math.round(v/2),e=Math.floor(E?g.q1Plot:g.lowPlot),h=Math.floor(E?g.q3Plot:g.lowPlot),p=Math.floor(g.highPlot),d=Math.floor(g.lowPlot),t||(g.graphic=t=c.g("point").add(b.group),g.stem=c.path().addClass("highcharts-boxplot-stem").add(t),D&&(g.whiskers=c.path().addClass("highcharts-boxplot-whisker").add(t)),
E&&(g.box=c.path(void 0).addClass("highcharts-boxplot-box").add(t)),g.medianShape=c.path(void 0).addClass("highcharts-boxplot-median").add(t)),f.styledMode||(r.stroke=g.stemColor||a.stemColor||G,r["stroke-width"]=l(g.stemWidth,a.stemWidth,a.lineWidth),r.dashstyle=g.stemDashStyle||a.stemDashStyle,g.stem.attr(r),D&&(A.stroke=g.whiskerColor||a.whiskerColor||G,A["stroke-width"]=l(g.whiskerWidth,a.whiskerWidth,a.lineWidth),g.whiskers.attr(A)),E&&(x.fill=g.fillColor||a.fillColor||G,x.stroke=a.lineColor||
G,x["stroke-width"]=a.lineWidth||0,g.box.attr(x)),y.stroke=g.medianColor||a.medianColor||G,y["stroke-width"]=l(g.medianWidth,a.medianWidth,a.lineWidth),g.medianShape.attr(y)),n=g.stem.strokeWidth()%2/2,u=k+I+n,g.stem[B]({d:["M",u,h,"L",u,p,"M",u,e,"L",u,d]}),E&&(n=g.box.strokeWidth()%2/2,e=Math.floor(e)+n,h=Math.floor(h)+n,k+=n,m+=n,g.box[B]({d:["M",k,h,"L",k,e,"L",m,e,"L",m,h,"L",k,h,"z"]})),D&&(n=g.whiskers.strokeWidth()%2/2,p+=n,d+=n,F=/%$/.test(D)?I*parseFloat(D)/100:D/2,g.whiskers[B]({d:["M",
u-F,p,"L",u+F,p,"M",u-F,d,"L",u+F,d]})),q=Math.round(g.medianPlot),n=g.medianShape.strokeWidth()%2/2,q+=n,g.medianShape[B]({d:["M",k,q,"L",m,q]}))})},setStackedPoints:p})});y(r,"parts-more/ErrorBarSeries.js",[r["parts/Globals.js"]],function(a){var p=a.noop,l=a.seriesType,e=a.seriesTypes;l("errorbar","boxplot",{color:"#000000",grouping:!1,linkedTo:":previous",tooltip:{pointFormat:'\x3cspan style\x3d"color:{point.color}"\x3e\u25cf\x3c/span\x3e {series.name}: \x3cb\x3e{point.low}\x3c/b\x3e - \x3cb\x3e{point.high}\x3c/b\x3e\x3cbr/\x3e'},
whiskerWidth:null},{type:"errorbar",pointArrayMap:["low","high"],toYData:function(a){return[a.low,a.high]},pointValKey:"high",doQuartiles:!1,drawDataLabels:e.arearange?function(){var a=this.pointValKey;e.arearange.prototype.drawDataLabels.call(this);this.data.forEach(function(b){b.y=b[a]})}:p,getColumnMetrics:function(){return this.linkedParent&&this.linkedParent.columnMetrics||e.column.prototype.getColumnMetrics.call(this)}})});y(r,"parts-more/WaterfallSeries.js",[r["parts/Globals.js"]],function(a){var p=
a.correctFloat,l=a.isNumber,e=a.pick,h=a.objectEach,b=a.arrayMin,g=a.arrayMax,f=a.addEvent,c=a.Chart,t=a.Point,w=a.Series,x=a.seriesType,d=a.seriesTypes;f(a.Axis,"afterInit",function(){this.isXAxis||(this.waterfallStacks={})});f(c,"beforeRedraw",function(){for(var b=this.axes,d=this.series,a=d.length;a--;)d[a].options.stacking&&(b.forEach(function(b){b.isXAxis||(b.waterfallStacks={})}),a=0)});x("waterfall","column",{dataLabels:{inside:!0},lineWidth:1,lineColor:"#333333",dashStyle:"Dot",borderColor:"#333333",
states:{hover:{lineWidthPlus:0}}},{pointValKey:"y",showLine:!0,generatePoints:function(){var b,a,c,f;d.column.prototype.generatePoints.apply(this);c=0;for(a=this.points.length;c<a;c++)if(b=this.points[c],f=this.processedYData[c],b.isIntermediateSum||b.isSum)b.y=p(f)},translate:function(){var b=this.options,a=this.yAxis,c,f,k,m,g,h,p,l,t,w=e(b.minPointLength,5),x=w/2,r=b.threshold,C=b.stacking,J=a.waterfallStacks[this.stackKey],A;d.column.prototype.translate.apply(this);p=l=r;f=this.points;c=0;for(b=
f.length;c<b;c++)k=f[c],h=this.processedYData[c],m=k.shapeArgs,t=[0,h],A=k.y,C?J&&(t=J[c],"overlap"===C?(g=t.threshold+t.total,t.total-=A,g=0<=A?g:g-A):0<=A?(g=t.threshold+t.posTotal,t.posTotal-=A):(g=t.threshold+t.negTotal,t.negTotal-=A,g-=A),k.isSum||(t.connectorThreshold=t.threshold+t.stackTotal),a.reversed?(h=0<=A?g-A:g+A,A=g):(h=g,A=g-A),k.below=h<=e(r,0),m.y=a.translate(h,0,1,0,1),m.height=Math.abs(m.y-a.translate(A,0,1,0,1))):(g=Math.max(p,p+A)+t[0],m.y=a.translate(g,0,1,0,1),k.isSum?(m.y=
a.translate(t[1],0,1,0,1),m.height=Math.min(a.translate(t[0],0,1,0,1),a.len)-m.y):k.isIntermediateSum?(0<=A?(h=t[1]+l,A=l):(h=l,A=t[1]+l),a.reversed&&(h^=A,A^=h,h^=A),m.y=a.translate(h,0,1,0,1),m.height=Math.abs(m.y-Math.min(a.translate(A,0,1,0,1),a.len)),l+=t[1]):(m.height=0<h?a.translate(p,0,1,0,1)-m.y:a.translate(p,0,1,0,1)-a.translate(p-h,0,1,0,1),p+=h,k.below=p<e(r,0)),0>m.height&&(m.y+=m.height,m.height*=-1)),k.plotY=m.y=Math.round(m.y)-this.borderWidth%2/2,m.height=Math.max(Math.round(m.height),
.001),k.yBottom=m.y+m.height,m.height<=w&&!k.isNull?(m.height=w,m.y-=x,k.plotY=m.y,k.minPointLengthOffset=0>k.y?-x:x):(k.isNull&&(m.width=0),k.minPointLengthOffset=0),m=k.plotY+(k.negative?m.height:0),this.chart.inverted?k.tooltipPos[0]=a.len-m:k.tooltipPos[1]=m},processData:function(b){var d=this.options,a=this.yData,c=d.data,k,m=a.length,q=d.threshold||0,f,g,e,h,t,l;for(l=g=f=e=h=0;l<m;l++)t=a[l],k=c&&c[l]?c[l]:{},"sum"===t||k.isSum?a[l]=p(g):"intermediateSum"===t||k.isIntermediateSum?(a[l]=p(f),
f=0):(g+=t,f+=t),e=Math.min(g,e),h=Math.max(g,h);w.prototype.processData.call(this,b);d.stacking||(this.dataMin=e+q,this.dataMax=h)},toYData:function(b){return b.isSum?0===b.x?null:"sum":b.isIntermediateSum?0===b.x?null:"intermediateSum":b.y},pointAttribs:function(b,a){var c=this.options.upColor;c&&!b.options.color&&(b.color=0<b.y?c:null);b=d.column.prototype.pointAttribs.call(this,b,a);delete b.dashstyle;return b},getGraphPath:function(){return["M",0,0]},getCrispPath:function(){var b=this.data,d=
this.yAxis,a=b.length,c=Math.round(this.graph.strokeWidth())%2/2,k=Math.round(this.borderWidth)%2/2,m=this.xAxis.reversed,f=this.yAxis.reversed,g=this.options.stacking,e=[],h,p,l,t,w,x,r;for(x=1;x<a;x++){w=b[x].shapeArgs;p=b[x-1];t=b[x-1].shapeArgs;h=d.waterfallStacks[this.stackKey];l=0<p.y?-t.height:0;h&&(h=h[x-1],g?(h=h.connectorThreshold,l=Math.round(d.translate(h,0,1,0,1)+(f?l:0))-c):l=t.y+p.minPointLengthOffset+k-c,r=["M",t.x+(m?0:t.width),l,"L",w.x+(m?w.width:0),l]);if(!g&&0>p.y&&!f||0<p.y&&
f)r[2]+=t.height,r[5]+=t.height;e=e.concat(r)}return e},drawGraph:function(){w.prototype.drawGraph.call(this);this.graph.attr({d:this.getCrispPath()})},setStackedPoints:function(){var b=this.options,d=this.yAxis.waterfallStacks,a=b.threshold,c=a||0,k=a||0,m=this.stackKey,f=this.xData,g=f.length,e,h,p,l;if(this.visible||!this.chart.options.chart.ignoreHiddenSeries)for(d[m]||(d[m]={}),d=d[m],m=0;m<g;m++)e=f[m],d[e]||(d[e]={negTotal:0,posTotal:0,total:0,stackTotal:0,threshold:0,stackState:[c]}),e=d[e],
h=this.yData[m],0<=h?e.posTotal+=h:e.negTotal+=h,l=b.data[m],h=e.posTotal,p=e.negTotal,l&&l.isIntermediateSum?(c^=k,k^=c,c^=k):l&&l.isSum&&(c=a),e.stackTotal=h+p,e.total=e.stackTotal,e.threshold=c,e.stackState[0]=c,e.stackState.push(e.stackTotal),c+=e.stackTotal},getExtremes:function(){var d=this.options.stacking,a,c,f,k,m;d&&(a=this.yAxis,a=a.waterfallStacks,c=this.stackedYNeg=[],f=this.stackedYPos=[],"overlap"===d?h(a[this.stackKey],function(d){k=[];d.stackState.forEach(function(b,a){m=d.stackState[0];
a?k.push(b+m):k.push(m)});c.push(b(k));f.push(g(k))}):h(a[this.stackKey],function(b){c.push(b.negTotal+b.threshold);f.push(b.posTotal+b.threshold)}),this.dataMin=b(c),this.dataMax=g(f))}},{getClassName:function(){var b=t.prototype.getClassName.call(this);this.isSum?b+=" highcharts-sum":this.isIntermediateSum&&(b+=" highcharts-intermediate-sum");return b},isValid:function(){return l(this.y,!0)||this.isSum||this.isIntermediateSum}})});y(r,"parts-more/PolygonSeries.js",[r["parts/Globals.js"]],function(a){var p=
a.Series,l=a.seriesType,e=a.seriesTypes;l("polygon","scatter",{marker:{enabled:!1,states:{hover:{enabled:!1}}},stickyTracking:!1,tooltip:{followPointer:!0,pointFormat:""},trackByArea:!0},{type:"polygon",getGraphPath:function(){for(var a=p.prototype.getGraphPath.call(this),b=a.length+1;b--;)(b===a.length||"M"===a[b])&&0<b&&a.splice(b,0,"z");return this.areaPath=a},drawGraph:function(){this.options.fillColor=this.color;e.area.prototype.drawGraph.call(this)},drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,
drawTracker:p.prototype.drawTracker,setStackedPoints:a.noop})});y(r,"parts-more/BubbleLegend.js",[r["parts/Globals.js"]],function(a){var p=a.Series,l=a.Legend,e=a.Chart,h=a.addEvent,b=a.wrap,g=a.color,f=a.isNumber,c=a.numberFormat,t=a.objectEach,w=a.merge,x=a.noop,d=a.pick,q=a.stableSort,n=a.setOptions,u=a.arrayMin,v=a.arrayMax;n({legend:{bubbleLegend:{borderColor:void 0,borderWidth:2,className:void 0,color:void 0,connectorClassName:void 0,connectorColor:void 0,connectorDistance:60,connectorWidth:1,
enabled:!1,labels:{className:void 0,allowOverlap:!1,format:"",formatter:void 0,align:"right",style:{fontSize:10,color:void 0},x:0,y:0},maxSize:60,minSize:10,legendIndex:0,ranges:{value:void 0,borderColor:void 0,color:void 0,connectorColor:void 0},sizeBy:"area",sizeByAbsoluteValue:!1,zIndex:1,zThreshold:0}}});a.BubbleLegend=function(b,d){this.init(b,d)};a.BubbleLegend.prototype={init:function(b,d){this.options=b;this.visible=!0;this.chart=d.chart;this.legend=d},setState:x,addToLegend:function(b){b.splice(this.options.legendIndex,
0,this)},drawLegendSymbol:function(b){var a=this.chart,k=this.options,c=d(b.options.itemDistance,20),e,g=k.ranges;e=k.connectorDistance;this.fontMetrics=a.renderer.fontMetrics(k.labels.style.fontSize.toString()+"px");g&&g.length&&f(g[0].value)?(q(g,function(b,d){return d.value-b.value}),this.ranges=g,this.setOptions(),this.render(),a=this.getMaxLabelSize(),g=this.ranges[0].radius,b=2*g,e=e-g+a.width,e=0<e?e:0,this.maxLabel=a,this.movementX="left"===k.labels.align?e:0,this.legendItemWidth=b+e+c,this.legendItemHeight=
b+this.fontMetrics.h/2):b.options.bubbleLegend.autoRanges=!0},setOptions:function(){var b=this.ranges,a=this.options,c=this.chart.series[a.seriesIndex],f=this.legend.baseline,e={"z-index":a.zIndex,"stroke-width":a.borderWidth},q={"z-index":a.zIndex,"stroke-width":a.connectorWidth},n=this.getLabelStyles(),u=c.options.marker.fillOpacity,h=this.chart.styledMode;b.forEach(function(k,m){h||(e.stroke=d(k.borderColor,a.borderColor,c.color),e.fill=d(k.color,a.color,1!==u?g(c.color).setOpacity(u).get("rgba"):
c.color),q.stroke=d(k.connectorColor,a.connectorColor,c.color));b[m].radius=this.getRangeRadius(k.value);b[m]=w(b[m],{center:b[0].radius-b[m].radius+f});h||w(!0,b[m],{bubbleStyle:w(!1,e),connectorStyle:w(!1,q),labelStyle:n})},this)},getLabelStyles:function(){var b=this.options,a={},c="left"===b.labels.align,f=this.legend.options.rtl;t(b.labels.style,function(b,d){"color"!==d&&"fontSize"!==d&&"z-index"!==d&&(a[d]=b)});return w(!1,a,{"font-size":b.labels.style.fontSize,fill:d(b.labels.style.color,"#000000"),
"z-index":b.zIndex,align:f||c?"right":"left"})},getRangeRadius:function(b){var d=this.options;return this.chart.series[this.options.seriesIndex].getRadius.call(this,d.ranges[d.ranges.length-1].value,d.ranges[0].value,d.minSize,d.maxSize,b)},render:function(){var b=this.chart.renderer,d=this.options.zThreshold;this.symbols||(this.symbols={connectors:[],bubbleItems:[],labels:[]});this.legendSymbol=b.g("bubble-legend");this.legendItem=b.g("bubble-legend-item");this.legendSymbol.translateX=0;this.legendSymbol.translateY=
0;this.ranges.forEach(function(b){b.value>=d&&this.renderRange(b)},this);this.legendSymbol.add(this.legendItem);this.legendItem.add(this.legendGroup);this.hideOverlappingLabels()},renderRange:function(b){var d=this.options,a=d.labels,c=this.chart.renderer,k=this.symbols,f=k.labels,e=b.center,q=Math.abs(b.radius),g=d.connectorDistance,n=a.align,u=a.style.fontSize,g=this.legend.options.rtl||"left"===n?-g:g,a=d.connectorWidth,h=this.ranges[0].radius,p=e-q-d.borderWidth/2+a/2,v,u=u/2-(this.fontMetrics.h-
u)/2,l=c.styledMode;"center"===n&&(g=0,d.connectorDistance=0,b.labelStyle.align="center");n=p+d.labels.y;v=h+g+d.labels.x;k.bubbleItems.push(c.circle(h,e+((p%1?1:.5)-(a%2?0:.5)),q).attr(l?{}:b.bubbleStyle).addClass((l?"highcharts-color-"+this.options.seriesIndex+" ":"")+"highcharts-bubble-legend-symbol "+(d.className||"")).add(this.legendSymbol));k.connectors.push(c.path(c.crispLine(["M",h,p,"L",h+g,p],d.connectorWidth)).attr(l?{}:b.connectorStyle).addClass((l?"highcharts-color-"+this.options.seriesIndex+
" ":"")+"highcharts-bubble-legend-connectors "+(d.connectorClassName||"")).add(this.legendSymbol));b=c.text(this.formatLabel(b),v,n+u).attr(l?{}:b.labelStyle).addClass("highcharts-bubble-legend-labels "+(d.labels.className||"")).add(this.legendSymbol);f.push(b);b.placed=!0;b.alignAttr={x:v,y:n+u}},getMaxLabelSize:function(){var b,d;this.symbols.labels.forEach(function(a){d=a.getBBox(!0);b=b?d.width>b.width?d:b:d});return b||{}},formatLabel:function(b){var d=this.options,k=d.labels.formatter;return(d=
d.labels.format)?a.format(d,b):k?k.call(b):c(b.value,1)},hideOverlappingLabels:function(){var b=this.chart,d=this.symbols;!this.options.labels.allowOverlap&&d&&(b.hideOverlappingLabels(d.labels),d.labels.forEach(function(b,a){b.newOpacity?b.newOpacity!==b.oldOpacity&&d.connectors[a].show():d.connectors[a].hide()}))},getRanges:function(){var b=this.legend.bubbleLegend,a,c=b.options.ranges,e,q=Number.MAX_VALUE,g=-Number.MAX_VALUE;b.chart.series.forEach(function(b){b.isBubble&&!b.ignoreSeries&&(e=b.zData.filter(f),
e.length&&(q=d(b.options.zMin,Math.min(q,Math.max(u(e),!1===b.options.displayNegative?b.options.zThreshold:-Number.MAX_VALUE))),g=d(b.options.zMax,Math.max(g,v(e)))))});a=q===g?[{value:g}]:[{value:q},{value:(q+g)/2},{value:g,autoRanges:!0}];c.length&&c[0].radius&&a.reverse();a.forEach(function(b,d){c&&c[d]&&(a[d]=w(!1,c[d],b))});return a},predictBubbleSizes:function(){var b=this.chart,d=this.fontMetrics,a=b.legend.options,c="horizontal"===a.layout,f=c?b.legend.lastLineHeight:0,e=b.plotSizeX,q=b.plotSizeY,
g=b.series[this.options.seriesIndex],b=Math.ceil(g.minPxSize),n=Math.ceil(g.maxPxSize),g=g.options.maxSize,u=Math.min(q,e);if(a.floating||!/%$/.test(g))d=n;else if(g=parseFloat(g),d=(u+f-d.h/2)*g/100/(g/100+1),c&&q-d>=e||!c&&e-d>=q)d=n;return[b,Math.ceil(d)]},updateRanges:function(b,d){var a=this.legend.options.bubbleLegend;a.minSize=b;a.maxSize=d;a.ranges=this.getRanges()},correctSizes:function(){var b=this.legend,d=this.chart.series[this.options.seriesIndex];1<Math.abs(Math.ceil(d.maxPxSize)-this.options.maxSize)&&
(this.updateRanges(this.options.minSize,d.maxPxSize),b.render())}};h(a.Legend,"afterGetAllItems",function(b){var d=this.bubbleLegend,c=this.options,k=c.bubbleLegend,f=this.chart.getVisibleBubbleSeriesIndex();d&&d.ranges&&d.ranges.length&&(k.ranges.length&&(k.autoRanges=!!k.ranges[0].autoRanges),this.destroyItem(d));0<=f&&c.enabled&&k.enabled&&(k.seriesIndex=f,this.bubbleLegend=new a.BubbleLegend(k,this),this.bubbleLegend.addToLegend(b.allItems))});e.prototype.getVisibleBubbleSeriesIndex=function(){for(var b=
this.series,d=0;d<b.length;){if(b[d]&&b[d].isBubble&&b[d].visible&&b[d].zData.length)return d;d++}return-1};l.prototype.getLinesHeights=function(){var b=this.allItems,d=[],a,c=b.length,f,e=0;for(f=0;f<c;f++)if(b[f].legendItemHeight&&(b[f].itemHeight=b[f].legendItemHeight),b[f]===b[c-1]||b[f+1]&&b[f]._legendItemPos[1]!==b[f+1]._legendItemPos[1]){d.push({height:0});a=d[d.length-1];for(e;e<=f;e++)b[e].itemHeight>a.height&&(a.height=b[e].itemHeight);a.step=f}return d};l.prototype.retranslateItems=function(b){var d,
a,c,f=this.options.rtl,e=0;this.allItems.forEach(function(k,g){d=k.legendGroup.translateX;a=k._legendItemPos[1];if((c=k.movementX)||f&&k.ranges)c=f?d-k.options.maxSize/2:d+c,k.legendGroup.attr({translateX:c});g>b[e].step&&e++;k.legendGroup.attr({translateY:Math.round(a+b[e].height/2)});k._legendItemPos[1]=a+b[e].height/2})};h(p,"legendItemClick",function(){var b=this.chart,d=this.visible,a=this.chart.legend;a&&a.bubbleLegend&&(this.visible=!d,this.ignoreSeries=d,b=0<=b.getVisibleBubbleSeriesIndex(),
a.bubbleLegend.visible!==b&&(a.update({bubbleLegend:{enabled:b}}),a.bubbleLegend.visible=b),this.visible=d)});b(e.prototype,"drawChartBox",function(b,d,a){var c=this.legend,f=0<=this.getVisibleBubbleSeriesIndex(),e;c&&c.options.enabled&&c.bubbleLegend&&c.options.bubbleLegend.autoRanges&&f?(e=c.bubbleLegend.options,f=c.bubbleLegend.predictBubbleSizes(),c.bubbleLegend.updateRanges(f[0],f[1]),e.placed||(c.group.placed=!1,c.allItems.forEach(function(b){b.legendGroup.translateY=null})),c.render(),this.getMargins(),
this.axes.forEach(function(b){b.render();e.placed||(b.setScale(),b.updateNames(),t(b.ticks,function(b){b.isNew=!0;b.isNewLabel=!0}))}),e.placed=!0,this.getMargins(),b.call(this,d,a),c.bubbleLegend.correctSizes(),c.retranslateItems(c.getLinesHeights())):(b.call(this,d,a),c&&c.options.enabled&&c.bubbleLegend&&(c.render(),c.retranslateItems(c.getLinesHeights())))})});y(r,"parts-more/BubbleSeries.js",[r["parts/Globals.js"]],function(a){var p=a.arrayMax,l=a.arrayMin,e=a.Axis,h=a.color,b=a.isNumber,g=a.noop,
f=a.pick,c=a.pInt,t=a.Point,w=a.Series,x=a.seriesType,d=a.seriesTypes;x("bubble","scatter",{dataLabels:{formatter:function(){return this.point.z},inside:!0,verticalAlign:"middle"},animationLimit:250,marker:{lineColor:null,lineWidth:1,fillOpacity:.5,radius:null,states:{hover:{radiusPlus:0}},symbol:"circle"},minSize:8,maxSize:"20%",softThreshold:!1,states:{hover:{halo:{size:5}}},tooltip:{pointFormat:"({point.x}, {point.y}), Size: {point.z}"},turboThreshold:0,zThreshold:0,zoneAxis:"z"},{pointArrayMap:["y",
"z"],parallelArrays:["x","y","z"],trackerGroups:["group","dataLabelsGroup"],specialGroup:"group",bubblePadding:!0,zoneAxis:"z",directTouch:!0,isBubble:!0,pointAttribs:function(b,d){var a=this.options.marker.fillOpacity;b=w.prototype.pointAttribs.call(this,b,d);1!==a&&(b.fill=h(b.fill).setOpacity(a).get("rgba"));return b},getRadii:function(b,d,a){var c,f=this.zData,e=a.minPxSize,g=a.maxPxSize,q=[],n;c=0;for(a=f.length;c<a;c++)n=f[c],q.push(this.getRadius(b,d,e,g,n));this.radii=q},getRadius:function(d,
a,c,f,e){var g=this.options,k="width"!==g.sizeBy,q=g.zThreshold,n=a-d;g.sizeByAbsoluteValue&&null!==e&&(e=Math.abs(e-q),n=Math.max(a-q,Math.abs(d-q)),d=0);b(e)?e<d?c=c/2-1:(d=0<n?(e-d)/n:.5,k&&0<=d&&(d=Math.sqrt(d)),c=Math.ceil(c+d*(f-c))/2):c=null;return c},animate:function(b){!b&&this.points.length<this.options.animationLimit&&(this.points.forEach(function(b){var d=b.graphic,a;d&&d.width&&(a={x:d.x,y:d.y,width:d.width,height:d.height},d.attr({x:b.plotX,y:b.plotY,width:1,height:1}),d.animate(a,this.options.animation))},
this),this.animate=null)},hasData:function(){return!!this.processedXData.length},translate:function(){var c,f=this.data,e,g,k=this.radii;d.scatter.prototype.translate.call(this);for(c=f.length;c--;)e=f[c],g=k?k[c]:0,b(g)&&g>=this.minPxSize/2?(e.marker=a.extend(e.marker,{radius:g,width:2*g,height:2*g}),e.dlBox={x:e.plotX-g,y:e.plotY-g,width:2*g,height:2*g}):e.shapeArgs=e.plotY=e.dlBox=void 0},alignDataLabel:d.column.prototype.alignDataLabel,buildKDTree:g,applyZones:g},{haloPath:function(b){return t.prototype.haloPath.call(this,
0===b?0:(this.marker?this.marker.radius||0:0)+b)},ttBelow:!1});e.prototype.beforePadding=function(){var d=this,e=this.len,g=this.chart,h=0,k=e,m=this.isXAxis,t=m?"xData":"yData",w=this.min,x={},r=Math.min(g.plotWidth,g.plotHeight),B=Number.MAX_VALUE,y=-Number.MAX_VALUE,z=this.max-w,H=e/z,C=[];this.series.forEach(function(b){var e=b.options;!b.bubblePadding||!b.visible&&g.options.chart.ignoreHiddenSeries||(d.allowZoomOutside=!0,C.push(b),m&&(["minSize","maxSize"].forEach(function(b){var d=e[b],a=/%$/.test(d),
d=c(d);x[b]=a?r*d/100:d}),b.minPxSize=x.minSize,b.maxPxSize=Math.max(x.maxSize,x.minSize),b=b.zData.filter(a.isNumber),b.length&&(B=f(e.zMin,Math.min(B,Math.max(l(b),!1===e.displayNegative?e.zThreshold:-Number.MAX_VALUE))),y=f(e.zMax,Math.max(y,p(b))))))});C.forEach(function(a){var c=a[t],e=c.length,f;m&&a.getRadii(B,y,a);if(0<z)for(;e--;)b(c[e])&&d.dataMin<=c[e]&&c[e]<=d.dataMax&&(f=a.radii[e],h=Math.min((c[e]-w)*H-f,h),k=Math.max((c[e]-w)*H+f,k))});C.length&&0<z&&!this.isLog&&(k-=e,H*=(e+Math.max(0,
h)-Math.min(k,e))/e,[["min","userMin",h],["max","userMax",k]].forEach(function(b){void 0===f(d.options[b[0]],d[b[1]])&&(d[b[0]]+=b[2]/H)}))}});y(r,"modules/networkgraph/integrations.js",[r["parts/Globals.js"]],function(a){a.networkgraphIntegrations={verlet:{attractiveForceFunction:function(a,l){return(l-a)/a},repulsiveForceFunction:function(a,l){return(l-a)/a*(l>a?1:0)},barycenter:function(){var a=this.options.gravitationalConstant,l=this.barycenter.xFactor,e=this.barycenter.yFactor,l=(l-(this.box.left+
this.box.width)/2)*a,e=(e-(this.box.top+this.box.height)/2)*a;this.nodes.forEach(function(a){a.fixedPosition||(a.plotX-=l/a.mass/a.degree,a.plotY-=e/a.mass/a.degree)})},repulsive:function(a,l,e){l=l*this.diffTemperature/a.mass/a.degree;a.fixedPosition||(a.plotX+=e.x*l,a.plotY+=e.y*l)},attractive:function(a,l,e){var h=a.getMass(),b=-e.x*l*this.diffTemperature;l=-e.y*l*this.diffTemperature;a.fromNode.fixedPosition||(a.fromNode.plotX-=b*h.fromNode/a.fromNode.degree,a.fromNode.plotY-=l*h.fromNode/a.fromNode.degree);
a.toNode.fixedPosition||(a.toNode.plotX+=b*h.toNode/a.toNode.degree,a.toNode.plotY+=l*h.toNode/a.toNode.degree)},integrate:function(a,l){var e=-a.options.friction,h=a.options.maxSpeed,b=(l.plotX+l.dispX-l.prevX)*e,e=(l.plotY+l.dispY-l.prevY)*e,g=Math.abs,f=g(b)/(b||1),g=g(e)/(e||1),b=f*Math.min(h,Math.abs(b)),e=g*Math.min(h,Math.abs(e));l.prevX=l.plotX+l.dispX;l.prevY=l.plotY+l.dispY;l.plotX+=b;l.plotY+=e;l.temperature=a.vectorLength({x:b,y:e})},getK:function(a){return Math.pow(a.box.width*a.box.height/
a.nodes.length,.5)}},euler:{attractiveForceFunction:function(a,l){return a*a/l},repulsiveForceFunction:function(a,l){return l*l/a},barycenter:function(){var a=this.options.gravitationalConstant,l=this.barycenter.xFactor,e=this.barycenter.yFactor;this.nodes.forEach(function(h){if(!h.fixedPosition){var b=h.getDegree(),b=b*(1+b/2);h.dispX+=(l-h.plotX)*a*b/h.degree;h.dispY+=(e-h.plotY)*a*b/h.degree}})},repulsive:function(a,l,e,h){a.dispX+=e.x/h*l/a.degree;a.dispY+=e.y/h*l/a.degree},attractive:function(a,
l,e,h){var b=a.getMass(),g=e.x/h*l;l*=e.y/h;a.fromNode.fixedPosition||(a.fromNode.dispX-=g*b.fromNode/a.fromNode.degree,a.fromNode.dispY-=l*b.fromNode/a.fromNode.degree);a.toNode.fixedPosition||(a.toNode.dispX+=g*b.toNode/a.toNode.degree,a.toNode.dispY+=l*b.toNode/a.toNode.degree)},integrate:function(a,l){var e;l.dispX+=l.dispX*a.options.friction;l.dispY+=l.dispY*a.options.friction;e=l.temperature=a.vectorLength({x:l.dispX,y:l.dispY});0!==e&&(l.plotX+=l.dispX/e*Math.min(Math.abs(l.dispX),a.temperature),
l.plotY+=l.dispY/e*Math.min(Math.abs(l.dispY),a.temperature))},getK:function(a){return Math.pow(a.box.width*a.box.height/a.nodes.length,.3)}}}});y(r,"modules/networkgraph/QuadTree.js",[r["parts/Globals.js"]],function(a){var p=a.QuadTreeNode=function(a){this.box=a;this.boxSize=Math.min(a.width,a.height);this.nodes=[];this.body=this.isInternal=!1;this.isEmpty=!0};a.extend(p.prototype,{insert:function(a,h){this.isInternal?this.nodes[this.getBoxPosition(a)].insert(a,h-1):(this.isEmpty=!1,this.body?h?
(this.isInternal=!0,this.divideBox(),!0!==this.body&&(this.nodes[this.getBoxPosition(this.body)].insert(this.body,h-1),this.body=!0),this.nodes[this.getBoxPosition(a)].insert(a,h-1)):this.nodes.push(a):(this.isInternal=!1,this.body=a))},updateMassAndCenter:function(){var a=0,h=0,b=0;this.isInternal?(this.nodes.forEach(function(e){e.isEmpty||(a+=e.mass,h+=e.plotX*e.mass,b+=e.plotY*e.mass)}),h/=a,b/=a):this.body&&(a=this.body.mass,h=this.body.plotX,b=this.body.plotY);this.mass=a;this.plotX=h;this.plotY=
b},divideBox:function(){var a=this.box.width/2,h=this.box.height/2;this.nodes[0]=new p({left:this.box.left,top:this.box.top,width:a,height:h});this.nodes[1]=new p({left:this.box.left+a,top:this.box.top,width:a,height:h});this.nodes[2]=new p({left:this.box.left+a,top:this.box.top+h,width:a,height:h});this.nodes[3]=new p({left:this.box.left,top:this.box.top+h,width:a,height:h})},getBoxPosition:function(a){var e=a.plotY<this.box.top+this.box.height/2;return a.plotX<this.box.left+this.box.width/2?e?0:
3:e?1:2}});var l=a.QuadTree=function(a,h,b,g){this.box={left:a,top:h,width:b,height:g};this.maxDepth=25;this.root=new p(this.box,"0");this.root.isInternal=!0;this.root.isRoot=!0;this.root.divideBox()};a.extend(l.prototype,{insertNodes:function(a){a.forEach(function(a){this.root.insert(a,this.maxDepth)},this)},visitNodeRecursive:function(a,h,b,g,f){var c;a||(a=this.root);a===this.root&&h&&(c=h(a));!1!==c&&(a.nodes.forEach(function(a){if(a.isInternal){h&&(c=h(a));if(!1===c)return;this.visitNodeRecursive(a,
h,b,g,f)}else a.body&&h&&h(a.body);b&&b(a)},this),a===this.root&&b&&b(a))},calculateMassAndCenter:function(){this.visitNodeRecursive(null,null,function(a){a.updateMassAndCenter()})},render:function(a,h){this.visitNodeRecursive(this.root,null,null,a,h)},clear:function(a){this.render(a,!0)},renderBox:function(a,h,b){a.graphic||b?b&&(a.graphic&&(a.graphic=a.graphic.destroy()),a.graphic2&&(a.graphic2=a.graphic2.destroy()),a.label&&(a.label=a.label.destroy())):(a.graphic=h.renderer.rect(a.box.left+h.plotLeft,
a.box.top+h.plotTop,a.box.width,a.box.height).attr({stroke:"rgba(100, 100, 100, 0.5)","stroke-width":2}).add(),isNaN(a.plotX)||(a.graphic2=h.renderer.circle(a.plotX,a.plotY,a.mass/10).attr({fill:"red",translateY:h.plotTop,translateX:h.plotLeft}).add()))}})});y(r,"modules/networkgraph/layouts.js",[r["parts/Globals.js"]],function(a){var p=a.pick,l=a.defined,e=a.addEvent,h=a.Chart;a.layouts={"reingold-fruchterman":function(){}};a.extend(a.layouts["reingold-fruchterman"].prototype,{init:function(b){this.options=
b;this.nodes=[];this.links=[];this.series=[];this.box={x:0,y:0,width:0,height:0};this.setInitialRendering(!0);this.integration=a.networkgraphIntegrations[b.integration];this.attractiveForce=p(b.attractiveForce,this.integration.attractiveForceFunction);this.repulsiveForce=p(b.repulsiveForce,this.integration.repulsiveForceFunction);this.approximation=b.approximation},start:function(){var b=this.series,a=this.options;this.currentStep=0;this.forces=b[0]&&b[0].forces||[];this.initialRendering&&(this.initPositions(),
b.forEach(function(b){b.render()}));this.setK();this.resetSimulation(a);a.enableSimulation&&this.step()},step:function(){var b=this,g=this.series,f=this.options;b.currentStep++;"barnes-hut"===b.approximation&&(b.createQuadTree(),b.quadTree.calculateMassAndCenter());b.forces.forEach(function(a){b[a+"Forces"](b.temperature)});b.applyLimits(b.temperature);b.temperature=b.coolDown(b.startTemperature,b.diffTemperature,b.currentStep);b.prevSystemTemperature=b.systemTemperature;b.systemTemperature=b.getSystemTemperature();
f.enableSimulation&&(g.forEach(function(b){b.chart&&b.render()}),b.maxIterations--&&isFinite(b.temperature)&&!b.isStable()?(b.simulation&&a.win.cancelAnimationFrame(b.simulation),b.simulation=a.win.requestAnimationFrame(function(){b.step()})):b.simulation=!1)},stop:function(){this.simulation&&a.win.cancelAnimationFrame(this.simulation)},setArea:function(b,a,f,c){this.box={left:b,top:a,width:f,height:c}},setK:function(){this.k=this.options.linkLength||this.integration.getK(this)},addNodes:function(b){b.forEach(function(b){-1===
this.nodes.indexOf(b)&&this.nodes.push(b)},this)},removeNode:function(b){b=this.nodes.indexOf(b);-1!==b&&this.nodes.splice(b,1)},removeLink:function(b){b=this.links.indexOf(b);-1!==b&&this.links.splice(b,1)},addLinks:function(b){b.forEach(function(b){-1===this.links.indexOf(b)&&this.links.push(b)},this)},addSeries:function(b){-1===this.series.indexOf(b)&&this.series.push(b)},clear:function(){this.nodes.length=0;this.links.length=0;this.series.length=0;this.resetSimulation()},resetSimulation:function(){this.forcedStop=
!1;this.systemTemperature=0;this.setMaxIterations();this.setTemperature();this.setDiffTemperature()},setMaxIterations:function(b){this.maxIterations=p(b,this.options.maxIterations)},setTemperature:function(){this.temperature=this.startTemperature=Math.sqrt(this.nodes.length)},setDiffTemperature:function(){this.diffTemperature=this.startTemperature/(this.options.maxIterations+1)},setInitialRendering:function(b){this.initialRendering=b},createQuadTree:function(){this.quadTree=new a.QuadTree(this.box.left,
this.box.top,this.box.width,this.box.height);this.quadTree.insertNodes(this.nodes)},initPositions:function(){var b=this.options.initialPositions;a.isFunction(b)?(b.call(this),this.nodes.forEach(function(b){l(b.prevX)||(b.prevX=b.plotX);l(b.prevY)||(b.prevY=b.plotY);b.dispX=0;b.dispY=0})):"circle"===b?this.setCircularPositions():this.setRandomPositions()},setCircularPositions:function(){function b(a){a.linksFrom.forEach(function(a){l[a.toNode.id]||(l[a.toNode.id]=!0,h.push(a.toNode),b(a.toNode))})}
var a=this.box,f=this.nodes,c=2*Math.PI/(f.length+1),e=f.filter(function(b){return 0===b.linksTo.length}),h=[],l={},d=this.options.initialPositionRadius;e.forEach(function(a){h.push(a);b(a)});h.length?f.forEach(function(b){-1===h.indexOf(b)&&h.push(b)}):h=f;h.forEach(function(b,f){b.plotX=b.prevX=p(b.plotX,a.width/2+d*Math.cos(f*c));b.plotY=b.prevY=p(b.plotY,a.height/2+d*Math.sin(f*c));b.dispX=0;b.dispY=0})},setRandomPositions:function(){function b(b){b=b*b/Math.PI;return b-=Math.floor(b)}var a=this.box,
f=this.nodes,c=f.length+1;f.forEach(function(f,e){f.plotX=f.prevX=p(f.plotX,a.width*b(e));f.plotY=f.prevY=p(f.plotY,a.height*b(c+e));f.dispX=0;f.dispY=0})},force:function(b){this.integration[b].apply(this,Array.prototype.slice.call(arguments,1))},barycenterForces:function(){this.getBarycenter();this.force("barycenter")},getBarycenter:function(){var b=0,a=0,f=0;this.nodes.forEach(function(c){a+=c.plotX*c.mass;f+=c.plotY*c.mass;b+=c.mass});return this.barycenter={x:a,y:f,xFactor:a/b,yFactor:f/b}},barnesHutApproximation:function(b,
a){var f=this.getDistXY(b,a),c=this.vectorLength(f),e,g;b!==a&&0!==c&&(a.isInternal?a.boxSize/c<this.options.theta&&0!==c?(g=this.repulsiveForce(c,this.k),this.force("repulsive",b,g*a.mass,f,c),e=!1):e=!0:(g=this.repulsiveForce(c,this.k),this.force("repulsive",b,g*a.mass,f,c)));return e},repulsiveForces:function(){var b=this;"barnes-hut"===b.approximation?b.nodes.forEach(function(a){b.quadTree.visitNodeRecursive(null,function(f){return b.barnesHutApproximation(a,f)})}):b.nodes.forEach(function(a){b.nodes.forEach(function(f){var c,
e,g;a===f||a.fixedPosition||(g=b.getDistXY(a,f),e=b.vectorLength(g),c=b.repulsiveForce(e,b.k),b.force("repulsive",a,c*f.mass,g,e))})})},attractiveForces:function(){var b=this,a,f,c;b.links.forEach(function(e){e.fromNode&&e.toNode&&(a=b.getDistXY(e.fromNode,e.toNode),f=b.vectorLength(a),0!==f&&(c=b.attractiveForce(f,b.k),b.force("attractive",e,c,a,f)))})},applyLimits:function(){var b=this;b.nodes.forEach(function(a){a.fixedPosition||(b.integration.integrate(b,a),b.applyLimitBox(a,b.box),a.dispX=0,
a.dispY=0)})},applyLimitBox:function(b,a){var f=b.marker&&b.marker.radius||0;b.plotX=Math.max(Math.min(b.plotX,a.width-f),a.left+f);b.plotY=Math.max(Math.min(b.plotY,a.height-f),a.top+f)},coolDown:function(b,a,f){return b-a*f},isStable:function(){return.00001>Math.abs(this.systemTemperature-this.prevSystemTemperature)||0>=this.temperature},getSystemTemperature:function(){return this.nodes.reduce(function(a,e){return a+e.temperature},0)},vectorLength:function(a){return Math.sqrt(a.x*a.x+a.y*a.y)},
getDistR:function(a,e){a=this.getDistXY(a,e);return this.vectorLength(a)},getDistXY:function(a,e){var b=a.plotX-e.plotX;a=a.plotY-e.plotY;return{x:b,y:a,absX:Math.abs(b),absY:Math.abs(a)}}});e(h,"predraw",function(){this.graphLayoutsLookup&&this.graphLayoutsLookup.forEach(function(a){a.stop()})});e(h,"render",function(){function b(a){a.maxIterations--&&isFinite(a.temperature)&&!a.isStable()&&!a.options.enableSimulation&&(a.beforeStep&&a.beforeStep(),a.step(),e=!1,f=!0)}var e,f=!1;if(this.graphLayoutsLookup){a.setAnimation(!1,
this);for(this.graphLayoutsLookup.forEach(function(a){a.start()});!e;)e=!0,this.graphLayoutsLookup.forEach(b);f&&this.series.forEach(function(a){a&&a.layout&&a.render()})}})});y(r,"modules/networkgraph/draggable-nodes.js",[r["parts/Globals.js"]],function(a){var p=a.Chart,l=a.addEvent;a.dragNodesMixin={onMouseDown:function(a,h){h=this.chart.pointer.normalize(h);a.fixedPosition={chartX:h.chartX,chartY:h.chartY,plotX:a.plotX,plotY:a.plotY};a.inDragMode=!0},onMouseMove:function(a,h){if(a.fixedPosition&&
a.inDragMode){var b=this.chart,e=b.pointer.normalize(h);h=a.fixedPosition.chartX-e.chartX;e=a.fixedPosition.chartY-e.chartY;if(5<Math.abs(h)||5<Math.abs(e))h=a.fixedPosition.plotX-h,e=a.fixedPosition.plotY-e,b.isInsidePlot(h,e)&&(a.plotX=h,a.plotY=e,this.redrawHalo(a),this.layout.simulation?this.layout.resetSimulation():(this.layout.setInitialRendering(!1),this.layout.enableSimulation?this.layout.start():this.layout.setMaxIterations(1),this.chart.redraw(),this.layout.setInitialRendering(!0)))}},onMouseUp:function(a){a.fixedPosition&&
(this.layout.enableSimulation?this.layout.start():this.chart.redraw(),a.inDragMode=!1,this.options.fixedDraggable||delete a.fixedPosition)},redrawHalo:function(a){a&&this.halo&&this.halo.attr({d:a.haloPath(this.options.states.hover.halo.size)})}};l(p,"load",function(){var a=this,h,b,g;a.container&&(h=l(a.container,"mousedown",function(f){var c=a.hoverPoint;c&&c.series&&c.series.hasDraggableNodes&&c.series.options.draggable&&(c.series.onMouseDown(c,f),b=l(a.container,"mousemove",function(a){return c&&
c.series&&c.series.onMouseMove(c,a)}),g=l(a.container.ownerDocument,"mouseup",function(a){b();g();return c&&c.series&&c.series.onMouseUp(c,a)}))}));l(a,"destroy",function(){h()})})});y(r,"parts-more/PackedBubbleSeries.js",[r["parts/Globals.js"]],function(a){var p=a.seriesType,l=a.Series,e=a.Point,h=a.defined,b=a.pick,g=a.addEvent,f=a.Chart,c=a.Color,t=a.layouts["reingold-fruchterman"],w=a.seriesTypes.bubble.prototype.pointClass,x=a.dragNodesMixin;a.networkgraphIntegrations.packedbubble={repulsiveForceFunction:function(a,
b,c,f){return Math.min(a,(c.marker.radius+f.marker.radius)/2)},barycenter:function(){var a=this,b=a.options.gravitationalConstant,c=a.box,f=a.nodes,e,k;f.forEach(function(d){a.options.splitSeries&&!d.isParentNode?(e=d.series.parentNode.plotX,k=d.series.parentNode.plotY):(e=c.width/2,k=c.height/2);d.fixedPosition||(d.plotX-=(d.plotX-e)*b/(d.mass*Math.sqrt(f.length)),d.plotY-=(d.plotY-k)*b/(d.mass*Math.sqrt(f.length)))})},repulsive:function(a,b,c,f){var d=b*this.diffTemperature/a.mass/a.degree;b=c.x*
d;c=c.y*d;a.fixedPosition||(a.plotX+=b,a.plotY+=c);f.fixedPosition||(f.plotX-=b,f.plotY-=c)},integrate:a.networkgraphIntegrations.verlet.integrate,getK:a.noop};a.layouts.packedbubble=a.extendClass(t,{beforeStep:function(){this.options.marker&&this.series.forEach(function(a){a&&(a.translate(),a.drawPoints())})},setCircularPositions:function(){var a=this,c=a.box,f=a.nodes,e=2*Math.PI/(f.length+1),g,k,m=a.options.initialPositionRadius;f.forEach(function(d,f){a.options.splitSeries&&!d.isParentNode?(g=
d.series.parentNode.plotX,k=d.series.parentNode.plotY):(g=c.width/2,k=c.height/2);d.plotX=d.prevX=b(d.plotX,g+m*Math.cos(d.index||f*e));d.plotY=d.prevY=b(d.plotY,k+m*Math.sin(d.index||f*e));d.dispX=0;d.dispY=0})},repulsiveForces:function(){var a=this,b,c,f,e=a.options.bubblePadding;a.nodes.forEach(function(d){d.degree=d.mass;d.neighbours=0;a.nodes.forEach(function(k){b=0;d===k||d.fixedPosition||!a.options.seriesInteraction&&d.series!==k.series||(f=a.getDistXY(d,k),c=a.vectorLength(f)-(d.marker.radius+
k.marker.radius+e),0>c&&(d.degree+=.01,d.neighbours++,b=a.repulsiveForce(-c/Math.sqrt(d.neighbours),a.k,d,k)),a.force("repulsive",d,b*k.mass,f,k,c))})})},applyLimitBox:function(a){var b,d;this.options.splitSeries&&!a.isParentNode&&this.options.parentNodeLimit&&(b=this.getDistXY(a,a.series.parentNode),d=a.series.parentNodeRadius-a.marker.radius-this.vectorLength(b),0>d&&d>-2*a.marker.radius&&(a.plotX-=.01*b.x,a.plotY-=.01*b.y));t.prototype.applyLimitBox.apply(this,arguments)},isStable:function(){return.00001>
Math.abs(this.systemTemperature-this.prevSystemTemperature)||0>=this.temperature||0<this.systemTemperature&&.01>this.systemTemperature/this.nodes.length}});p("packedbubble","bubble",{minSize:"10%",maxSize:"50%",sizeBy:"area",zoneAxis:"y",tooltip:{pointFormat:"Value: {point.value}"},draggable:!0,useSimulation:!0,dataLabels:{formatter:function(){return this.point.value},parentNodeFormatter:function(){return this.name},parentNodeTextPath:{enabled:!0},padding:0},layoutAlgorithm:{initialPositions:"circle",
initialPositionRadius:20,bubblePadding:5,parentNodeLimit:!1,seriesInteraction:!0,dragBetweenSeries:!1,parentNodeOptions:{maxIterations:400,gravitationalConstant:.03,maxSpeed:50,initialPositionRadius:100,seriesInteraction:!0,marker:{fillColor:null,fillOpacity:1,lineWidth:1,lineColor:null,symbol:"circle"}},enableSimulation:!0,type:"packedbubble",integration:"packedbubble",maxIterations:1E3,splitSeries:!1,maxSpeed:5,gravitationalConstant:.01,friction:-.981}},{hasDraggableNodes:!0,forces:["barycenter",
"repulsive"],pointArrayMap:["value"],pointValKey:"value",isCartesian:!1,axisTypes:[],noSharedTooltip:!0,accumulateAllPoints:function(a){var b=a.chart,d=[],c,f;for(c=0;c<b.series.length;c++)if(a=b.series[c],a.visible||!b.options.chart.ignoreHiddenSeries)for(f=0;f<a.yData.length;f++)d.push([null,null,a.yData[f],a.index,f,{id:f,marker:{radius:0}}]);return d},init:function(){l.prototype.init.apply(this,arguments);g(this,"updatedData",function(){this.chart.series.forEach(function(a){a.type===this.type&&
(a.isDirty=!0)},this)});return this},render:function(){var b=[];l.prototype.render.apply(this,arguments);this.data.forEach(function(d){a.isArray(d.dataLabels)&&d.dataLabels.forEach(function(a){b.push(a)})});this.chart.hideOverlappingLabels(b)},setVisible:function(){var a=this;l.prototype.setVisible.apply(a,arguments);a.parentNodeLayout&&a.graph?a.visible?(a.graph.show(),a.parentNode.dataLabel&&a.parentNode.dataLabel.show()):(a.graph.hide(),a.parentNodeLayout.removeNode(a.parentNode),a.parentNode.dataLabel&&
a.parentNode.dataLabel.hide()):a.layout&&(a.visible?a.layout.addNodes(a.points):a.points.forEach(function(b){a.layout.removeNode(b)}))},drawDataLabels:function(){var a=this.options.dataLabels.textPath,b=this.points;l.prototype.drawDataLabels.apply(this,arguments);this.parentNode&&(this.parentNode.formatPrefix="parentNode",this.points=[this.parentNode],this.options.dataLabels.textPath=this.options.dataLabels.parentNodeTextPath,l.prototype.drawDataLabels.apply(this,arguments),this.points=b,this.options.dataLabels.textPath=
a)},calculateParentRadius:function(){var a;this.group&&(a=this.group.element.getBBox());this.parentNodeRadius=Math.min(Math.max(Math.sqrt(2*this.parentNodeMass/Math.PI)+20,20),a?Math.max(Math.sqrt(Math.pow(a.width,2)+Math.pow(a.height,2))/2+20,20):Math.sqrt(2*this.parentNodeMass/Math.PI)+20);this.parentNode&&(this.parentNode.marker.radius=this.parentNodeRadius)},drawGraph:function(){if(this.layout&&this.layout.options.splitSeries){var b=this.chart,f,e=this.layout.options.parentNodeOptions.marker,
e={fill:e.fillColor||c(this.color).brighten(.4).get(),opacity:e.fillOpacity,stroke:e.lineColor||this.color,"stroke-width":e.lineWidth};f=this.visible?"inherit":"hidden";this.parentNodesGroup||(this.parentNodesGroup=this.plotGroup("parentNodesGroup","parentNode",f,.1,b.seriesGroup),this.group.attr({zIndex:2}));this.calculateParentRadius();f=a.merge({x:this.parentNode.plotX-this.parentNodeRadius,y:this.parentNode.plotY-this.parentNodeRadius,width:2*this.parentNodeRadius,height:2*this.parentNodeRadius},
e);this.graph?this.graph.attr(f):this.graph=this.parentNode.graphic=b.renderer.symbol(e.symbol).attr(f).add(this.parentNodesGroup)}},createParentNodes:function(){var a=this,b=a.chart,c=a.parentNodeLayout,f,e=a.parentNode;a.parentNodeMass=0;a.points.forEach(function(b){a.parentNodeMass+=Math.PI*Math.pow(b.marker.radius,2)});a.calculateParentRadius();c.nodes.forEach(function(b){b.seriesIndex===a.index&&(f=!0)});c.setArea(0,0,b.plotWidth,b.plotHeight);f||(e||(e=(new w).init(this,{mass:a.parentNodeRadius/
2,marker:{radius:a.parentNodeRadius},dataLabels:{inside:!1},dataLabelOnNull:!0,degree:a.parentNodeRadius,isParentNode:!0,seriesIndex:a.index})),a.parentNode&&(e.plotX=a.parentNode.plotX,e.plotY=a.parentNode.plotY),a.parentNode=e,c.addSeries(a),c.addNodes([e]))},addSeriesLayout:function(){var b=this.options.layoutAlgorithm,c=this.chart.graphLayoutsStorage,f=this.chart.graphLayoutsLookup,e=a.merge(b,b.parentNodeOptions,{enableSimulation:this.layout.options.enableSimulation}),g;g=c[b.type+"-series"];
g||(c[b.type+"-series"]=g=new a.layouts[b.type],g.init(e),f.splice(g.index,0,g));this.parentNodeLayout=g;this.createParentNodes()},addLayout:function(){var b=this.options.layoutAlgorithm,c=this.chart.graphLayoutsStorage,f=this.chart.graphLayoutsLookup,e=this.chart.options.chart,g;c||(this.chart.graphLayoutsStorage=c={},this.chart.graphLayoutsLookup=f=[]);g=c[b.type];g||(b.enableSimulation=h(e.forExport)?!e.forExport:b.enableSimulation,c[b.type]=g=new a.layouts[b.type],g.init(b),f.splice(g.index,0,
g));this.layout=g;this.points.forEach(function(a){a.mass=2;a.degree=1;a.collisionNmb=1});g.setArea(0,0,this.chart.plotWidth,this.chart.plotHeight);g.addSeries(this);g.addNodes(this.points)},deferLayout:function(){var a=this.options.layoutAlgorithm;this.visible&&(this.addLayout(),a.splitSeries&&this.addSeriesLayout())},translate:function(){var b=this.chart,c=this.data,f=this.index,e,g,k,m,l=this.options.useSimulation;this.processedXData=this.xData;this.generatePoints();h(b.allDataPoints)||(b.allDataPoints=
this.accumulateAllPoints(this),this.getPointRadius());l?k=b.allDataPoints:(k=this.placeBubbles(b.allDataPoints),this.options.draggable=!1);for(m=0;m<k.length;m++)k[m][3]===f&&(e=c[k[m][4]],g=k[m][2],l||(e.plotX=k[m][0]-b.plotLeft+b.diffX,e.plotY=k[m][1]-b.plotTop+b.diffY),e.marker=a.extend(e.marker,{radius:g,width:2*g,height:2*g}));l&&this.deferLayout()},checkOverlap:function(a,b){var d=a[0]-b[0],c=a[1]-b[1];return-.001>Math.sqrt(d*d+c*c)-Math.abs(a[2]+b[2])},positionBubble:function(a,b,c){var d=
Math.sqrt,f=Math.asin,e=Math.acos,g=Math.pow,h=Math.abs,d=d(g(a[0]-b[0],2)+g(a[1]-b[1],2)),e=e((g(d,2)+g(c[2]+b[2],2)-g(c[2]+a[2],2))/(2*(c[2]+b[2])*d)),f=f(h(a[0]-b[0])/d);a=(0>a[1]-b[1]?0:Math.PI)+e+f*(0>(a[0]-b[0])*(a[1]-b[1])?1:-1);return[b[0]+(b[2]+c[2])*Math.sin(a),b[1]-(b[2]+c[2])*Math.cos(a),c[2],c[3],c[4]]},placeBubbles:function(a){var b=this.checkOverlap,d=this.positionBubble,c=[],f=1,e=0,g=0,h;h=[];var l;a=a.sort(function(a,b){return b[2]-a[2]});if(1===a.length)h=[0,0,a[0][0],a[0][1],a[0][2]];
else if(a.length){c.push([[0,0,a[0][2],a[0][3],a[0][4]]]);c.push([[0,0-a[1][2]-a[0][2],a[1][2],a[1][3],a[1][4]]]);for(l=2;l<a.length;l++)a[l][2]=a[l][2]||1,h=d(c[f][e],c[f-1][g],a[l]),b(h,c[f][0])?(c.push([]),g=0,c[f+1].push(d(c[f][e],c[f][0],a[l])),f++,e=0):1<f&&c[f-1][g+1]&&b(h,c[f-1][g+1])?(g++,c[f].push(d(c[f][e],c[f-1][g],a[l])),e++):(e++,c[f].push(h));this.chart.stages=c;this.chart.rawPositions=[].concat.apply([],c);this.resizeRadius();h=this.chart.rawPositions}return h},resizeRadius:function(){var a=
this.chart,b=a.rawPositions,c=Math.min,f=Math.max,e=a.plotLeft,g=a.plotTop,h=a.plotHeight,l=a.plotWidth,t,p,x,w,r,z;t=x=Number.POSITIVE_INFINITY;p=w=Number.NEGATIVE_INFINITY;for(z=0;z<b.length;z++)r=b[z][2],t=c(t,b[z][0]-r),p=f(p,b[z][0]+r),x=c(x,b[z][1]-r),w=f(w,b[z][1]+r);z=[p-t,w-x];c=c.apply([],[(l-e)/z[0],(h-g)/z[1]]);if(1e-10<Math.abs(c-1)){for(z=0;z<b.length;z++)b[z][2]*=c;this.placeBubbles(b)}else a.diffY=h/2+g-x-(w-x)/2,a.diffX=l/2+e-t-(p-t)/2},calculateZExtremes:function(){var d=this.options.zMin,
c=this.options.zMax,f=Infinity,e=-Infinity;if(d&&c)return[d,c];this.chart.series.forEach(function(b){b.yData.forEach(function(b){a.defined(b)&&(b>e&&(e=b),b<f&&(f=b))})});d=b(d,f);c=b(c,e);return[d,c]},getPointRadius:function(){var a=this,b=a.chart,c=a.options,f=c.useSimulation,e=Math.min(b.plotWidth,b.plotHeight),g={},h=[],l=b.allDataPoints,t,p,x,w,r;["minSize","maxSize"].forEach(function(a){var b=parseInt(c[a],10),d=/%$/.test(c[a]);g[a]=d?e*b/100:b*Math.sqrt(l.length)});b.minRadius=t=g.minSize/
Math.sqrt(l.length);b.maxRadius=p=g.maxSize/Math.sqrt(l.length);r=f?a.calculateZExtremes():[t,p];(l||[]).forEach(function(b,c){x=f?Math.max(Math.min(b[2],r[1]),r[0]):b[2];w=a.getRadius(r[0],r[1],t,p,x);0===w&&(w=null);l[c][2]=w;h.push(w)});a.radii=h},redrawHalo:x.redrawHalo,onMouseDown:x.onMouseDown,onMouseMove:x.onMouseMove,onMouseUp:function(b){if(b.fixedPosition&&!b.removed){var c,d,f=this.layout,e=this.parentNodeLayout;e&&f.options.dragBetweenSeries&&e.nodes.forEach(function(e){b&&b.marker&&e!==
b.series.parentNode&&(c=f.getDistXY(b,e),d=f.vectorLength(c)-e.marker.radius-b.marker.radius,0>d&&(e.series.addPoint(a.merge(b.options,{plotX:b.plotX,plotY:b.plotY}),!1),f.removeNode(b),b.remove()))});x.onMouseUp.apply(this,arguments)}},destroy:function(){this.parentNode&&(this.parentNodeLayout.removeNode(this.parentNode),this.parentNode.dataLabel&&(this.parentNode.dataLabel=this.parentNode.dataLabel.destroy()));a.Series.prototype.destroy.apply(this,arguments)},alignDataLabel:a.Series.prototype.alignDataLabel},
{destroy:function(){this.series.layout&&this.series.layout.removeNode(this);return e.prototype.destroy.apply(this,arguments)}});g(f,"beforeRedraw",function(){this.allDataPoints&&delete this.allDataPoints})});y(r,"parts-more/Polar.js",[r["parts/Globals.js"]],function(a){var p=a.pick,l=a.Series,e=a.seriesTypes,h=a.wrap,b=l.prototype,g=a.Pointer.prototype;b.searchPointByAngle=function(a){var b=this.chart,f=this.xAxis.pane.center;return this.searchKDTree({clientX:180+-180/Math.PI*Math.atan2(a.chartX-
f[0]-b.plotLeft,a.chartY-f[1]-b.plotTop)})};b.getConnectors=function(a,b,e,g){var c,d,f,h,l,t,k,m;d=g?1:0;c=0<=b&&b<=a.length-1?b:0>b?a.length-1+b:0;b=0>c-1?a.length-(1+d):c-1;d=c+1>a.length-1?d:c+1;f=a[b];d=a[d];h=f.plotX;f=f.plotY;l=d.plotX;t=d.plotY;d=a[c].plotX;c=a[c].plotY;h=(1.5*d+h)/2.5;f=(1.5*c+f)/2.5;l=(1.5*d+l)/2.5;k=(1.5*c+t)/2.5;t=Math.sqrt(Math.pow(h-d,2)+Math.pow(f-c,2));m=Math.sqrt(Math.pow(l-d,2)+Math.pow(k-c,2));h=Math.atan2(f-c,h-d);k=Math.PI/2+(h+Math.atan2(k-c,l-d))/2;Math.abs(h-
k)>Math.PI/2&&(k-=Math.PI);h=d+Math.cos(k)*t;f=c+Math.sin(k)*t;l=d+Math.cos(Math.PI+k)*m;k=c+Math.sin(Math.PI+k)*m;d={rightContX:l,rightContY:k,leftContX:h,leftContY:f,plotX:d,plotY:c};e&&(d.prevPointCont=this.getConnectors(a,b,!1,g));return d};b.toXY=function(a){var b,f=this.chart,e=a.plotX;b=a.plotY;a.rectPlotX=e;a.rectPlotY=b;b=this.xAxis.postTranslate(a.plotX,this.yAxis.len-b);a.plotX=a.polarPlotX=b.x-f.plotLeft;a.plotY=a.polarPlotY=b.y-f.plotTop;this.kdByAngle?(f=(e/Math.PI*180+this.xAxis.pane.options.startAngle)%
360,0>f&&(f+=360),a.clientX=f):a.clientX=a.plotX};e.spline&&(h(e.spline.prototype,"getPointSpline",function(a,b,e,g){this.chart.polar?g?(a=this.getConnectors(b,g,!0,this.connectEnds),a=["C",a.prevPointCont.rightContX,a.prevPointCont.rightContY,a.leftContX,a.leftContY,a.plotX,a.plotY]):a=["M",e.plotX,e.plotY]:a=a.call(this,b,e,g);return a}),e.areasplinerange&&(e.areasplinerange.prototype.getPointSpline=e.spline.prototype.getPointSpline));a.addEvent(l,"afterTranslate",function(){var b=this.chart,c,
e;if(b.polar){(this.kdByAngle=b.tooltip&&b.tooltip.shared)?this.searchPoint=this.searchPointByAngle:this.options.findNearestPointBy="xy";if(!this.preventPostTranslate)for(c=this.points,e=c.length;e--;)this.toXY(c[e]),!b.hasParallelCoordinates&&!this.yAxis.reversed&&c[e].y<this.yAxis.min&&(c[e].isNull=!0);this.hasClipCircleSetter||(this.hasClipCircleSetter=!!a.addEvent(this,"afterRender",function(){var c;b.polar&&(c=this.yAxis.center,this.group.clip(b.renderer.clipCircle(c[0],c[1],c[2]/2)),this.setClip=
a.noop)}))}},{order:2});h(b,"getGraphPath",function(a,b){var c=this,f,e,d;if(this.chart.polar){b=b||this.points;for(f=0;f<b.length;f++)if(!b[f].isNull){e=f;break}!1!==this.options.connectEnds&&void 0!==e&&(this.connectEnds=!0,b.splice(b.length,0,b[e]),d=!0);b.forEach(function(a){void 0===a.polarPlotY&&c.toXY(a)})}f=a.apply(this,[].slice.call(arguments,1));d&&b.pop();return f});l=function(a,b){var c=this.chart,f=this.options.animation,e=this.group,d=this.markerGroup,g=this.xAxis.center,h=c.plotLeft,
l=c.plotTop;c.polar?c.renderer.isSVG&&(!0===f&&(f={}),b?(a={translateX:g[0]+h,translateY:g[1]+l,scaleX:.001,scaleY:.001},e.attr(a),d&&d.attr(a)):(a={translateX:h,translateY:l,scaleX:1,scaleY:1},e.animate(a,f),d&&d.animate(a,f),this.animate=null)):a.call(this,b)};h(b,"animate",l);e.column&&(e=e.column.prototype,e.polarArc=function(a,b,e,g){var c=this.xAxis.center,d=this.yAxis.len;return this.chart.renderer.symbols.arc(c[0],c[1],d-b,null,{start:e,end:g,innerR:d-p(a,d)})},h(e,"animate",l),h(e,"translate",
function(a){var b=this.xAxis,f=b.startAngleRad,e,g,d;this.preventPostTranslate=!0;a.call(this);if(b.isRadial)for(e=this.points,d=e.length;d--;)g=e[d],a=g.barX+f,g.shapeType="path",g.shapeArgs={d:this.polarArc(g.yBottom,g.plotY,a,a+g.pointWidth)},this.toXY(g),g.tooltipPos=[g.plotX,g.plotY],g.ttBelow=g.plotY>b.center[1]}),h(e,"alignDataLabel",function(a,c,e,g,h,d){this.chart.polar?(a=c.rectPlotX/Math.PI*180,null===g.align&&(g.align=20<a&&160>a?"left":200<a&&340>a?"right":"center"),null===g.verticalAlign&&
(g.verticalAlign=45>a||315<a?"bottom":135<a&&225>a?"top":"middle"),b.alignDataLabel.call(this,c,e,g,h,d)):a.call(this,c,e,g,h,d)}));h(g,"getCoordinates",function(a,b){var c=this.chart,e={xAxis:[],yAxis:[]};c.polar?c.axes.forEach(function(a){var d=a.isXAxis,f=a.center,g=b.chartX-f[0]-c.plotLeft,f=b.chartY-f[1]-c.plotTop;e[d?"xAxis":"yAxis"].push({axis:a,value:a.translate(d?Math.PI-Math.atan2(g,f):Math.sqrt(Math.pow(g,2)+Math.pow(f,2)),!0)})}):e=a.call(this,b);return e});a.SVGRenderer.prototype.clipCircle=
function(b,c,e){var f=a.uniqueKey(),g=this.createElement("clipPath").attr({id:f}).add(this.defs);b=this.circle(b,c,e).add(g);b.id=f;b.clipPath=g;return b};a.addEvent(a.Chart,"getAxes",function(){this.pane||(this.pane=[]);a.splat(this.options.pane).forEach(function(b){new a.Pane(b,this)},this)});a.addEvent(a.Chart,"afterDrawChartBox",function(){this.pane.forEach(function(a){a.render()})});h(a.Chart.prototype,"get",function(b,c){return a.find(this.pane,function(a){return a.options.id===c})||b.call(this,
c)})});y(r,"masters/highcharts-more.src.js",[],function(){})});
//# sourceMappingURL=highcharts-more.js.map
...@@ -33,7 +33,8 @@ public class Function { ...@@ -33,7 +33,8 @@ public class Function {
private String resName; private String resName;
private String resUrl; private String resUrl;
private String imageURL; private String imageURL;
//暫時沒有imageURL,用本地資源代替
private int icRes;
/** /**
* 自定義字段 * 自定義字段
...@@ -55,9 +56,9 @@ public class Function { ...@@ -55,9 +56,9 @@ public class Function {
private int textSizeRes; private int textSizeRes;
@Generated(hash = 1165180133) @Generated(hash = 816556116)
public Function(Long dbid, @NotNull Long id, int parentId, int groupId, int status, public Function(Long dbid, @NotNull Long id, int parentId, int groupId, int status,
long effectiveTime, String resName, String resUrl, String imageURL) { long effectiveTime, String resName, String resUrl, String imageURL, int icRes) {
this.dbid = dbid; this.dbid = dbid;
this.id = id; this.id = id;
this.parentId = parentId; this.parentId = parentId;
...@@ -67,6 +68,7 @@ public class Function { ...@@ -67,6 +68,7 @@ public class Function {
this.resName = resName; this.resName = resName;
this.resUrl = resUrl; this.resUrl = resUrl;
this.imageURL = imageURL; this.imageURL = imageURL;
this.icRes = icRes;
} }
@Generated(hash = 133141990) @Generated(hash = 133141990)
...@@ -90,12 +92,12 @@ public class Function { ...@@ -90,12 +92,12 @@ public class Function {
this.textSize = textSize; this.textSize = textSize;
} }
public Function(Long id, int parentId, int groupId, String resName, int nameRes) { public Function(Long id, int parentId, int groupId, String resName, int icRes) {
this.id = id; this.id = id;
this.parentId = parentId; this.parentId = parentId;
this.groupId = groupId; this.groupId = groupId;
this.resName = resName; this.resName = resName;
this.nameRes = nameRes; this.icRes = icRes;
} }
public Function(int nameRes, int textColorRes, int backgroundColorRes, int textSizeRes) { public Function(int nameRes, int textColorRes, int backgroundColorRes, int textSizeRes) {
...@@ -250,4 +252,12 @@ public class Function { ...@@ -250,4 +252,12 @@ public class Function {
public void setGroupId(int groupId) { public void setGroupId(int groupId) {
this.groupId = groupId; this.groupId = groupId;
} }
public int getIcRes() {
return this.icRes;
}
public void setIcRes(int icRes) {
this.icRes = icRes;
}
} }
...@@ -33,6 +33,7 @@ public class FunctionDao extends AbstractDao<Function, Long> { ...@@ -33,6 +33,7 @@ public class FunctionDao extends AbstractDao<Function, Long> {
public final static Property ResName = new Property(6, String.class, "resName", false, "RES_NAME"); public final static Property ResName = new Property(6, String.class, "resName", false, "RES_NAME");
public final static Property ResUrl = new Property(7, String.class, "resUrl", false, "RES_URL"); public final static Property ResUrl = new Property(7, String.class, "resUrl", false, "RES_URL");
public final static Property ImageURL = new Property(8, String.class, "imageURL", false, "IMAGE_URL"); public final static Property ImageURL = new Property(8, String.class, "imageURL", false, "IMAGE_URL");
public final static Property IcRes = new Property(9, int.class, "icRes", false, "IC_RES");
} }
...@@ -56,7 +57,8 @@ public class FunctionDao extends AbstractDao<Function, Long> { ...@@ -56,7 +57,8 @@ public class FunctionDao extends AbstractDao<Function, Long> {
"\"EFFECTIVE_TIME\" INTEGER NOT NULL ," + // 5: effectiveTime "\"EFFECTIVE_TIME\" INTEGER NOT NULL ," + // 5: effectiveTime
"\"RES_NAME\" TEXT," + // 6: resName "\"RES_NAME\" TEXT," + // 6: resName
"\"RES_URL\" TEXT," + // 7: resUrl "\"RES_URL\" TEXT," + // 7: resUrl
"\"IMAGE_URL\" TEXT);"); // 8: imageURL "\"IMAGE_URL\" TEXT," + // 8: imageURL
"\"IC_RES\" INTEGER NOT NULL );"); // 9: icRes
} }
/** Drops the underlying database table. */ /** Drops the underlying database table. */
...@@ -93,6 +95,7 @@ public class FunctionDao extends AbstractDao<Function, Long> { ...@@ -93,6 +95,7 @@ public class FunctionDao extends AbstractDao<Function, Long> {
if (imageURL != null) { if (imageURL != null) {
stmt.bindString(9, imageURL); stmt.bindString(9, imageURL);
} }
stmt.bindLong(10, entity.getIcRes());
} }
@Override @Override
...@@ -123,6 +126,7 @@ public class FunctionDao extends AbstractDao<Function, Long> { ...@@ -123,6 +126,7 @@ public class FunctionDao extends AbstractDao<Function, Long> {
if (imageURL != null) { if (imageURL != null) {
stmt.bindString(9, imageURL); stmt.bindString(9, imageURL);
} }
stmt.bindLong(10, entity.getIcRes());
} }
@Override @Override
...@@ -141,7 +145,8 @@ public class FunctionDao extends AbstractDao<Function, Long> { ...@@ -141,7 +145,8 @@ public class FunctionDao extends AbstractDao<Function, Long> {
cursor.getLong(offset + 5), // effectiveTime cursor.getLong(offset + 5), // effectiveTime
cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6), // resName cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6), // resName
cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7), // resUrl cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7), // resUrl
cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8) // imageURL cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8), // imageURL
cursor.getInt(offset + 9) // icRes
); );
return entity; return entity;
} }
...@@ -157,6 +162,7 @@ public class FunctionDao extends AbstractDao<Function, Long> { ...@@ -157,6 +162,7 @@ public class FunctionDao extends AbstractDao<Function, Long> {
entity.setResName(cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6)); entity.setResName(cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6));
entity.setResUrl(cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7)); entity.setResUrl(cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7));
entity.setImageURL(cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8)); entity.setImageURL(cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8));
entity.setIcRes(cursor.getInt(offset + 9));
} }
@Override @Override
......
/**
// AAChartModel.java
// AAChartCore
//
// Created by AnAn on 2017/9/5.
// Copyright © 2018年 An An. All rights reserved.
* ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ ...... SOURCE CODE ......◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
* ◉◉◉................................................... ◉◉◉
* ◉◉◉ https://github.com/AAChartModel/AAChartCore ◉◉◉
* ◉◉◉ https://github.com/AAChartModel/AAChartCore-Kotlin ◉◉◉
* ◉◉◉................................................... ◉◉◉
* ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ ...... SOURCE CODE ......◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
* -------------------------------------------------------------------------------
*
* 🌕 🌖 🌗 🌘 ❀❀❀ WARM TIPS!!! ❀❀❀ 🌑 🌒 🌓 🌔
*
* Please contact me on GitHub,if there are any problems encountered in use.
* GitHub Issues : https://github.com/AAChartModel/AAChartCore/issues
* -------------------------------------------------------------------------------
* And if you want to contribute for this project, please contact me as well
* GitHub : https://github.com/AAChartModel
* StackOverflow : https://stackoverflow.com/users/7842508/codeforu
* JianShu : http://www.jianshu.com/u/f1e6753d4254
* SegmentFault : https://segmentfault.com/u/huanghunbieguan
*
* -------------------------------------------------------------------------------
*/
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartAnimationType;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartStackingType;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartSymbolStyleType;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartType;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartZoomType;
public class AAChartModel {
public String animationType; //动画类型
public Integer animationDuration; //动画时间
public String title; //标题内容
public String titleFontColor; //标题字体颜色
public Float titleFontSize; //标题字体大小
public String titleFontWeight; //标题字体粗细
public String subtitle; //副标题内容
public String subtitleAlign;
public String subtitleFontColor; //副标题字体颜色
public Float subtitleFontSize; //副标题字体大小
public String subtitleFontWeight; //副标题字体粗细
public String axesTextColor; //x 轴和 y 轴文字颜色
public float axesTextSize; //x 轴和 y 轴文字大小
public String chartType; //图表类型
public String stacking; //堆积样式
public String markerSymbol; //折线曲线连接点的类型:"circle", "square", "diamond", "triangle","triangle-down",默认是"circle"
public String markerSymbolStyle;
public String zoomType; //缩放类型 AAChartZoomTypeX表示可沿着 x 轴进行手势缩放
public Boolean inverted; //x 轴是否翻转(垂直)
public Boolean xAxisReversed; //x 轴翻转
public Boolean yAxisReversed; //y 轴翻转
public Boolean tooltipEnabled; //是否显示浮动提示框(默认显示)
public String tooltipValueSuffix; //浮动提示框单位后缀
public Boolean tooltipCrosshairs; //是否显示准星线(默认显示)
public Boolean gradientColorEnable; //是否要为渐变色
public Boolean polar; //是否极化图形(变为雷达图)
public Float marginLeft;
public Float marginRight;
public Boolean dataLabelsEnabled; //是否显示数据
public String dataLabelsFontColor;
public Float dataLabelsFontSize;
public String dataLabelsFontWeight;
public Boolean xAxisLabelsEnabled; //x轴是否显示数据
public Integer xAxisTickInterval;
public Integer yAxisTickInterval;
public String gridLineDashStyle; //x轴网格线样式
public String gridLineColor; //x轴网格线顏色
public String tickPosition; //刻度线相对于轴线的位置,可用的值有 inside 和 outside,分别表示在轴线的内部和外部。 默认是:outside.
public String[]categories; //x轴是否显示数据
public Float xAxisGridLineWidth; //x轴网格线的宽度
public Boolean xAxisVisible; //x 轴是否显示
public Boolean yAxisVisible; //y 轴是否显示
public Boolean yAxisLabelsEnabled; //y轴是否显示数据
public String yAxisTitle; //y轴标题
public Float yAxisLineWidth; //y 轴轴线的宽度
public Float xAxisLineWidth; //x 轴轴线的宽度
public String yAxisLineColor; //y 轴轴线的顏色
public Float yAxisMin;
public Float yAxisMax;
public Boolean yAxisAllowDecimals; //允許小數
public Float yAxisGridLineWidth; //y轴网格线的宽度
public Object[]colorsTheme; //图表主题颜色数组
public Boolean legendEnabled; //是否显示图例
public Object backgroundColor; //图表背景色
public Float borderRadius; //柱状图长条图头部圆角半径(可用于设置头部的形状,仅对条形图,柱状图有效)
public Float markerRadius; //折线连接点的半径长度
public Object[] series;
public Boolean touchEventEnabled; //是否支持用户触摸事件
public AAChartModel animationType(String prop) {
animationType = prop;
return this;
}
public AAChartModel animationDuration(Integer prop) {
animationDuration = prop;
return this;
}
public AAChartModel title(String prop) {
title = prop;
return this;
}
public AAChartModel titleFontColor(String prop) {
titleFontColor = prop;
return this;
}
public AAChartModel titleFontSize(Float prop) {
titleFontSize = prop;
return this;
}
public AAChartModel titleFontWeight(String prop) {
titleFontWeight = prop;
return this;
}
public AAChartModel subtitle(String prop) {
subtitle = prop;
return this;
}
public AAChartModel subtitleAlign(String prop) {
subtitleAlign = prop;
return this;
}
public AAChartModel subtitleFontColor(String prop) {
subtitleFontColor = prop;
return this;
}
public AAChartModel subtitleFontSize(Float prop) {
subtitleFontSize = prop;
return this;
}
public AAChartModel subtitleFontWeight(String prop) {
subtitleFontWeight = prop;
return this;
}
public AAChartModel axesTextColor(String prop) {
axesTextColor = prop;
return this;
}
public AAChartModel axesTextSize(float prop) {
axesTextSize = prop;
return this;
}
public AAChartModel chartType(String prop) {
chartType = prop;
return this;
}
public AAChartModel stacking(String prop) {
stacking = prop;
return this;
}
public AAChartModel markerSymbol(String prop) {
markerSymbol = prop;
return this;
}
public AAChartModel markerSymbolStyle(String prop) {
markerSymbolStyle = prop;
return this;
}
public AAChartModel zoomType(String prop) {
zoomType = prop;
return this;
}
public AAChartModel inverted(Boolean prop) {
inverted = prop;
return this;
}
public AAChartModel xAxisReversed(Boolean prop) {
xAxisReversed = prop;
return this;
}
public AAChartModel yAxisReversed(Boolean prop) {
yAxisReversed = prop;
return this;
}
public AAChartModel tooltipEnabled(Boolean prop) {
tooltipEnabled = prop;
return this;
}
public AAChartModel tooltipValueSuffixSet(String prop) {
tooltipValueSuffix = prop;
return this;
}
public AAChartModel tooltipCrosshairs(Boolean prop) {
tooltipCrosshairs = prop;
return this;
}
public AAChartModel gradientColorEnable(Boolean prop) {
gradientColorEnable = prop;
return this;
}
public AAChartModel polar(Boolean prop) {
polar = prop;
return this;
}
public AAChartModel marginLeft(Float prop) {
marginLeft = prop;
return this;
}
public AAChartModel marginRight(Float prop) {
marginRight = prop;
return this;
}
public AAChartModel dataLabelsEnabled(Boolean prop) {
dataLabelsEnabled = prop;
return this;
}
public AAChartModel dataLabelsFontColor(String prop) {
dataLabelsFontColor = prop;
return this;
}
public AAChartModel dataLabelsFontSize(Float prop) {
dataLabelsFontSize = prop;
return this;
}
public AAChartModel dataLabelsFontWeight(String prop) {
dataLabelsFontWeight = prop;
return this;
}
public AAChartModel xAxisLabelsEnabled(Boolean prop) {
xAxisLabelsEnabled = prop;
return this;
}
public AAChartModel xAxisTickInterval(Integer prop) {
xAxisTickInterval = prop;
return this;
}
public AAChartModel yAxisTickInterval(Integer prop) {
yAxisTickInterval = prop;
return this;
}
public AAChartModel gridLineDashStyle(String LineStyle) {
gridLineDashStyle = LineStyle;
return this;
}
public AAChartModel gridLineColor(String lineColor) {
gridLineColor = lineColor;
return this;
}
public AAChartModel tickPosition(String tickPosition) {
this.tickPosition = tickPosition;
return this;
}
public AAChartModel categories(String[] prop) {
categories = prop;
return this;
}
public AAChartModel xAxisGridLineWidth(Float prop) {
xAxisGridLineWidth = prop;
return this;
}
public AAChartModel yAxisGridLineWidth(Float prop) {
yAxisGridLineWidth = prop;
return this;
}
public AAChartModel xAxisVisible(Boolean prop) {
xAxisVisible = prop;
return this;
}
public AAChartModel yAxisVisible(Boolean prop) {
yAxisVisible = prop;
return this;
}
public AAChartModel yAxisLabelsEnabled(Boolean prop) {
yAxisLabelsEnabled = prop;
return this;
}
public AAChartModel yAxisTitle(String prop) {
yAxisTitle = prop;
return this;
}
public AAChartModel yAxisLineWidth(Float prop) {
yAxisLineWidth = prop;
return this;
}
public AAChartModel xAxisLineWidth(Float prop) {
xAxisLineWidth = prop;
return this;
}
public AAChartModel yAxisLineColor(String color) {
yAxisLineColor = color;
return this;
}
public AAChartModel yAxisMin(Float prop) {
yAxisMin = prop;
return this;
}
public AAChartModel yAxisMax(Float prop) {
yAxisMax = prop;
return this;
}
public AAChartModel yAxisAllowDecimals(Boolean prop) {
yAxisAllowDecimals = prop;
return this;
}
public AAChartModel colorsTheme(Object[] prop) {
colorsTheme = prop;
return this;
}
public AAChartModel legendEnabled(Boolean prop) {
legendEnabled = prop;
return this;
}
public AAChartModel backgroundColor(Object prop) {
backgroundColor = prop;
return this;
}
public AAChartModel borderRadius(Float prop) {
borderRadius = prop;
return this;
}
public AAChartModel markerRadius(Float prop) {
markerRadius = prop;
return this;
}
public AAChartModel series(Object[] prop) {
series = prop;
return this;
}
public AAChartModel touchEventEnabled(Boolean prop) {
touchEventEnabled = prop;
return this;
}
public AAChartModel() {
chartType = AAChartType.Line;
animationDuration = 500;//以毫秒为单位
animationType = AAChartAnimationType.Linear;
inverted = false;
stacking = AAChartStackingType.False;
xAxisReversed = false;
yAxisReversed = false;
zoomType = AAChartZoomType.None;
dataLabelsEnabled = false;
markerSymbolStyle = AAChartSymbolStyleType.Normal;
colorsTheme = new String[]{"#fe117c","#ffc069","#06caf4","#7dffc0"};//默认的颜色数组(必须要添加默认数组,否则就会出错)
tooltipCrosshairs = true;
gradientColorEnable = false;
polar = false;
xAxisLabelsEnabled = true;
xAxisGridLineWidth = 0f;
yAxisLabelsEnabled = true;
yAxisGridLineWidth = 1f;
legendEnabled = true;
backgroundColor = "#ffffff";
borderRadius = 0f;//柱状图长条图头部圆角半径(可用于设置头部的形状,仅对条形图,柱状图有效,设置为1000时,柱形图或者条形图头部为楔形)
markerRadius = 6f;//折线连接点的半径长度,如果值设置为0,这样就相当于不显示了
titleFontColor = "#000000";//标题字体颜色为黑色
titleFontWeight = "regular";//常规字体
titleFontSize = 11f;
subtitleFontColor = "#000000";//副标题字体颜色为黑色
subtitleFontWeight = "regular";//常规字体
subtitleFontSize = 9f;
dataLabelsFontColor = "#000000";//数据标签默认颜色为黑色
dataLabelsFontWeight = "bold";//图表的数据字体为粗体
dataLabelsFontSize = 10f;
}
}
/**
// AAChartModel.java
// AAChartCore
//
// Created by AnAn on 2017/9/8..
// Copyright © 2018年 An An. All rights reserved.
* ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ ...... SOURCE CODE ......◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
* ◉◉◉................................................... ◉◉◉
* ◉◉◉ https://github.com/AAChartModel/AAChartCore ◉◉◉
* ◉◉◉ https://github.com/AAChartModel/AAChartCore-Kotlin ◉◉◉
* ◉◉◉................................................... ◉◉◉
* ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ ...... SOURCE CODE ......◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
* -------------------------------------------------------------------------------
*
* 🌕 🌖 🌗 🌘 ❀❀❀ WARM TIPS!!! ❀❀❀ 🌑 🌒 🌓 🌔
*
* Please contact me on GitHub,if there are any problems encountered in use.
* GitHub Issues : https://github.com/AAChartModel/AAChartCore/issues
* -------------------------------------------------------------------------------
* And if you want to contribute for this project, please contact me as well
* GitHub : https://github.com/AAChartModel
* StackOverflow : https://stackoverflow.com/users/7842508/codeforu
* JianShu : http://www.jianshu.com/u/f1e6753d4254
* SegmentFault : https://segmentfault.com/u/huanghunbieguan
*
* -------------------------------------------------------------------------------
*/
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.webkit.JavascriptInterface;
import android.webkit.JsResult;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAOptions;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AATools.AAJSStringPurer;
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
import java.util.HashMap;
import java.util.Map;
public class AAChartView extends WebView {
public interface AAChartViewCallBack {
void chartViewDidFinishLoad(AAChartView aaChartView);
void chartViewMoveOverEventMessage(
AAChartView aaChartView,
AAMoveOverEventMessageModel messageModel
);
}
public Float contentWidth;
public Float contentHeight;
public Boolean chartSeriesHidden;
public Boolean isClearBackgroundColor;
public AAChartViewCallBack callBack;
public void setContentWidth(Float contentWidth) {
this.contentWidth = contentWidth;
String jsStr = "setTheChartViewContentWidth('"
+ this.contentWidth + "')";
safeEvaluateJavaScriptString(jsStr);
}
public void setContentHeight(Float contentHeight) {
this.contentHeight = contentHeight;
String jsStr = "setTheChartViewContentHeight('"
+ this.contentHeight + "')";
safeEvaluateJavaScriptString(jsStr);
}
public void setChartSeriesHidden(Boolean chartSeriesHidden) {
this.chartSeriesHidden = chartSeriesHidden;
String jsStr = "setChartSeriesHidden('"
+ this.chartSeriesHidden + "')";
safeEvaluateJavaScriptString(jsStr);
}
public void setIsClearBackgroundColor(Boolean isClearBackgroundColor) {
this.isClearBackgroundColor = isClearBackgroundColor;
if (this.isClearBackgroundColor) {
this.setBackgroundColor(0);
this.getBackground().setAlpha(0);
} else {
this.setBackgroundColor(1);
this.getBackground().setAlpha(255);
}
}
private String optionsJson;
public AAChartView(
Context context
) {
super(context);
setupBasicContent();
}
public AAChartView(
Context context,
AttributeSet attrs
) {
super(context, attrs);
setupBasicContent();
}
public AAChartView(
Context context,
AttributeSet attrs,
int defStyleAttr
) {
super(context, attrs, defStyleAttr);
setupBasicContent();
}
private void setupBasicContent() {
// Do some initialize work.
this.contentWidth = 420f;
this.contentHeight = 580f;
this.isClearBackgroundColor = false;
this.getSettings().setJavaScriptEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
this.setWebContentsDebuggingEnabled(true);
}
//把当前对象作为androidObject别名传递给js
//js通过window.androidObject.androidMethod()就可以直接调用安卓的androidMethod方法
this.addJavascriptInterface(this, "androidObject");
}
//js调用安卓,必须加@JavascriptInterface注释的方法才可以被js调用
@JavascriptInterface
public String androidMethod(String message) {
Gson gson = new Gson();
Map messageBody = new HashMap<String, Object>();
messageBody = gson.fromJson(message, messageBody.getClass());
AAMoveOverEventMessageModel eventMessageModel = getEventMessageModel(messageBody);
if (callBack != null) {
callBack.chartViewMoveOverEventMessage(this,eventMessageModel);
}
// Log.i("androidMethod","++++++++++++++++显示总共调用了几次");
return "";
}
public void aa_drawChartWithChartModel(final AAChartModel chartModel) {
AAOptions aaOptions = AAOptionsConstructor.configureChartOptions(chartModel);
this.aa_drawChartWithChartOptions(aaOptions);
}
public void aa_refreshChartWithChartModel(AAChartModel chartModel) {
AAOptions aaOptions = AAOptionsConstructor.configureChartOptions(chartModel);
this.aa_refreshChartWithChartOptions(aaOptions);
}
public void aa_drawChartWithChartOptions(final AAOptions chartOptions) {
if (this.optionsJson != null) {
this.aa_refreshChartWithChartOptions(chartOptions);
} else {
this.loadLocalFilesAndDrawChart(chartOptions);
this.showJavaScriptAlertView();
}
}
public void aa_refreshChartWithChartOptions(AAOptions chartOptions) {
configureChartOptionsAndDrawChart(chartOptions);
}
public void aa_onlyRefreshTheChartDataWithChartOptionsSeriesArray(
AASeriesElement[] seriesElementsArr
) {
aa_onlyRefreshTheChartDataWithChartOptionsSeriesArray(seriesElementsArr,true);
}
public void aa_onlyRefreshTheChartDataWithChartOptionsSeriesArray(
AASeriesElement[] seriesElementsArr,
Boolean animation
) {
String seriesArr = new Gson().toJson(seriesElementsArr);
String javaScriptStr = "onlyRefreshTheChartDataWithSeries('"
+ seriesArr + "','" + animation + "')";
this.safeEvaluateJavaScriptString(javaScriptStr);
}
public void aa_updateChartWithOptions(
Object options,
Boolean redraw
) {
String classNameStr = options.getClass().getSimpleName();
classNameStr = classNameStr.replace("AA","");
//convert fist character to be lowercase string
String firstChar = classNameStr.substring(0,1);
String lowercaseFirstStr = firstChar.toLowerCase();
classNameStr = classNameStr.substring(1);
String finalClassName = lowercaseFirstStr + classNameStr;
Map finalOptionsMap = new HashMap();
finalOptionsMap.put(finalClassName,options);
String optionsStr = new Gson().toJson(finalOptionsMap);
String javaScriptStr = "updateChart('" + optionsStr + "','" + redraw + "')";
this.safeEvaluateJavaScriptString(javaScriptStr);
}
public void aa_addPointToChartSeriesElement(
Integer elementIndex,
Object options
) {
aa_addPointToChartSeriesElement(
elementIndex,
options,
true);
}
public void aa_addPointToChartSeriesElement(
Integer elementIndex,
Object options,
Boolean shift
) {
aa_addPointToChartSeriesElement(
elementIndex,
options,
true,
shift,
true);
}
public void aa_addPointToChartSeriesElement(
Integer elementIndex,
Object options,
Boolean redraw,
Boolean shift,
Boolean animation
) {
String optionsStr;
if ( options instanceof Integer
|| options instanceof Float
|| options instanceof Double) {
optionsStr = String.valueOf(options);
} else {
optionsStr = new Gson().toJson(options);
}
String javaScriptStr = "addPointToChartSeries('"
+ elementIndex + "','"
+ optionsStr + "','"
+ redraw + "','"
+ shift + "','"
+ animation + "')";
this.safeEvaluateJavaScriptString(javaScriptStr);
}
public void aa_showTheSeriesElementContent(Integer elementIndex) {
String javaScriptStr = "showTheSeriesElementContentWithIndex('"
+ elementIndex + "')";
this.safeEvaluateJavaScriptString(javaScriptStr);
}
public void aa_hideTheSeriesElementContent(Integer elementIndex) {
String javaScriptStr = "hideTheSeriesElementContentWithIndex('"
+ elementIndex + "')";
this.safeEvaluateJavaScriptString(javaScriptStr);
}
public void aa_addElementToChartSeries(AASeriesElement aaSeriesElement) {
String pureElementJsonStr = new Gson().toJson(aaSeriesElement);
String javaScriptStr = "addElementToChartSeriesWithElement('"
+ pureElementJsonStr + "')";
this.safeEvaluateJavaScriptString(javaScriptStr);
}
public void aa_removeElementFromChartSeries(Integer elementIndex) {
String javaScriptStr = "removeElementFromChartSeriesWithElementIndex('"
+ elementIndex + "')";
this.safeEvaluateJavaScriptString(javaScriptStr);
}
public void aa_evaluateTheJavaScriptStringFunction(String jsFunctionStr) {
String pureJSFunctionStr = AAJSStringPurer.pureJavaScriptFunctionString(jsFunctionStr);
String jsFunctionNameStr = "evaluateTheJavaScriptStringFunction('"
+ pureJSFunctionStr + "')";
safeEvaluateJavaScriptString(jsFunctionNameStr);
}
private void loadLocalFilesAndDrawChart(final AAOptions aaOptions) {
this.loadUrl("file:///android_asset/AAChartView.html");
this.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
// Log.i("js files load","图表加载完成!!!!!!!! ");
configureChartOptionsAndDrawChart(aaOptions);
if (callBack != null) {
callBack.chartViewDidFinishLoad(AAChartView.this);
}
}
});
}
private void configureChartOptionsAndDrawChart(AAOptions chartOptions) {
if (isClearBackgroundColor) {
chartOptions.chart.backgroundColor("rgba(0,0,0,0)");
}
Gson gson = new Gson();
String aaOptionsJsonStr = gson.toJson(chartOptions);
this.optionsJson = aaOptionsJsonStr;
String javaScriptStr = "loadTheHighChartView('"
+ aaOptionsJsonStr + "','"
+ this.contentWidth + "','"
+ this.contentHeight + "')";
this.safeEvaluateJavaScriptString(javaScriptStr);
}
private void showJavaScriptAlertView() {
this.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsAlert(WebView view,
String url,
String message,
final JsResult result) {
super.onJsAlert(view, url, message, result);
String urlStr = "url --->" + url + "\n\n\n";
String messageStr = "message --->" + message + "\n\n\n";
String resultStr = "result --->" + result;
String alertMessageStr = urlStr + messageStr + resultStr;
new AlertDialog.Builder(getContext())
.setTitle("JavaScript alert Information")//设置对话框标题
.setMessage(alertMessageStr)
.setNeutralButton("sure",null)
.show();
return true;
}
});
}
private AAMoveOverEventMessageModel getEventMessageModel(Map messageBody) {
AAMoveOverEventMessageModel eventMessageModel = new AAMoveOverEventMessageModel();
eventMessageModel.name = messageBody.get("name").toString();
eventMessageModel.x = (Double) messageBody.get("x");
eventMessageModel.y = (Double) messageBody.get("y");
eventMessageModel.category = messageBody.get("category").toString();
eventMessageModel.offset = (LinkedTreeMap) messageBody.get("offset");
Double index = (Double) messageBody.get("index");
eventMessageModel.index = index.intValue();
return eventMessageModel;
}
private void safeEvaluateJavaScriptString(String javaScriptString) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
this.evaluateJavascript("javascript:"+javaScriptString, new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
// Log.i("call back information","输出打印查看回调的结果"+s);
}
});
} else {
this.loadUrl("javascript:"+javaScriptString);
}
}
}
/**
* ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ ...... SOURCE CODE ......◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
* ◉◉◉................................................... ◉◉◉
* ◉◉◉ https://github.com/AAChartModel/AAChartCore ◉◉◉
* ◉◉◉ https://github.com/AAChartModel/AAChartCore-Kotlin ◉◉◉
* ◉◉◉................................................... ◉◉◉
* ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ ...... SOURCE CODE ......◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
* -------------------------------------------------------------------------------
*
* 🌕 🌖 🌗 🌘 ❀❀❀ WARM TIPS!!! ❀❀❀ 🌑 🌒 🌓 🌔
*
* Please contact me on GitHub,if there are any problems encountered in use.
* GitHub Issues : https://github.com/AAChartModel/AAChartCore/issues
* -------------------------------------------------------------------------------
* And if you want to contribute for this project, please contact me as well
* GitHub : https://github.com/AAChartModel
* StackOverflow : https://stackoverflow.com/users/7842508/codeforu
* JianShu : http://www.jianshu.com/u/f1e6753d4254
* SegmentFault : https://segmentfault.com/u/huanghunbieguan
*
* -------------------------------------------------------------------------------
*/
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger;
import com.google.gson.internal.LinkedTreeMap;
public class AAMoveOverEventMessageModel {
public String name;
public Double x;
public Double y;
public String category;
public LinkedTreeMap offset;
public Integer index;
}
/**
* // AAOptionsConstructor.java
* // AAChartCore
* //
* // Created by AnAn on 2018/12/08.
* // Copyright © 2018年 An An. All rights reserved.
* /**
* ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ ...... SOURCE CODE ......◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
* ◉◉◉................................................... ◉◉◉
* ◉◉◉ https://github.com/AAChartModel/AAChartCore ◉◉◉
* ◉◉◉ https://github.com/AAChartModel/AAChartCore-Kotlin ◉◉◉
* ◉◉◉................................................... ◉◉◉
* ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ ...... SOURCE CODE ......◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
* <p>
* <p>
* -------------------------------------------------------------------------------
* <p>
* 🌕 🌖 🌗 🌘 ❀❀❀ WARM TIPS!!! ❀❀❀ 🌑 🌒 🌓 🌔
* <p>
* Please contact me on GitHub,if there are any problems encountered in use.
* GitHub Issues : https://github.com/AAChartModel/AAChartCore/issues
* -------------------------------------------------------------------------------
* And if you want to contribute for this project, please contact me as well
* GitHub : https://github.com/AAChartModel
* StackOverflow : https://stackoverflow.com/users/7842508/codeforu
* JianShu : http://www.jianshu.com/u/f1e6753d4254
* SegmentFault : https://segmentfault.com/u/huanghunbieguan
* <p>
* -------------------------------------------------------------------------------
*/
/**
* -------------------------------------------------------------------------------
*
* 🌕 🌖 🌗 🌘 ❀❀❀ WARM TIPS!!! ❀❀❀ 🌑 🌒 🌓 🌔
*
* Please contact me on GitHub,if there are any problems encountered in use.
* GitHub Issues : https://github.com/AAChartModel/AAChartCore/issues
* -------------------------------------------------------------------------------
* And if you want to contribute for this project, please contact me as well
* GitHub : https://github.com/AAChartModel
* StackOverflow : https://stackoverflow.com/users/7842508/codeforu
* JianShu : http://www.jianshu.com/u/f1e6753d4254
* SegmentFault : https://segmentfault.com/u/huanghunbieguan
*
* -------------------------------------------------------------------------------
*/
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartAnimationType;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartSymbolStyleType;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartType;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAAnimation;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAArea;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAArearange;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAAreaspline;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AABar;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAChart;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAColumn;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAColumnrange;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AADataLabels;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAItemStyle;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AALabels;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AALegend;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AALine;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAMarker;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAOptions;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAPie;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAPlotOptions;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AASeries;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AASpline;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAStyle;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AASubtitle;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AATitle;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AATooltip;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAXAxis;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAYAxis;
public class AAOptionsConstructor {
public static AAOptions configureChartOptions(
AAChartModel aaChartModel
) {
AAChart aaChart = new AAChart()
.type(aaChartModel.chartType) //绘图类型
.inverted(aaChartModel.inverted) //设置是否反转坐标轴,使X轴垂直,Y轴水平。 如果值为 true,则 x 轴默认是 倒置 的。 如果图表中出现条形图系列,则会自动反转
.backgroundColor(aaChartModel.backgroundColor) //设置图表的背景色(包含透明度的设置)
.pinchType(aaChartModel.zoomType) //设置手势缩放方向
.panning(true) //设置手势缩放后是否可平移
.polar(aaChartModel.polar) //是否极化图表(开启极坐标模式)
.marginLeft(aaChartModel.marginLeft) //图表左边距
.marginRight(aaChartModel.marginRight) //图表右边距
;
AATitle aaTitle = new AATitle()
.text(aaChartModel.title) //标题文本内容
.style(new AAStyle()
.color(aaChartModel.titleFontColor) //Title font color
.fontSize(aaChartModel.titleFontSize) //Title font size
.fontWeight(aaChartModel.titleFontWeight) //Title font weight
);
AASubtitle aaSubtitle = new AASubtitle()
.text(aaChartModel.subtitle) //副标题内容
.align(aaChartModel.subtitleAlign) //图表副标题文本水平对齐方式。可选的值有 “left”,”center“和“right”。 默认是:center.
.style(new AAStyle()
.color(aaChartModel.subtitleFontColor) //Subtitle font color
.fontSize(aaChartModel.subtitleFontSize) //Subtitle font size
.fontWeight(aaChartModel.subtitleFontWeight) //Subtitle font weight
);
AATooltip aaTooltip = new AATooltip()
.enabled(aaChartModel.tooltipEnabled) //启用浮动提示框
.shared(true) //多组数据共享一个浮动提示框
.crosshairs(true) //启用准星线
.valueSuffix(aaChartModel.tooltipValueSuffix) //浮动提示框的单位名称后缀
;
AAPlotOptions aaPlotOptions = new AAPlotOptions()
.series(new AASeries()
.stacking(aaChartModel.stacking) //设置是否百分比堆叠显示图形
);
if (!aaChartModel.animationType.equals(AAChartAnimationType.Linear)) {
aaPlotOptions.series.animation((new AAAnimation()
.easing(aaChartModel.animationType)
.duration(aaChartModel.animationDuration)
));
}
configureAAPlotOptionsMarkerStyle(aaChartModel, aaPlotOptions);
configureAAPlotOptionsDataLabels(aaPlotOptions, aaChartModel);
AALegend aaLegend = new AALegend()
.enabled(aaChartModel.legendEnabled) //是否显示 legend
.itemStyle(new AAItemStyle()
.color(aaChartModel.axesTextColor));
AAOptions aaOptions = new AAOptions()
.chart(aaChart)
.title(aaTitle)
.subtitle(aaSubtitle)
.tooltip(aaTooltip)
.plotOptions(aaPlotOptions)
.legend(aaLegend)
.series(aaChartModel.series)
.colors(aaChartModel.colorsTheme) //设置颜色主题
.touchEventEnabled(aaChartModel.touchEventEnabled) //是否支持点击事件
;
configureAxisContentAndStyle(aaOptions, aaChartModel);
return aaOptions;
}
private static void configureAAPlotOptionsMarkerStyle(
AAChartModel aaChartModel,
AAPlotOptions aaPlotOptions
) {
String chartType = aaChartModel.chartType;
//数据点标记相关配置,只有线性图(折线图、曲线图、折线区域填充图、曲线区域填充图、散点图、折线范围填充图、曲线范围填充图、多边形图)才有数据点标记
if (chartType.equals(AAChartType.Area)
|| chartType.equals(AAChartType.Areaspline)
|| chartType.equals(AAChartType.Line)
|| chartType.equals(AAChartType.Spline)
|| chartType.equals(AAChartType.Scatter)
|| chartType.equals(AAChartType.Arearange)
|| chartType.equals(AAChartType.Areasplinerange)
|| chartType.equals(AAChartType.Polygon)) {
AAMarker aaMarker = new AAMarker()
.radius(aaChartModel.markerRadius) //曲线连接点半径,默认是4
.symbol(aaChartModel.markerSymbol); //曲线点类型:"circle", "square", "diamond", "triangle","triangle-down",默认是"circle"
if (aaChartModel.markerSymbolStyle.equals(AAChartSymbolStyleType.InnerBlank)) {
aaMarker.fillColor("#ffffff") //点的填充色(用来设置折线连接点的填充色)
.lineWidth(2f) //外沿线的宽度(用来设置折线连接点的轮廓描边的宽度)
.lineColor(""); //外沿线的颜色(用来设置折线连接点的轮廓描边颜色,当值为空字符串时,默认取数据点或数据列的颜色)
} else if (aaChartModel.markerSymbolStyle.equals(AAChartSymbolStyleType.BorderBlank)) {
aaMarker.lineWidth(2f)
.lineColor(aaChartModel.backgroundColor);
}
AASeries aaSeries = aaPlotOptions.series;
aaSeries.marker(aaMarker);
}
}
private static void configureAAPlotOptionsDataLabels(
AAPlotOptions aaPlotOptions,
AAChartModel aaChartModel
) {
String chartType = aaChartModel.chartType;
AADataLabels aaDataLabels = new AADataLabels()
.enabled(aaChartModel.dataLabelsEnabled);
if (aaChartModel.dataLabelsEnabled) {
aaDataLabels = aaDataLabels
.style(new AAStyle()
.color(aaChartModel.dataLabelsFontColor)
.fontSize(aaChartModel.dataLabelsFontSize)
.fontWeight(aaChartModel.dataLabelsFontWeight)
);
}
switch (chartType) {
case AAChartType.Column:
AAColumn aaColumn = new AAColumn()
.borderWidth(0f)
.borderRadius(aaChartModel.borderRadius)
.dataLabels(aaDataLabels);
if (aaChartModel.polar) {
aaColumn.pointPadding(0f)
.groupPadding(0.005f);
}
aaPlotOptions.column(aaColumn);
break;
case AAChartType.Bar:
AABar aaBar = (new AABar()
.borderWidth(0f)
.borderRadius(aaChartModel.borderRadius)
.dataLabels(aaDataLabels));
if (aaChartModel.polar) {
aaBar.pointPadding(0f)
.groupPadding(0.005f);
}
aaPlotOptions.bar(aaBar);
break;
case AAChartType.Area:
aaPlotOptions.area(new AAArea().dataLabels(aaDataLabels));
break;
case AAChartType.Areaspline:
aaPlotOptions.areaspline(new AAAreaspline().dataLabels(aaDataLabels));
break;
case AAChartType.Line:
aaPlotOptions.line(new AALine().dataLabels(aaDataLabels));
break;
case AAChartType.Spline:
aaPlotOptions.spline(new AASpline().dataLabels(aaDataLabels));
break;
case AAChartType.Pie:
AAPie aaPie = new AAPie()
.allowPointSelect(true)
.cursor("pointer")
.showInLegend(true);
if (aaChartModel.dataLabelsEnabled) {
aaDataLabels.format("<b>{point.name}</b>: {point.percentage:.1f} %");
}
aaPie.dataLabels(aaDataLabels);
aaPlotOptions.pie(aaPie);
break;
case AAChartType.Columnrange:
AAColumnrange aaColumnrange = new AAColumnrange()
.borderRadius(0f) //The color of the border surrounding each column or bar
.borderWidth(0f) //The corner radius of the border surrounding each column or bar. default:0
.dataLabels(aaDataLabels);
aaPlotOptions.columnrange(aaColumnrange);
break;
case AAChartType.Arearange:
AAArearange aaArearange = new AAArearange()
.dataLabels(aaDataLabels);
aaPlotOptions.arearange(aaArearange);
break;
}
}
private static void configureAxisContentAndStyle(
AAOptions aaOptions,
AAChartModel aaChartModel
) {
String chartType = aaChartModel.chartType;
//x 轴和 Y 轴的相关配置,扇形图、金字塔图和漏斗图则不需要设置 X 轴和 Y 轴的相关内容
if (!chartType.equals(AAChartType.Pie)
&& !chartType.equals(AAChartType.Pyramid)
&& !chartType.equals(AAChartType.Funnel)
) {
Boolean aaXAxisLabelsEnabled = aaChartModel.xAxisLabelsEnabled;
AALabels aaXAxisLabels = new AALabels()
.enabled(aaXAxisLabelsEnabled);//设置 x 轴是否显示文字
if (aaXAxisLabelsEnabled) {
aaXAxisLabels.style(new AAStyle()
.color(aaChartModel.axesTextColor)
.fontSize(aaChartModel.axesTextSize)
);
}
AAXAxis aaXAxis = new AAXAxis()
.labels(aaXAxisLabels) //设置 x 轴是否显示文字
.reversed(aaChartModel.xAxisReversed)
.gridLineWidth(aaChartModel.xAxisGridLineWidth) //x轴网格线宽度
.gridLineDashStyle(aaChartModel.gridLineDashStyle)
.categories(aaChartModel.categories)
.gridLineColor(aaChartModel.gridLineColor)
.visible(aaChartModel.xAxisVisible) //x轴是否可见
.lineWidth(aaChartModel.xAxisLineWidth)
.tickInterval(aaChartModel.xAxisTickInterval)//x轴坐标点间隔数
.lineColor(aaChartModel.yAxisLineColor);//x軸軸線顏色
Boolean aaYAxisLabelsEnabled = aaChartModel.yAxisLabelsEnabled;
AALabels aaYAxisLabels = new AALabels()
.enabled(aaChartModel.yAxisLabelsEnabled)
.format("{value}")
.x(-10f);
if (aaYAxisLabelsEnabled) {
aaYAxisLabels.style(new AAStyle()
.fontSize(aaChartModel.axesTextSize)
.color(aaChartModel.axesTextColor)
);
}
AAYAxis aaYAxis = new AAYAxis()
.labels(aaYAxisLabels) //设置 y 轴是否显示数字
.min(aaChartModel.yAxisMin) //设置 y 轴最小值,最小值等于零就不能显示负值了
.max(aaChartModel.yAxisMax) //y轴最大值
.allowDecimals(aaChartModel.yAxisAllowDecimals) //是否允许显示小数
.reversed(aaChartModel.yAxisReversed)
.gridLineDashStyle(aaChartModel.gridLineDashStyle)
.gridLineWidth(aaChartModel.yAxisGridLineWidth) //y轴网格线宽度
.title(new AATitle()
.text(aaChartModel.yAxisTitle)
.style(new AAStyle()
.color(aaChartModel.axesTextColor))
) //y 轴标题
.lineWidth(aaChartModel.yAxisLineWidth) //设置 y轴轴线的宽度,为0即是隐藏 y轴轴线
.lineColor(aaChartModel.yAxisLineColor)//y軸軸線顏色
.visible(aaChartModel.yAxisVisible)
.tickPosition(aaChartModel.tickPosition)
.tickInterval(aaChartModel.yAxisTickInterval);//y轴坐标点间隔数
aaOptions.xAxis(aaXAxis)
.yAxis(aaYAxis);
}
}
}
/**
// AASeriesElement.java
// AAChartCore
//
// Created by anan on 2018/4/16..
// Copyright © 2018年 An An. All rights reserved.
* ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ ...... SOURCE CODE ......◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
* ◉◉◉................................................... ◉◉◉
* ◉◉◉ https://github.com/AAChartModel/AAChartCore ◉◉◉
* ◉◉◉ https://github.com/AAChartModel/AAChartCore-Kotlin ◉◉◉
* ◉◉◉................................................... ◉◉◉
* ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ ...... SOURCE CODE ......◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉
* -------------------------------------------------------------------------------
*
* 🌕 🌖 🌗 🌘 ❀❀❀ WARM TIPS!!! ❀❀❀ 🌑 🌒 🌓 🌔
*
* Please contact me on GitHub,if there are any problems encountered in use.
* GitHub Issues : https://github.com/AAChartModel/AAChartCore/issues
* -------------------------------------------------------------------------------
* And if you want to contribute for this project, please contact me as well
* GitHub : https://github.com/AAChartModel
* StackOverflow : https://stackoverflow.com/users/7842508/codeforu
* JianShu : http://www.jianshu.com/u/f1e6753d4254
* SegmentFault : https://segmentfault.com/u/huanghunbieguan
*
* -------------------------------------------------------------------------------
*/
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AADataLabels;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAMarker;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AAShadow;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel.AATooltip;
/**
* Created by anan on 2018/4/16.
*/
public class AASeriesElement {
private String type;
private String name;
private Object[] data;
private Float lineWidth;//折线图、曲线图、直方折线图、折线填充图、曲线填充图、直方折线填充图的线条宽度
private Float borderWidth;
private Object color;
private Object fillColor;
private Float fillOpacity;//折线填充图、曲线填充图、直方折线填充图等填充图类型的填充颜色透明度
private Float threshold;//The threshold, also called zero level or base level. For line type series this is only used in conjunction with negativeColor. default:0.
private String negativeColor;// The color for the parts of the graph or points that are below the threshold
private String dashStyle;
private Integer yAxis;
private AADataLabels dataLabels;
private AAMarker marker;
private Object step;
private Boolean colorByPoint;
private Integer zIndex;
private Object[] zones;
private AAShadow shadow;
private String stack;
private AATooltip tooltip;
public AASeriesElement type(String prop) {
type = prop;
return this;
}
public AASeriesElement name(String prop) {
name = prop;
return this;
}
public AASeriesElement data(Object[] prop) {
data = prop;
return this;
}
public AASeriesElement lineWidth(Float prop) {
lineWidth = prop;
return this;
}
public AASeriesElement borderWidth(Float prop) {
borderWidth = prop;
return this;
}
public AASeriesElement color(Object prop) {
color = prop;
return this;
}
public AASeriesElement fillColor(Object prop) {
fillColor = prop;
return this;
}
public AASeriesElement fillOpacity(Float prop) {
fillOpacity = prop;
return this;
}
public AASeriesElement threshold(Float prop) {
threshold = prop;
return this;
}
public AASeriesElement negativeColor(String prop) {
negativeColor = prop;
return this;
}
public AASeriesElement dashStyle(String prop) {
dashStyle = prop;
return this;
}
public AASeriesElement yAxis(Integer prop) {
yAxis = prop;
return this;
}
public AASeriesElement dataLabels(AADataLabels prop) {
dataLabels = prop;
return this;
}
public AASeriesElement marker(AAMarker prop) {
marker = prop;
return this;
}
public AASeriesElement step(Object prop) {
step = prop;
return this;
}
public AASeriesElement colorByPoint(Boolean prop) {
colorByPoint = prop;
return this;
}
public AASeriesElement zIndex(Integer prop) {
zIndex = prop;
return this;
}
public AASeriesElement zones(Object[] prop) {
zones = prop;
return this;
}
public AASeriesElement shadow(AAShadow prop) {
shadow = prop;
return this;
}
public AASeriesElement stack(String prop) {
stack = prop;
return this;
}
public AASeriesElement tooltip(AATooltip prop) {
tooltip = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum;
public interface AAChartAlignType {
String Left = "left";
String Center = "center";
String Right = "right";
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum;
public interface AAChartAnimationType {
String Linear = "linear";
String EaseInQuad = "easeInQuad";
String EaseOutQuad = "easeOutQuad";
String EaseInOutQuad = "easeInOutQuad";
String EaseInCubic = "easeInCubic";
String EaseOutCubic = "easeOutCubic";
String EaseInOutCubic = "easeInOutCubic";
String EaseInQuart = "easeInQuart";
String EaseOutQuart = "easeOutQuart";
String EaseInOutQuart = "easeInOutQuart";
String EaseInQuint = "easeInQuint";
String EaseOutQuint = "easeOutQuint";
String EaseInOutQuint = "easeInOutQuint";
String EaseInSine = "easeInSine";
String EaseOutSine = "easeOutSine";
String EaseInOutSine = "easeInOutSine";
String EaseInExpo = "easeInExpo";
String EaseOutExpo = "easeOutExpo";
String EaseInOutExpo = "easeInOutExpo";
String EaseInCirc = "easeInCirc";
String EaseOutCirc = "easeOutCirc";
String EaseInOutCirc = "easeInOutCirc";
String EaseOutBounce = "easeOutBounce";
String EaseInBack = "easeInBack";
String EaseOutBack = "easeOutBack";
String EaseInOutBack = "easeInOutBack";
String Elastic = "elastic";
String SwingFromTo = "swingFromTo";
String SwingFrom = "swingFrom";
String SwingTo = "swingTo";
String Bounce = "bounce";
String BouncePast = "bouncePast";
String EaseFromTo = "easeFromTo";
String EaseFrom = "easeFrom";
String EaseTo = "easeTo";
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum;
public interface AAChartFontWeightType {
String Thin = "thin";
String Regular = "regular";
String Bold = "bold";
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum;
public interface AAChartLayoutType {
String Horizontal = "horizontal";
String Vertical = "vertical";
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum;
public interface AAChartLineDashStyleType {
String Solid = "Solid";
String ShortDash = "ShortDash";
String ShortDot = "ShortDot";
String ShortDashDot = "ShortDashDot";
String ShortDashDotDot = "ShortDashDotDot";
String Dot = "Dot";
String Dash = "Dash";
String LongDash = "LongDash";
String DashDot = "DashDot";
String LongDashDot = "LongDashDot";
String LongDashDotDot = "LongDashDotDot";
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum;
public interface AAChartStackingType {
String False = "";
String Normal = "normal";
String Percent = "percent";
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum;
public interface AAChartSymbolStyleType {
String Normal = "normal";
String InnerBlank = "innerBlank";
String BorderBlank = "borderBlank";
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum;
public interface AAChartSymbolType {
String Circle = "circle";
String Square = "square";
String Diamond = "diamond";
String Triangle = "triangle";
String Triangle_down = "triangle-down";
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum;
public interface AAChartType {
String Column = "column";
String Bar = "bar";
String Area = "area";
String Areaspline = "areaspline";
String Line = "line";
String Spline = "spline";
String Scatter = "scatter";
String Pie = "pie";
String Bubble = "bubble";
String Pyramid = "pyramid";
String Funnel = "funnel";
String Columnrange = "columnrange";
String Arearange = "arearange";
String Areasplinerange = "areasplinerange";
String Boxplot = "boxplot";
String Waterfall = "waterfall";
String Polygon = "polygon";
String Gauge = "gauge";
String Errorbar = "errorbar";
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum;
public interface AAChartVerticalAlignType {
String Top = "top";
String Middle = "middle";
String Bottom = "bottom";
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum;
public interface AAChartZoomType {
String None = "none";
String X = "x";
String Y = "y";
String XY = "xy";
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAAnimation {
public Integer duration;
public String easing;
public AAAnimation duration(Integer prop) {
duration = prop;
return this;
}
public AAAnimation easing(String prop) {
easing = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAArea {
public AADataLabels dataLabels;
public AAArea dataLabels(AADataLabels prop) {
dataLabels = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAArearange {
public AADataLabels dataLabels;
public AAArearange dataLabels(AADataLabels prop) {
dataLabels = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAAreaspline {
public AADataLabels dataLabels;
public AAAreaspline dataLabels(AADataLabels prop) {
dataLabels = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AABar {
public String name;
public Object[] data;
public String color;
public Boolean grouping;//Whether to group non-stacked columns or to let them render independent of each other. Non-grouped columns will be laid out individually and overlap each other. 默认是:true.
public Float pointPadding;//Padding between each column or bar, in x axis units. 默认是:0.1.
public Float pointPlacement;//Padding between each column or bar, in x axis units. 默认是:0.1.
public Float groupPadding;//Padding between each value groups, in x axis units. 默认是:0.2.
public Float borderWidth;
public Boolean colorByPoint;//对每个不同的点设置颜色(当图表类型为 AABar 时,设置为 AABar 对象的属性,当图表类型为 bar 时,应该设置为 bar 对象的属性才有效)
public AADataLabels dataLabels;
public String stacking;
public Float borderRadius;
public Float yAxis;
public AABar name(String prop) {
name = prop;
return this;
}
public AABar data(Object[] prop) {
data = prop;
return this;
}
public AABar color(String prop) {
color = prop;
return this;
}
public AABar grouping(Boolean prop) {
grouping = prop;
return this;
}
public AABar pointPadding(Float prop) {
pointPadding = prop;
return this;
}
public AABar pointPlacement(Float prop) {
pointPlacement = prop;
return this;
}
public AABar groupPadding(Float prop) {
groupPadding = prop;
return this;
}
public AABar borderWidth(Float prop) {
borderWidth = prop;
return this;
}
public AABar colorByPoint(Boolean prop) {
colorByPoint = prop;
return this;
}
public AABar dataLabels(AADataLabels prop) {
dataLabels = prop;
return this;
}
public AABar stacking(String prop) {
stacking = prop;
return this;
}
public AABar borderRadius(Float prop) {
borderRadius = prop;
return this;
}
public AABar yAxis(Float prop) {
yAxis = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAChart {
public String type;
public Object backgroundColor;
public String plotBackgroundImage;
public String pinchType;
public Boolean panning;
public String panKey;
public Boolean polar;
public AAAnimation animation;
public Boolean inverted;
/*图表外边缘和绘图区域之间的边距。 数组中的数字分别表示顶部,右侧,底部和左侧 ([👆,👉,👇,👈])。
也可以使用 marginTop,marginRight,marginBottom 和 marginLeft 来设置某一个方向的边距*/
public Float[] margin;
public Float marginTop; //👆
public Float marginRight; //👉
public Float marginBottom; //👇
public Float marginLeft; //👈
public AAChart type(String prop) {
type = prop;
return this;
}
public AAChart backgroundColor(Object prop) {
backgroundColor = prop;
return this;
}
public AAChart plotBackgroundImage(String prop) {
plotBackgroundImage = prop;
return this;
}
public AAChart pinchType(String prop) {
pinchType = prop;
return this;
}
public AAChart panning(Boolean prop) {
panning = prop;
return this;
}
public AAChart panKey(String prop) {
panKey = prop;
return this;
}
public AAChart polar(Boolean prop) {
polar = prop;
return this;
}
public AAChart animation(AAAnimation prop) {
animation = prop;
return this;
}
public AAChart inverted(Boolean prop) {
inverted = prop;
return this;
}
public AAChart margin(Float[] prop) {
margin = prop;
return this;
}
public AAChart marginTop(Float prop) {
marginTop = prop;
return this;
}
public AAChart marginRight(Float prop) {
marginRight = prop;
return this;
}
public AAChart marginBottom(Float prop) {
marginBottom = prop;
return this;
}
public AAChart marginLeft(Float prop) {
marginLeft = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAColumn {
public String name;
public Object[] data;
public String color;
public Boolean grouping;//Whether to group non-stacked columns or to let them render independent of each other. Non-grouped columns will be laid out individually and overlap each other. 默认是:true.
public Float pointPadding;//Padding between each column or bar, in x axis units. 默认是:0.1.
public Float pointPlacement;//Padding between each column or bar, in x axis units. 默认是:0.1.
public Float groupPadding;//Padding between each value groups, in x axis units. 默认是:0.2.
public Float borderWidth;
public Boolean colorByPoint;//对每个不同的点设置颜色(当图表类型为 AAColumn 时,设置为 AAColumn 对象的属性,当图表类型为 bar 时,应该设置为 bar 对象的属性才有效)
public AADataLabels dataLabels;
public String stacking;
public Float borderRadius;
public Float yAxis;
public AAColumn name(String prop) {
name = prop;
return this;
}
public AAColumn data(Object[] prop) {
data = prop;
return this;
}
public AAColumn color(String prop) {
color = prop;
return this;
}
public AAColumn grouping(Boolean prop) {
grouping = prop;
return this;
}
public AAColumn pointPadding(Float prop) {
pointPadding = prop;
return this;
}
public AAColumn pointPlacement(Float prop) {
pointPlacement = prop;
return this;
}
public AAColumn groupPadding(Float prop) {
groupPadding = prop;
return this;
}
public AAColumn borderWidth(Float prop) {
borderWidth = prop;
return this;
}
public AAColumn colorByPoint(Boolean prop) {
colorByPoint = prop;
return this;
}
public AAColumn dataLabels(AADataLabels prop) {
dataLabels = prop;
return this;
}
public AAColumn stacking(String prop) {
stacking = prop;
return this;
}
public AAColumn borderRadius(Float prop) {
borderRadius = prop;
return this;
}
public AAColumn yAxis(Float prop) {
yAxis = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAColumnrange {
public Float borderRadius;
public Float borderWidth;
public AADataLabels dataLabels;
public AAColumnrange borderRadius(Float prop) {
borderRadius = prop;
return this;
}
public AAColumnrange borderWidth(Float prop) {
borderWidth = prop;
return this;
}
public AAColumnrange dataLabels(AADataLabels prop) {
dataLabels = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AACrosshair {
public Float width;
public String color;
public String dashStyle;
public AACrosshair width(Float prop) {
width = prop;
return this;
}
public AACrosshair color(String prop) {
color = prop;
return this;
}
public AACrosshair dashStyle(String prop) {
dashStyle = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AADataElement {
public String name;
public Float y;
public Object color;
public AADataLabels dataLabels;
public AAMarker marker;
public AADataElement name(String prop) {
name = prop;
return this;
}
public AADataElement y(Float prop) {
y = prop;
return this;
}
public AADataElement color(Object prop) {
color = prop;
return this;
}
public AADataElement dataLabels(AADataLabels prop) {
dataLabels = prop;
return this;
}
public AADataElement marker(AAMarker prop) {
marker = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AADataLabels {
public Boolean enabled;
public AAStyle style;
public String format;
public Float rotation;
public Boolean allowOverlap;
public Boolean useHTML;
public Float distance;
public String verticalAlign;
public Float x;
public Float y;
public String color;
public String backgroundColor;
public String borderColor;
public Float borderRadius;
public Float borderWidth;
public String shape;
public AADataLabels enabled(Boolean prop) {
enabled = prop;
return this;
}
public AADataLabels style(AAStyle prop) {
style = prop;
return this;
}
public AADataLabels format(String prop) {
format = prop;
return this;
}
public AADataLabels rotation(Float prop) {
rotation = prop;
return this;
}
public AADataLabels allowOverlap(Boolean prop) {
allowOverlap = prop;
return this;
}
public AADataLabels useHTML(Boolean prop) {
useHTML = prop;
return this;
}
public AADataLabels distance(Float prop) {
distance = prop;
return this;
}
public AADataLabels verticalAlign(String prop) {
verticalAlign = prop;
return this;
}
public AADataLabels x(Float prop) {
x = prop;
return this;
}
public AADataLabels y(Float prop) {
y = prop;
return this;
}
public AADataLabels color(String prop) {
color = prop;
return this;
}
public AADataLabels backgroundColor(String prop) {
backgroundColor = prop;
return this;
}
public AADataLabels borderColor(String prop) {
borderColor = prop;
return this;
}
public AADataLabels borderRadius(Float prop) {
borderRadius = prop;
return this;
}
public AADataLabels borderWidth(Float prop) {
borderWidth = prop;
return this;
}
public AADataLabels shape(String prop) {
shape = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
import java.util.Map;
public class AAHalo {
public Map attributes;
public Float opacity;
public Float size;
public AAHalo attributes(Map prop) {
attributes = prop;
return this;
}
public AAHalo opacity(Float prop) {
opacity = prop;
return this;
}
public AAHalo size(Float prop) {
size = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAHover {
public String borderColor;
public Float brightness;
public String color;
public AAHalo halo;
public AAHover borderColor(String prop) {
borderColor = prop;
return this;
}
public AAHover brightness(Float prop) {
brightness = prop;
return this;
}
public AAHover color(String prop) {
color = prop;
return this;
}
public AAHover halo(AAHalo prop) {
halo = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAItemStyle {
public String color;
public String cursor;
public String pointer;
public String fontSize;
public String fontWeight;
public AAItemStyle color(String prop) {
color = prop;
return this;
}
public AAItemStyle cursor(String prop) {
cursor = prop;
return this;
}
public AAItemStyle pointer(String prop) {
pointer = prop;
return this;
}
public AAItemStyle fontSize(Float prop) {
fontSize = prop + "px";
return this;
}
public AAItemStyle fontWeight(String prop) {
fontWeight = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AALabel {
public String text;
public Object style;
public AALabel text(String prop) {
text = prop;
return this;
}
public AALabel style(Object prop) {
style = prop;
return this;
}
}
\ No newline at end of file
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AATools.AAJSStringPurer;
public class AALabels {
public String align;//轴标签的对齐方式,可用的值有 "left"、"center" 及 "right"。默认值是根据坐标轴的位置(在图表中的位置)即标签的旋转角度进行智能判断的。 默认是:center.
public Object autoRotation; //只针对水平轴有效,允许在防止轴标签重叠时自动旋转轴标签的角度。当空间足够时,轴标签不会被旋转。当图表变小时(主要是宽度变小) ,轴标签开始旋转对应的角度,然后会依次删除间隔的轴标签并尝试旋转数组中的角度。可以通过将此参数设置为 false 来关闭轴标签旋转(这将导致标签自动换行)。 默认是:[-45].
public Float autoRotationLimit;//当每个分类的宽度比该参数的值大很多(像素)时,轴标签将不会被自动旋转,而是以换行的形式展示轴标签。 当轴标签包含多个短词时换行展示轴标签可以使得轴标签有足够的空间,所以设置合理的自动旋转下限是非常有意义的。 默认是:80.
public Float distance;//只针对极地图有效,定义周标签与绘图区边缘的距离。 默认是:15.
public Boolean enabled;//是否显示坐标轴标签 默认是:true.
public String format;//坐标轴格式化字符串。 默认是:{value}.
public String formatter;//坐标轴格式化字符串。 默认是:{value}.
public Float padding;//轴标签的内间距,作用是保证轴标签之间有空隙。 默认是:5.
public Float rotation;//轴标签的旋转角度 默认是:0.
public Integer staggerLines;//只针对水平轴有效,定义轴标签显示行数。
public Integer step;//显示 n 的倍数标签,例如设置为 2 则表示标签间隔一个轴标签显示。默认情况下,为了避免轴标签被覆盖,该参数会根据情况自动计算。可以通过设置此参数为 1 来阻止自动计算。
public AAStyle style;//轴标签的 CSS 样式
public Float x;//相对于坐标轴刻度线的水平偏移。 默认是:0.
public Float y;//相对于坐标轴刻度线的垂直平偏移。 默认是:null.
public Boolean useHTML;//HTML渲染
public AALabels align(String prop) {
align = prop;
return this;
}
public AALabels autoRotation(Object prop) {
autoRotation = prop;
return this;
}
public AALabels autoRotationLimit(Float prop) {
autoRotationLimit = prop;
return this;
}
public AALabels distance(Float prop) {
distance = prop;
return this;
}
public AALabels enabled(Boolean prop) {
enabled = prop;
return this;
}
public AALabels format(String prop) {
format = prop;
return this;
}
public AALabels formatter(String prop) {
String pureJSFunctionStr = "(" + prop + ")";
pureJSFunctionStr = AAJSStringPurer.pureJavaScriptFunctionString(pureJSFunctionStr);
formatter = pureJSFunctionStr;
return this;
}
public AALabels padding(Float prop) {
padding = prop;
return this;
}
public AALabels rotation(Float prop) {
rotation = prop;
return this;
}
public AALabels staggerLines(Integer prop) {
staggerLines = prop;
return this;
}
public AALabels step(Integer prop) {
step = prop;
return this;
}
public AALabels style(AAStyle prop) {
style = prop;
return this;
}
public AALabels x(Float prop) {
x = prop;
return this;
}
public AALabels y(Float prop) {
y = prop;
return this;
}
public AALabels useHTML(Boolean prop) {
useHTML = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AALegend {
public String layout; //图例数据项的布局。布局类型: "horizontal" 或 "vertical" 即水平布局和垂直布局 默认是:horizontal.
public String align; //设定图例在图表区中的水平对齐方式,合法值有left,center 和 right。
public String verticalAlign; //设定图例在图表区中的垂直对齐方式,合法值有 top,middle 和 bottom。垂直位置可以通过 y 选项做进一步设定。
public Boolean enabled;
public String borderColor;
public Float borderWidth;
public Float itemMarginTop; //图例的每一项的顶部外边距,单位px。 默认是:0.
public AAItemStyle itemStyle;
public Float x;
public Float y;
public Boolean floating;
public AALegend layout(String prop) {
layout = prop;
return this;
}
public AALegend align(String prop) {
align = prop;
return this;
}
public AALegend verticalAlign(String prop) {
verticalAlign = prop;
return this;
}
public AALegend enabled(Boolean prop) {
enabled = prop;
return this;
}
public AALegend borderColor(String prop) {
borderColor = prop;
return this;
}
public AALegend BorderWidth(Float prop) {
borderWidth = prop;
return this;
}
public AALegend itemMarginTop(Float prop) {
itemMarginTop = prop;
return this;
}
public AALegend itemStyle(AAItemStyle prop) {
itemStyle = prop;
return this;
}
public AALegend x(Float prop) {
x = prop;
return this;
}
public AALegend y(Float prop) {
y = prop;
return this;
}
public AALegend floating(Boolean prop) {
floating = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AALine {
public AADataLabels dataLabels;
public AALine dataLabels(AADataLabels prop) {
dataLabels = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAMarker {
public Float radius;
public String symbol;
public String fillColor;//点的填充色(用来设置折线连接点的填充色)
public Float lineWidth;//外沿线的宽度(用来设置折线连接点的轮廓描边的宽度)
public Object lineColor;//外沿线的颜色(用来设置折线连接点的轮廓描边颜色,当值为空字符串时,默认取数据点或数据列的颜色。)
public AAMarker radius(Float prop) {
radius = prop;
return this;
}
public AAMarker symbol(String prop) {
symbol = prop;
return this;
}
public AAMarker fillColor(String prop) {
fillColor = prop;
return this;
}
public AAMarker lineWidth(Float prop) {
lineWidth = prop;
return this;
}
public AAMarker lineColor(Object prop) {
lineColor = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAOptions {
public AAChart chart;
public AATitle title;
public AASubtitle subtitle;
public AAXAxis xAxis;
public AAYAxis yAxis;
public AAXAxis[] xAxisArray;
public AAYAxis[] yAxisArray;
public AATooltip tooltip;
public AAPlotOptions plotOptions;
public Object[] series;
public AALegend legend;
public Object[] colors;
public Boolean touchEventEnabled;
public AAOptions chart(AAChart prop) {
chart = prop;
return this;
}
public AAOptions title(AATitle prop) {
title = prop;
return this;
}
public AAOptions subtitle(AASubtitle prop) {
subtitle = prop;
return this;
}
public AAOptions xAxis(AAXAxis prop) {
xAxis = prop;
return this;
}
public AAOptions yAxis(AAYAxis prop) {
yAxis = prop;
return this;
}
public AAOptions xAxisArray(AAXAxis[] prop) {
xAxisArray = prop;
return this;
}
public AAOptions yAxisArray(AAYAxis[] prop) {
yAxisArray = prop;
return this;
}
public AAOptions tooltip(AATooltip prop) {
tooltip = prop;
return this;
}
public AAOptions plotOptions(AAPlotOptions prop) {
plotOptions = prop;
return this;
}
public AAOptions series(Object[] prop) {
series = prop;
return this;
}
public AAOptions legend(AALegend prop) {
legend = prop;
return this;
}
public AAOptions colors(Object[] prop) {
colors = prop;
return this;
}
public AAOptions touchEventEnabled(Boolean prop) {
touchEventEnabled = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAPie {
public String name;
public Object[] data;
public AADataLabels dataLabels;
public Float size;
public String innerSize;
public Boolean allowPointSelect;
public String cursor;
public Boolean showInLegend;
public Float startAngle;
public Float endAngle;
public Float depth;
public Float center;
public AAPie name(String prop) {
name = prop;
return this;
}
public AAPie data(Object[] prop) {
data = prop;
return this;
}
public AAPie dataLabels(AADataLabels prop) {
dataLabels = prop;
return this;
}
public AAPie size(Float prop) {
size = prop;
return this;
}
public AAPie innerSize(String prop) {
innerSize = prop;
return this;
}
public AAPie allowPointSelect(Boolean prop) {
allowPointSelect = prop;
return this;
}
public AAPie cursor(String prop) {
cursor = prop;
return this;
}
public AAPie showInLegend(Boolean prop) {
showInLegend = prop;
return this;
}
public AAPie startAngle(Float prop) {
startAngle = prop;
return this;
}
public AAPie endAngle(Float prop) {
endAngle = prop;
return this;
}
public AAPie depth(Float prop) {
depth = prop;
return this;
}
public AAPie center(Float prop) {
center = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAPlotBandsElement {
public Float from;
public Float to;
public Object color;
public String borderColor;
public Float borderWidth;
public String className;
public AALabel label;
public Integer zIndex;
public AAPlotBandsElement from(Float prop) {
from = prop;
return this;
}
public AAPlotBandsElement to(Float prop) {
to = prop;
return this;
}
public AAPlotBandsElement color(Object prop) {
color = prop;
return this;
}
public AAPlotBandsElement borderColor(String prop) {
borderColor = prop;
return this;
}
public AAPlotBandsElement borderWidth(Float prop) {
borderWidth = prop;
return this;
}
public AAPlotBandsElement className(String prop) {
className = prop;
return this;
}
public AAPlotBandsElement label(AALabel prop) {
label = prop;
return this;
}
public AAPlotBandsElement zIndex(Integer prop) {
zIndex = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAPlotLinesElement {
public Object color;
public String dashStyle;
public Float width;
public Float value;
public Integer zIndex;
public AALabel label;
public AAPlotLinesElement color(Object prop) {
color = prop;
return this;
}
public AAPlotLinesElement dashStyle(String prop) {
dashStyle = prop;
return this;
}
public AAPlotLinesElement width(Float prop) {
width = prop;
return this;
}
public AAPlotLinesElement value(Float prop) {
value = prop;
return this;
}
public AAPlotLinesElement zIndex(Integer prop) {
zIndex = prop;
return this;
}
public AAPlotLinesElement label(AALabel prop) {
label = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAPlotOptions {
public AAColumn column;
public AALine line;
public AAPie pie;
public AABar bar;
public AASpline spline;
public AAArea area;
public AAAreaspline areaspline;
public AAColumnrange columnrange;
public AAArearange arearange;
public AASeries series;
public AAPlotOptions column(AAColumn prop) {
column = prop;
return this;
}
public AAPlotOptions line(AALine prop) {
line = prop;
return this;
}
public AAPlotOptions pie(AAPie prop) {
pie = prop;
return this;
}
public AAPlotOptions bar(AABar prop) {
bar = prop;
return this;
}
public AAPlotOptions spline(AASpline prop) {
spline = prop;
return this;
}
public AAPlotOptions area(AAArea prop) {
area = prop;
return this;
}
public AAPlotOptions areaspline(AAAreaspline prop) {
areaspline = prop;
return this;
}
public AAPlotOptions columnrange(AAColumnrange prop) {
columnrange = prop;
return this;
}
public AAPlotOptions arearange(AAArearange prop) {
arearange = prop;
return this;
}
public AAPlotOptions series(AASeries prop) {
series = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AASelect {
public String borderColor;
public String color;
public AAHalo halo;
public AASelect borderColor(String prop) {
borderColor = prop;
return this;
}
public AASelect color(String prop) {
color = prop;
return this;
}
public AASelect halo(AAHalo prop) {
halo = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
import java.util.Map;
public class AASeries {
public Float borderRadius;
public AAMarker marker;
public String stacking;
public AAAnimation animation;
public String[] keys;
public Boolean colorByPoint;//决定了图表是否给每个数据列或每个点分配一个颜色,默认值是 false, 即默认是给每个数据类分配颜色,
public Boolean connectNulls;//设置折线是否断点重连
public Map events;
public AAShadow shadow;
public AASeries borderRadius(Float prop) {
borderRadius = prop;
return this;
}
public AASeries marker(AAMarker prop) {
marker = prop;
return this;
}
public AASeries stacking(String prop) {
stacking = prop;
return this;
}
public AASeries animation(AAAnimation prop) {
animation = prop;
return this;
}
public AASeries keys(String[] prop) {
keys = prop;
return this;
}
public AASeries colorByPoint(Boolean prop) {
colorByPoint = prop;
return this;
}
public AASeries connectNulls(Boolean prop) {
connectNulls = prop;
return this;
}
public AASeries events(Map prop) {
events = prop;
return this;
}
public AASeries shadow(AAShadow prop) {
shadow = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAShadow {
public String color;
public Float offsetX;
public Float offsetY;
public Float opacity;
public Float width;
public AAShadow color(String prop) {
color = prop;
return this;
}
public AAShadow offsetX(Float prop) {
offsetX = prop;
return this;
}
public AAShadow offsetY(Float prop) {
offsetY = prop;
return this;
}
public AAShadow opacity(Float prop) {
opacity = prop;
return this;
}
public AAShadow width(Float prop) {
width = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AASpline {
public AADataLabels dataLabels;
public AASpline dataLabels(AADataLabels prop) {
dataLabels = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAStates {
public AAHover hover;
public AASelect select;
public AAStates hover(AAHover prop) {
hover = prop;
return this;
}
public AAStates select(AASelect prop) {
select = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAStyle {
public String color;
public String fontSize;
public String fontWeight;
public String textOutLine;
public AAStyle color(String prop) {
color = prop;
return this;
}
public AAStyle fontSize(Float prop) {
fontSize = prop + "px";
return this;
}
public AAStyle fontWeight(String prop) {
fontWeight = prop;
return this;
}
public AAStyle textOutline(String prop) {
textOutLine = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartVerticalAlignType;
public class AASubtitle {
public String text;
public AAStyle style;
public String align;
public String verticalAlign;
public Float x;
public Float y;
public Boolean userHTML;
public AASubtitle text(String prop) {
text = prop;
return this;
}
public AASubtitle style(AAStyle prop) {
style = prop;
return this;
}
public AASubtitle align(String prop) {
align = prop;
return this;
}
public AASubtitle verticalAlign(AAChartVerticalAlignType prop) {
verticalAlign = prop.toString();
return this;
}
public AASubtitle x(Float prop) {
x = prop;
return this;
}
public AASubtitle y(Float prop) {
y = prop;
return this;
}
public AASubtitle userHTML(Boolean prop) {
userHTML = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartAlignType;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartEnum.AAChartVerticalAlignType;
public class AATitle {
public String text;
public AAStyle style;
public String align;
public String verticalAlign;
public Float x;
public Float y;
public Boolean userHTML;
public AATitle text(String prop) {
text = prop;
return this;
}
public AATitle style(AAStyle prop) {
style = prop;
return this;
}
public AATitle align(AAChartAlignType prop) {
align = prop.toString();
return this;
}
public AATitle verticalAlign(AAChartVerticalAlignType prop) {
verticalAlign = prop.toString();
return this;
}
public AATitle x(Float prop) {
x = prop;
return this;
}
public AATitle y(Float prop) {
y = prop;
return this;
}
public AATitle userHTML(Boolean prop) {
userHTML = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AATools.AAJSStringPurer;
public class AATooltip {
public String backgroundColor;
public String borderColor;
public Float borderRadius;
public Float borderWidth;
public AAStyle style;
public Boolean enabled;
public Boolean useHTML;
public String formatter;
public String headerFormat;
public String pointFormat;
public String footerFormat;
public Integer valueDecimals;
public Boolean shared;
public Boolean crosshairs;
public String valueSuffix;
public AATooltip backgroundColor(String prop) {
backgroundColor = prop;
return this;
}
public AATooltip borderColor(String prop) {
borderColor = prop;
return this;
}
public AATooltip borderRadius(Float prop) {
borderRadius = prop;
return this;
}
public AATooltip borderWidth(Float prop) {
borderWidth = prop;
return this;
}
public AATooltip style(AAStyle prop) {
style = prop;
return this;
}
public AATooltip enabled(Boolean prop) {
enabled = prop;
return this;
}
public AATooltip useHTML(Boolean prop) {
useHTML = prop;
return this;
}
public AATooltip formatter(String prop) {
String pureJSFunctionStr = "(" + prop + ")";
pureJSFunctionStr = AAJSStringPurer.pureJavaScriptFunctionString(pureJSFunctionStr);
formatter = pureJSFunctionStr;
return this;
}
public AATooltip headerFormat(String prop) {
headerFormat = prop;
return this;
}
public AATooltip pointFormat(String prop) {
pointFormat = prop;
return this;
}
public AATooltip footerFormat(String prop) {
footerFormat = prop;
return this;
}
public AATooltip valueDecimals(Integer prop) {
valueDecimals = prop;
return this;
}
public AATooltip shared(Boolean prop) {
shared = prop;
return this;
}
public AATooltip crosshairs(Boolean prop) {
crosshairs = prop;
return this;
}
public AATooltip valueSuffix(String prop) {
valueSuffix = prop;
return this;
}
public AATooltip() {
enabled = true;
shared = true;
crosshairs = true;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
import com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAChartConfiger.AASeriesElement;
public class AAWaterfall extends AASeriesElement {
public String upColor;
public String color;
public Float borderWidth;
public Object[] data;
public AAWaterfall upColor(String prop) {
upColor = prop;
return this;
}
public AAWaterfall color(String prop) {
color = prop;
return this;
}
public AAWaterfall borderWidth(Float prop) {
borderWidth = prop;
return this;
}
public AAWaterfall data(Object[] prop) {
data = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAXAxis {
public AAPlotBandsElement[] plotBands;
public AAPlotLinesElement[] plotLines;
public String[] categories;
public Integer linkedTo;
public Boolean reversed;
public Boolean opposite;
public Float lineWidth; //x轴轴线宽度
public String lineColor; //x轴轴线线颜色
public Float max; //x轴最大值
public Float min;//x轴最小值(设置为0就不会有负数)
public String tickColor; //x轴轴线下方刻度线颜色
public Float gridLineWidth; //x轴网格线宽度
public String gridLineColor; //x轴网格线颜色
public String gridLineDashStyle; //x轴网格线样式
public Float off;//x轴垂直偏移
public AALabels labels; //用于设置 x 轴文字相关的
public Boolean visible; //用于设置 x 轴以及 x 轴文字是否显示
public Boolean startOnTick; //Whether to force the axis to start on a tick. Use this option with the minPadding option to control the axis start. 默认是:false.
public Integer tickInterval;//x轴刻度点间隔数(设置每隔几个点显示一个 X轴的内容:
public AACrosshair crosshair; //准星线样式设置
public String tickmarkPlacement; //本参数只对分类轴有效。 当值为 on 时刻度线将在分类上方显示;当值为 between 时,刻度线将在两个分类中间显示。当 tickInterval 为 1 时,默认是 between,其他情况默认是 on。 默认是:null.
public Float tickWidth;//坐标轴刻度线的宽度,设置为 0 时则不显示刻度线
public Float tickLength;//坐标轴刻度线的长度。 默认是:10.
public String tickPosition; //刻度线相对于轴线的位置,可用的值有 inside 和 outside,分别表示在轴线的内部和外部。 默认是:outside.
public AAXAxis plotBands(AAPlotBandsElement[] prop) {
plotBands = prop;
return this;
}
public AAXAxis plotLines(AAPlotLinesElement[] prop) {
plotLines = prop;
return this;
}
public AAXAxis categories(String[] prop) {
categories = prop;
return this;
}
public AAXAxis linkedTo(Integer prop) {
linkedTo = prop;
return this;
}
public AAXAxis reversed(Boolean prop) {
reversed = prop;
return this;
}
public AAXAxis opposite(Boolean prop) {
opposite = prop;
return this;
}
public AAXAxis lineWidth(Float prop) {
lineWidth = prop;
return this;
}
public AAXAxis lineColor(String prop) {
lineColor = prop;
return this;
}
public AAXAxis max(Float prop) {
max = prop;
return this;
}
public AAXAxis min(Float prop) {
min = prop;
return this;
}
public AAXAxis tickColor(String prop) {
tickColor = prop;
return this;
}
public AAXAxis gridLineWidth(Float prop) {
gridLineWidth = prop;
return this;
}
public AAXAxis gridLineColor(String prop) {
gridLineColor = prop;
return this;
}
public AAXAxis gridLineDashStyle(String prop) {
gridLineDashStyle = prop;
return this;
}
public AAXAxis off(Float prop) {
off = prop;
return this;
}
public AAXAxis labels(AALabels prop) {
labels = prop;
return this;
}
public AAXAxis visible(Boolean prop) {
visible = prop;
return this;
}
public AAXAxis startOnTick(Boolean prop) {
startOnTick = prop;
return this;
}
public AAXAxis tickInterval(Integer prop) {
tickInterval = prop;
return this;
}
public AAXAxis crosshair(AACrosshair prop) {
crosshair = prop;
return this;
}
public AAXAxis tickmarkPlacement(String prop) {
tickmarkPlacement = prop;
return this;
}
public AAXAxis tickWidth(Float prop) {
tickWidth = prop;
return this;
}
public AAXAxis tickLength(Float prop) {
tickLength = prop;
return this;
}
public AAXAxis tickPosition(String prop) {
tickPosition = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AAOptionsModel;
public class AAYAxis {
public AATitle title;
public AAPlotBandsElement[] plotBands;
public AAPlotLinesElement[] plotLines;
public String[] categories;
public Boolean reversed;
public Float gridLineWidth;// y 轴网格线宽度
public String gridLineColor; // y 轴网格线颜色
public String gridLineDashStyle; //网格线线条样式,所有可用的线条样式参考:Highcharts线条样式
public String alternateGridColor; //backcolor of every other grid line area
public String gridLineInterpolation; //Polar charts only. Whether the grid lines should draw as a polygon with straight lines between categories, or as circles. Can be either circle or polygon. 默认是:null.
public AALabels labels;//用于设置 y 轴文字相关的
public Float lineWidth; // y 轴线宽度
public String lineColor; // y 轴线颜色
public Float off; // y 轴线水平偏移
public Boolean allowDecimals; //y轴是否允许显示小数
public Float max; //y轴最大值
public Float min; //y轴最小值(设置为0就不会有负数)
//private var minPadding: //Padding of the min value relative to the length of the axis. A padding of 0.05 will make a 100px axis 5px longer. This is useful when you don't want the lowest data value to appear on the edge of the plot area. 默认是:0.05.
public Object[] tickPositions; //自定义Y轴坐标(如:[0, 25, 50, 75 , 100])
public Boolean visible; //y轴是否允许显示
public Boolean opposite;//是否将坐标轴显示在对立面,默认情况下 x 轴是在图表的下方显示,y 轴是在左方,坐标轴显示在对立面后,x 轴是在上方显示,y 轴是在右方显示(即坐标轴会显示在对立面)。该配置一般是用于多坐标轴区分展示,另外在 Highstock 中,y 轴默认是在对立面显示的。 默认是:false.
public Integer tickInterval;
public AACrosshair crosshair; //准星线样式设置
public String stackLabels;
public Float tickWidth;//坐标轴刻度线的宽度,设置为 0 时则不显示刻度线
public Float tickLength;//坐标轴刻度线的长度。 默认是:10.
public String tickPosition; //刻度线相对于轴线的位置,可用的值有 inside 和 outside,分别表示在轴线的内部和外部。 默认是:outside.
public AAYAxis title(AATitle prop) {
title = prop;
return this;
}
public AAYAxis plotBands(AAPlotBandsElement[] prop) {
plotBands = prop;
return this;
}
public AAYAxis plotLines(AAPlotLinesElement[] prop) {
plotLines = prop;
return this;
}
public AAYAxis categories(String[] prop) {
categories = prop;
return this;
}
public AAYAxis reversed(Boolean prop) {
reversed = prop;
return this;
}
public AAYAxis gridLineWidth(Float prop) {
gridLineWidth = prop;
return this;
}
public AAYAxis gridLineColor(String prop) {
gridLineColor = prop;
return this;
}
public AAYAxis gridLineDashStyle(String prop) {
gridLineDashStyle = prop;
return this;
}
public AAYAxis alternateGridColor(String prop) {
alternateGridColor = prop;
return this;
}
public AAYAxis gridLineInterpolation(String prop) {
gridLineInterpolation = prop;
return this;
}
public AAYAxis labels(AALabels prop) {
labels = prop;
return this;
}
public AAYAxis lineWidth(Float prop) {
lineWidth = prop;
return this;
}
public AAYAxis lineColor(String prop) {
lineColor = prop;
return this;
}
public AAYAxis off(Float prop) {
off = prop;
return this;
}
public AAYAxis allowDecimals(Boolean prop) {
allowDecimals = prop;
return this;
}
public AAYAxis max(Float prop) {
max = prop;
return this;
}
public AAYAxis min(Float prop) {
min = prop;
return this;
}
public AAYAxis tickPositions(Object[] prop) {
tickPositions = prop;
return this;
}
public AAYAxis visible(Boolean prop) {
visible = prop;
return this;
}
public AAYAxis opposite(Boolean prop) {
opposite = prop;
return this;
}
public AAYAxis tickInterval(Integer prop) {
tickInterval = prop;
return this;
}
public AAYAxis crosshair(AACrosshair prop) {
crosshair = prop;
return this;
}
public AAYAxis stackLabels(String prop) {
stackLabels = prop;
return this;
}
public AAYAxis tickWidth(Float prop) {
tickWidth = prop;
return this;
}
public AAYAxis tickLength(Float prop) {
tickLength = prop;
return this;
}
public AAYAxis tickPosition(String prop) {
tickPosition = prop;
return this;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AATools;
public class AAColor {
public static String blackColor() {
return "black";
}
public static String darkGrayColor() {
return "darkGray";
}
public static String lightGrayColor() {
return "lightGray";
}
public static String whiteColor() {
return "white";
}
public static String grayColor() {
return "gray";
}
public static String redColor() {
return "red";
}
public static String greenColor() {
return "green";
}
public static String blueColor() {
return "blue";
}
public static String cyanColor() {
return "cyan";
}
public static String yellowColor() {
return "yellow";
}
public static String magentaColor() {
return "magenta";
}
public static String orangeColor() {
return "orange";
}
public static String purpleColor() {
return "purple";
}
public static String brownColor() { return "brown"; }
public static String clearColor() {
return "clear";
}
public static String rgbaColor(
Integer red,
Integer green,
Integer blue,
Float alpha
) {
return "rgba(" + red +"," + green + "," + blue + "," + alpha + ")";
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AATools;
import java.util.HashMap;
import java.util.Map;
public class AAGradientColor {
public static HashMap<String, Object> oceanBlueColor() {
return oceanBlueColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> sanguineColor() {
return sanguineColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> lusciousLimeColor() {
return lusciousLimeColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> purpleLakeColor() {
return purpleLakeColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> freshPapayaColor() {
return freshPapayaColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> ultramarineColor() {
return ultramarineColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> pinkSugarColor() {
return pinkSugarColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> lemonDrizzleColor() {
return lemonDrizzleColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> victoriaPurpleColor() {
return victoriaPurpleColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> springGreensColor() {
return springGreensColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> mysticMauveColor() {
return mysticMauveColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> reflexSilverColor() {
return reflexSilverColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> neonGlowColor() {
return neonGlowColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> berrySmoothieColor() {
return berrySmoothieColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> newLeafColor() {
return newLeafColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> cottonCandyColor() {
return cottonCandyColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> pixieDustColor() {
return pixieDustColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> fizzyPeachColor() {
return fizzyPeachColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> sweetDreamColor() {
return sweetDreamColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> firebrickColor() {
return firebrickColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> wroughtIronColor() {
return wroughtIronColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> deepSeaColor() {
return deepSeaColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> coastalBreezeColor() {
return coastalBreezeColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> eveningDelightColor() {
return eveningDelightColor(AALinearGradientDirection.ToTop);
}
public static HashMap<String, Object> oceanBlueColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#2E3192","#1BFFFF");
}
public static HashMap<String, Object> sanguineColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#D4145A","#FBB03B");
}
public static HashMap<String, Object> lusciousLimeColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#009245","#FCEE21");
}
public static HashMap<String, Object> purpleLakeColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#662D8C","#ED1E79");
}
public static HashMap<String, Object> freshPapayaColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#ED1C24","#FCEE21");
}
public static HashMap<String, Object> ultramarineColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#00A8C5","#FFFF7E");
}
public static HashMap<String, Object> pinkSugarColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#D74177","#FFE98A");
}
public static HashMap<String, Object> lemonDrizzleColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#FB872B","#D9E021");
}
public static HashMap<String, Object> victoriaPurpleColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#312A6C","#852D91");
}
public static HashMap<String, Object> springGreensColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#009E00","#FFFF96");
}
public static HashMap<String, Object> mysticMauveColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#B066FE","#63E2FF");
}
public static HashMap<String, Object> reflexSilverColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#808080","#E6E6E6");
}
public static HashMap<String, Object> neonGlowColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#00FFA1","#00FFFF");
}
public static HashMap<String, Object> berrySmoothieColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#8E78FF","#FC7D7B");
}
public static HashMap<String, Object> newLeafColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#00537E","#3AA17E");
}
public static HashMap<String, Object> cottonCandyColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#FCA5F1","#B5FFFF");
}
public static HashMap<String, Object> pixieDustColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#D585FF","#00FFEE");
}
public static HashMap<String, Object> fizzyPeachColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#F24645","#EBC08D");
}
public static HashMap<String, Object> sweetDreamColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#3A3897","#A3A1FF");
}
public static HashMap<String, Object> firebrickColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#45145A","#FF5300");
}
public static HashMap<String, Object> wroughtIronColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#333333","#5A5454");
}
public static HashMap<String, Object> deepSeaColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#4F00BC","#29ABE2");
}
public static HashMap<String, Object> coastalBreezeColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#00B7FF","#FFFFC7");
}
public static HashMap<String, Object> eveningDelightColor(AALinearGradientDirection direction) {
return linearGradient(direction,"#93278F","#00A99D");
}
public static HashMap<String, Object> linearGradient(String startColor,
String endColor) {
return linearGradient(AALinearGradientDirection.ToTop, startColor, endColor);
}
public static HashMap<String, Object> linearGradient(
AALinearGradientDirection direction,
String startColor,
String endColor
) {
Object[][] stopsArr = new Object[][]{
{0 ,startColor},
{1 ,endColor},
};
return linearGradient(direction,stopsArr);
}
public static HashMap<String, Object> linearGradient(
AALinearGradientDirection direction,
Object[][] stopsArr
) {
Map linearGradientMap = linearGradientMap(direction);
HashMap linearGradientColorMap = new HashMap<String, Object>();
linearGradientColorMap.put("linearGradient",linearGradientMap);
linearGradientColorMap.put("stops",stopsArr);
return linearGradientColorMap;
}
/**
(0,0) ----------- (1,0)
| |
| |
| |
| |
| |
(0,1) ----------- (1,1)
*/
private static Map linearGradientMap(AALinearGradientDirection direction) {
switch (direction) {
case ToTop:
return linearGradientMap(0, 1, 0, 0);
case ToBottom:
return linearGradientMap(0, 0, 0, 1);
case ToLeft:
return linearGradientMap(1, 0, 0, 0);
case ToRight:
return linearGradientMap(0, 0, 1, 0);
case ToTopLeft:
return linearGradientMap(1, 1, 0, 0);
case ToTopRight:
return linearGradientMap(0, 1, 1, 0);
case ToBottomLeft:
return linearGradientMap(1, 0, 0, 1);
case ToBottomRight:
return linearGradientMap(0, 0, 1, 1);
default: return null;
}
}
private static Map linearGradientMap(int x1, int y1, int x2, int y2) {
Map linearGradientMap = new HashMap<String, Integer>();
linearGradientMap.put("x1",x1);
linearGradientMap.put("y1",y1);
linearGradientMap.put("x2",x2);
linearGradientMap.put("y2",y2);
return linearGradientMap;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AATools;
public class AAJSStringPurer {
public static String pureJavaScriptFunctionString(String jsFunctionStr) {
String pureJSFunctionStr = jsFunctionStr;
pureJSFunctionStr = pureJSFunctionStr.replace("'", "\"");
pureJSFunctionStr = pureJSFunctionStr.replace("\0", "");
pureJSFunctionStr = pureJSFunctionStr.replace("\n", "");
pureJSFunctionStr = pureJSFunctionStr.replace("\\", "\\\\");
pureJSFunctionStr = pureJSFunctionStr.replace("\"", "\\\"");
pureJSFunctionStr = pureJSFunctionStr.replace("\n", "\\n");
pureJSFunctionStr = pureJSFunctionStr.replace("\r", "\\r");
pureJSFunctionStr = pureJSFunctionStr.replace("\f", "\\f");
pureJSFunctionStr = pureJSFunctionStr.replace("\u2028", "\\u2028");
pureJSFunctionStr = pureJSFunctionStr.replace("\u2029","\\u2029" );
return pureJSFunctionStr;
}
}
package com.gingersoft.gsa.cloud.ui.AAChartCore.AAChartCoreLib.AATools;
public enum AALinearGradientDirection {
ToTop, //⇧⇧⇧⇧⇧⇧
ToBottom, //⇩⇩⇩⇩⇩⇩
ToLeft, //⇦⇦⇦⇦⇦⇦
ToRight, //⇨⇨⇨⇨⇨⇨
ToTopLeft, //⇖⇖⇖⇖⇖⇖
ToTopRight, //⇗⇗⇗⇗⇗⇗
ToBottomLeft, //⇙⇙⇙⇙⇙⇙
ToBottomRight, //⇘⇘⇘⇘⇘⇘
}
...@@ -12,6 +12,5 @@ include 'cc-register', ...@@ -12,6 +12,5 @@ include 'cc-register',
'table-mode', 'table-mode',
'demo_interceptors', 'demo_interceptors',
'print-module', 'print-module',
'chart',
rootProject.name = 'GSA-Cloud' , 'pools' rootProject.name = 'GSA-Cloud' , 'pools'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment