本文介绍了Android 曲线图的绘制示例代码,分享给大家,具体如下:
效果展示
效果展示.gif
使用方式
// 初始化数据表格相关
with(mTableView) {
// 配置坐标系
setupCoordinator("日", "人", /*这里是横坐标的值*/0f, 5f, 10f, 15f, 20f, 25f, 30f)
// 添加曲线, 确保纵坐标的数值位数相等
addWave(ContextCompat.getColor(this@MainActivity, R.color.colorYellow), false,
0f, 10f, 30f, 54f, 30f, 100f, 10f)
addWave(ContextCompat.getColor(this@MainActivity, R.color.colorGreen), false,
0f, 30f, 20f, 20f, 46f, 25f, 5f)
addWave(ContextCompat.getColor(this@MainActivity, R.color.colorPink), false,
0f, 30f, 20f, 50f, 46f, 30f, 30f)
addWave(Color.parseColor("#8596dee9"), true,
0f, 15f, 10f, 10f, 40f, 20f, 5f)
}
实现思路
代码实现
/**
* Created by FrankChoo on 2017/12/29.
* Email: frankchoochina@gmail.com
* Version: 1.0
* Description: 表格自定义View
*/
public class TableView extends View {
private List<WaveConfigData> mWaves;// 数值集合
// 坐标轴的数值
private int mCoordinateYCount = 8;
private float[] mCoordinateXValues;// 外界传入
private float[] mCoordinateYValues;// 动态计算
// 坐标的单位
private String mXUnit;
private String mYUnit;
// 所有曲线中所有数据中的最大值
private float mGlobalMaxValue;// 用于确认是否需要调整坐标系
private Paint mCoordinatorPaint;
private Paint mTextPaint;
private Paint mWrapPaint;
// 坐标轴上描述性文字的空间大小
private int mTopUnitHeight;// 顶部Y轴单位高度
private int mBottomTextHeight;
private int mLeftTextWidth;
// 网格尺寸
private int mGridWidth, mGridHeight;
private float mAnimProgress;
public TableView(Context context) {
this(context, null);
}
public TableView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public TableView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
post(new Runnable() {
@Override
public void run() {
showAnimator();
}
});
}
private void init() {
// 初始化数据集合的容器
mWaves = new ArrayList<>();
// 坐标系的单位
mBottomTextHeight = dp2px(40);// X轴底部字体的高度
mLeftTextWidth = mBottomTextHeight;// Y轴左边字体的宽度
mTopUnitHeight = dp2px(30);// 顶部Y轴的单位
// 初始化坐标轴Paint
mCoordinatorPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mCoordinatorPaint.setColor(Color.LTGRAY);
// 初始化文本Paint
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mTextPaint.setColor(Color.GRAY);
mTextPaint.setTextSize(sp2px(12));
// 初始化曲线Paint
mWrapPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mWrapPaint.setPathEffect(new CornerPathEffect(200f));
}
/**
* 配置坐标轴信息
*
* @param xUnit X 轴的单位
* @param yUnit Y 轴的单位
* @param coordinateXValues X 坐标轴上的数值
*/
public void setupCoordinator(String xUnit, String yUnit, float... coordinateXValues) {
mXUnit = xUnit;
mYUnit = yUnit;
mCoordinateXValues = coordinateXValues;
}
/**
* 添加一条曲线, 确保与横坐标的数值对应
*
* @param color
* @param isCoverRegion
* @param values
*/
public void addWave(int color, boolean isCoverRegion, float... values) {
mWaves.add(new WaveConfigData(color, isCoverRegion, values));
// 根据value的值去计算纵坐标的数值
float maxValue = 0;
for (float value : values) {
maxValue = Math.max(maxValue, value);
}
if (maxValue < mGlobalMaxValue) return;
mGlobalMaxValue = maxValue;
// 保证网格的数值都为 5 的倍数
float gridValue = mGlobalMaxValue / (mCoordinateYCount - 1);
if (gridValue % 5 != 0) {
gridValue += 5 - (gridValue % 5);
}
// 给纵坐标的数值赋值
mCoordinateYValues = new float[mCoordinateYCount];
for (int i = 0; i < mCoordinateYCount; i++) {
mCoordinateYValues[i] = i * gridValue;
}
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
drawCoordinate(canvas);
drawWrap(canvas);
}
public void showAnimator() {
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f).setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mAnimProgress = (float) animation.getAnimatedValue();
invalidate();
}
});
animator.start();
}
/**
* 绘制坐标系
*/
private void drawCoordinate(Canvas canvas) {
Point start = new Point();
Point stop = new Point();
// 1. 绘制横轴线和纵坐标单位
int xLineCount = mCoordinateYValues.length;
mGridHeight = (getHeight() - getPaddingTop() - getPaddingBottom() - mBottomTextHeight - mTopUnitHeight) / (xLineCount - 1);
for (int i = 0; i < xLineCount; i++) {
start.x = getPaddingLeft() + mLeftTextWidth;
start.y = getHeight() - getPaddingBottom() - mBottomTextHeight - mGridHeight * i;
stop.x = getRight() - getPaddingRight();
stop.y = start.y;
// 绘制横轴线
canvas.drawLine(start.x, start.y, stop.x, stop.y, mCoordinatorPaint);
// 绘制纵坐标单位
if (i == 0) continue;
String drawText = String.valueOf((int) mCoordinateYValues[i]);
Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
float offsetY = ((fontMetrics.bottom - fontMetrics.top) / 2 + fontMetrics.bottom) / 2;
float baseLine = start.y + offsetY;
float left = getPaddingLeft() + mLeftTextWidth / 2 - mTextPaint.measureText(drawText) / 2;
canvas.drawText(drawText, left, baseLine, mTextPaint);
// 绘制Y轴单位
if (i == xLineCount - 1) {
drawText = mYUnit;
baseLine = getPaddingTop() + mTopUnitHeight / 2;
canvas.drawText(drawText, left, baseLine, mTextPaint);
}
}
// 2. 绘制纵轴线和横坐标单位
int yLineCount = mCoordinateXValues.length;
mGridWidth = (getWidth() - getPaddingLeft() - getPaddingRight() - mLeftTextWidth) / (yLineCount - 1);
for (int i = 0; i < yLineCount; i++) {
start.x = getPaddingTop() + mLeftTextWidth + mGridWidth * i;
start.y = getPaddingTop() + mTopUnitHeight;
stop.x = start.x;
stop.y = getHeight() - mBottomTextHeight - getPaddingBottom();
// 绘制纵轴线
canvas.drawLine(start.x, start.y, stop.x, stop.y, mCoordinatorPaint);
// 绘制横坐标单位
String drawText = String.valueOf((int) mCoordinateXValues[i]);
Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
float offsetY = ((fontMetrics.bottom - fontMetrics.top) / 2 + fontMetrics.bottom) / 2;
float baseLine = getHeight() - getPaddingBottom() - mBottomTextHeight / 2 + offsetY;
float left = start.x - mTextPaint.measureText(drawText) / 2;
// 绘制X轴单位
if (i == 0) {
drawText = mXUnit;
left = getPaddingLeft() + mLeftTextWidth / 2 - mTextPaint.measureText(drawText) / 2;
}
canvas.drawText(drawText, left, baseLine, mTextPaint);
}
}
/**
* 绘制曲线
*/
private void drawWrap(Canvas canvas) {
canvas.clipRect(new RectF(
mLeftTextWidth,
getPaddingTop() + mTopUnitHeight,
(getRight() - getPaddingRight()) * mAnimProgress,
getHeight() - getPaddingBottom() - mBottomTextHeight)
);
float yHeight = mGridHeight * (mCoordinateYCount - 1);
for (WaveConfigData wave : mWaves) {
Path path = new Path();
path.moveTo(0, getHeight());
float maxY = mCoordinateYValues[mCoordinateYCount - 1];// Y轴坐标的最大值
for (int index = 1; index < wave.values.length; index++) {
path.lineTo(
mLeftTextWidth + mGridWidth * index,
getHeight() - getPaddingBottom() - mBottomTextHeight
- yHeight * (wave.values[index] / maxY)
);
}
if (wave.isCoverRegion) {
mWrapPaint.setStyle(Paint.Style.FILL);
path.lineTo(getRight() - getPaddingRight(), getHeight());
path.close();
} else {
mWrapPaint.setStyle(Paint.Style.STROKE);
mWrapPaint.setStrokeWidth(10);
}
mWrapPaint.setColor(wave.color);
canvas.drawPath(path, mWrapPaint);
}
}
private int dp2px(float dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dp, getResources().getDisplayMetrics());
}
private int sp2px(float sp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
sp, getResources().getDisplayMetrics());
}
public static class WaveConfigData {
int color;
boolean isCoverRegion;
float values[];
public WaveConfigData(int color, boolean isCoverRegion, float[] values) {
this.color = color;
this.isCoverRegion = isCoverRegion;
this.values = values;
}
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
我画了4条线从中心到按钮,我给你看的照片。我不知道如何在图片中画出红色的曲线。 [在此处输入图像说明] 或 [在此输入图像说明(更简单)]
本文向大家介绍Python绘制3d螺旋曲线图实例代码,包括了Python绘制3d螺旋曲线图实例代码的使用技巧和注意事项,需要的朋友参考一下 Line plots 绘制2D或3D数据 参数 描述 xs, ys X轴,Y轴坐标定点 zs Z值,每一个点的值都是1 zdir 绘制2D集合时使用z的方向 其他的参数:plot() Python代码: 效果图: 总结 以上就是本文关于Python绘制3d螺旋
本文向大家介绍C#绘制曲线图的方法,包括了C#绘制曲线图的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#绘制曲线图的方法。分享给大家供大家参考。具体如下: 1. 曲线图效果: 2. C#代码: 3. 数据缩小一个级别的效果: 4. 完整代码 DrawingCurve.cs: 希望本文所述对大家的C#程序设计有所帮助。
本文向大家介绍WPF如何绘制光滑连续贝塞尔曲线示例代码,包括了WPF如何绘制光滑连续贝塞尔曲线示例代码的使用技巧和注意事项,需要的朋友参考一下 1.需求 WPF本身没有直接把点集合绘制成曲线的函数。可以通过贝塞尔曲线函数来绘制。 贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。当然在一些比较成熟的位图软件中也有贝塞尔曲线工
本文向大家介绍python绘制分布折线图的示例,包括了python绘制分布折线图的示例的使用技巧和注意事项,需要的朋友参考一下 用Python 绘制分布(折线)图,使用的是 plot()函数。 一个简单的例子: 结果: 以上就是python绘制分布折线图的示例代码的详细内容,更多关于python绘制分布折线图的资料请关注呐喊教程其它相关文章!
问题内容: 我正在尝试用Java绘制曲线。一个简单的以(X,Y)开始,(X,Y)结束和曲线量的贝塞尔曲线就足够了。 我找不到在Swing中执行此操作的方法。如果不在Swing中,我可以使用一些简单的数学方法吗?我将如何在Swing中实现它? 编辑:我知道如何通过重写paint(Graphics g)方法绘制形状和线条。 问题答案: 您可以使用Java 2D Object Path2D.Double