android坐标图绘制曲线,Android 曲线图 绘制曲线
Android 曲线图
Paste_Image.png
这里我引用了上回介绍的 折线图
首先我们看看onDrwa 里面做了什么 从图里面我们可看到 绘制的框线方法,绘制data线方法 绘制线上的圆
从最上面的图效果来看我们不需要圆 也不需要折线,但是框线要保留 因此我们需要 把
这个几个方法 改成public ,到时候继承之后重写他 不调用父方法即可
Paste_Image.png
Paste_Image.png
接下来我们创建一个 类继承 DrawLineChart 重写 DrawLineCircle,DrawLine 方法
这样我们就保留 了框线, 取消了圆和折线的绘制
接下来在DrawLine 里面绘制曲线
@Override
public void DrawLine(Canvas canvas) {
Path mPath=new Path();
for(int j = 0; j < mPoints.length; j++) {
Point startp = mPoints[j];
Point endp;
if (j != mPoints.length - 1) {
endp = mPoints[j + 1];
int wt = (startp.x + endp.x) / 2;
Point p3 = new Point();
Point p4 = new Point();
p3.y = startp.y;
p3.x = wt;
p4.y = endp.y;
p4.x = wt;
if (j == 0) {
mPath.moveTo(startp.x, startp.y);
}
/**
*添加一个立方贝塞尔曲线的最后一点,接近控制点
*(x1,y1)和(x2,y2),到最后(x3,y3)。如果没有移至()调用
*为这个轮廓,第一点是自动设置为(0,0)。
*
* @param x1的坐标1立方曲线控制点
* @param y1第一控制点的坐标一立方曲线
* @param x2上第二个控制点的坐标一立方曲线
* @param y2第二控制点的坐标一立方曲线
* @param x3的坐标三次曲线的终点
* @param y3终点坐标的三次曲线
*
*/
mPath.cubicTo(p3.x, p3.y, p4.x, p4.y, endp.x, endp.y);
}
}
/**这里直接使用了折线的画笔,你也可以在此类在定义一个画笔*/
canvas.drawPath(mPath,getBrokenLinePaint());
}
什么, 你不光要曲线,。 还要填充式的怎么办,这个时候你就需要将你的曲线连接起来 起点到终点连接起来 将画笔Style 改为FILL ,怎么连? 看图,从图上 我们可以看到
终点x,终点y 连接到 终点x,底部y
终点x,底部y 连接到 起点x,底部y
起点x 底部y 连接到 起点x,起点y
Paste_Image.png
根据上面的分析 我们代码 就是这样的了
@Override
public void DrawLine(Canvas canvas) {
Path mPath=new Path();
for(int j = 0; j < mPoints.length; j++) {
Point startp = mPoints[j];
Point endp;
if (j != mPoints.length - 1) {
endp = mPoints[j + 1];
int wt = (startp.x + endp.x) / 2;
Point p3 = new Point();
Point p4 = new Point();
p3.y = startp.y;
p3.x = wt;
p4.y = endp.y;
p4.x = wt;
if (j == 0) {
mPath.moveTo(startp.x, startp.y);
}
/**
*添加一个立方贝塞尔曲线的最后一点,接近控制点
*(x1,y1)和(x2,y2),到最后(x3,y3)。如果没有移至()调用
*为这个轮廓,第一点是自动设置为(0,0)。
*
* @param x1的坐标1立方曲线控制点
* @param y1第一控制点的坐标一立方曲线
* @param x2上第二个控制点的坐标一立方曲线
* @param y2第二控制点的坐标一立方曲线
* @param x3的坐标三次曲线的终点
* @param y3终点坐标的三次曲线
*
*/
mPath.cubicTo(p3.x, p3.y, p4.x, p4.y, endp.x, endp.y);
}else {
/**连接到终点x,底部y*/
mPath.lineTo(startp.x,getNeedDrawHeight()+getBrokenLineTop());
/**连接到起点x,底部y*/
mPath.lineTo(mPoints[0].x,getNeedDrawHeight()+getBrokenLineTop());
/**连接到起点x,起点y*/
mPath.lineTo(mPoints[0].x,mPoints[0].y);
}
}
Paint paint=getBrokenLinePaint();
/**修改画笔属性*/
paint.setStyle(Paint.Style.FILL);
canvas.drawPath(mPath,getBrokenLinePaint());
}
效果图
Paste_Image.png
完整代码
package com.app_chart;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
public class CurveChart extends DrawLineChart {
public CurveChart(Context context) {
super(context);
}
public CurveChart(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public void DrawLineCircle(Canvas canvas) {
}
@Override
public void DrawLine(Canvas canvas) {
Path mPath=new Path();
for(int j = 0; j < mPoints.length; j++) {
Point startp = mPoints[j];
Point endp;
if (j != mPoints.length - 1) {
endp = mPoints[j + 1];
int wt = (startp.x + endp.x) / 2;
Point p3 = new Point();
Point p4 = new Point();
p3.y = startp.y;
p3.x = wt;
p4.y = endp.y;
p4.x = wt;
if (j == 0) {
mPath.moveTo(startp.x, startp.y);
}
/**
*添加一个立方贝塞尔曲线的最后一点,接近控制点
*(x1,y1)和(x2,y2),到最后(x3,y3)。如果没有移至()调用
*为这个轮廓,第一点是自动设置为(0,0)。
*
* @param x1的坐标1立方曲线控制点
* @param y1第一控制点的坐标一立方曲线
* @param x2上第二个控制点的坐标一立方曲线
* @param y2第二控制点的坐标一立方曲线
* @param x3的坐标三次曲线的终点
* @param y3终点坐标的三次曲线
*
*/
mPath.cubicTo(p3.x, p3.y, p4.x, p4.y, endp.x, endp.y);
}else {
/**连接到终点x,底部y*/
mPath.lineTo(startp.x,getNeedDrawHeight()+getBrokenLineTop());
/**连接到起点x,底部y*/
mPath.lineTo(mPoints[0].x,getNeedDrawHeight()+getBrokenLineTop());
/**连接到起点x,起点y*/
mPath.lineTo(mPoints[0].x,mPoints[0].y);
}
}
Paint paint=getBrokenLinePaint();
/**修改画笔属性*/
paint.setStyle(Paint.Style.FILL);
canvas.drawPath(mPath,getBrokenLinePaint());
}
}
Activity 调用
Paste_Image.png
DrawLineChart 代码
package com.app_chart;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import java.text.DecimalFormat;
public class DrawLineChart extends View {
private static final String TAG = "DrawLineChart";
/**View宽度*/
private int mViewWidth;
/** View高度*/
private int mViewHeight;
/**边框线画笔*/
private Paint mBorderLinePaint;
/**文本画笔*/
private Paint mTextPaint;
/**要绘制的折线线画笔*/
private Paint mBrokenLinePaint;
/**折线文本画笔*/
private Paint mBrokenLineTextPaint;
/**圆画笔*/
private Paint mCirclePaint;
/**横线画笔*/
private Paint mHorizontalLinePaint;
/**圆的厚度*/
private float mCircleWidth=2;
/**圆的半径*/
private float radius=5;
/**边框的左边距*/
private float mBrokenLineLeft=dip2px(30);
/**边框的上边距*/
private float mBrokenLineTop=dip2px(10);
/**边框的下边距*/
private float mBrokenLineBottom=dip2px(20);
/**边框的右边距*/
private float mBrokenLinerRight=dip2px(10);
/**需要绘制的宽度*/
private float mNeedDrawWidth;
/**需要绘制的高度*/
private float mNeedDrawHeight;
/**数据值*/
private float[] value=new float[]{-5.55f,-6.899f,-4.55f,-0.045f,21.511f,22.221f,22.330f,21.448f,21.955f,23.6612f,22,22.18883f,21.47995f};
/**图表的最大值*/
private float maxVlaue=27.55f;
/**图表的最小值*/
private float minValue=-19.12f;
/**要计算的总值*/
private float calculateValue;
/**框线平均值*/
private float averageValue;
/**横线数量*/
private float numberLine=5;
/**边框线颜色*/
private int mBorderLineColor=Color.BLACK;
/**边框线的宽度*/
private int mBorderWidth=2;
/**边框文本颜色*/
private int mBorderTextColor=Color.GRAY;
/**边框文本大小*/
private float mBorderTextSize=20;
/**边框横线颜色*/
private int mBorderTransverseLineColor=Color.GRAY;
/**边框横线宽度*/
private float mBorderTransverseLineWidth=2;
/**折线颜色*/
private int mBrokenLineColor=Color.BLUE;
/**折线文本颜色*/
private int mBrokenLineTextColor=Color.BLUE;
/**折线宽度*/
private float mBrokenLineWidth=2;
/**折线文本大小*/
private float mBrokenLineTextSize=15;
/**折线圆的颜色*/
private int mCircleColor=Color.BLUE;
/**计算后的x,y坐标*/
public Point[] mPoints;
/**圆的半径*/
public void setRadius(float radius) {
this.radius = dip2px(radius);
}
/**设置宽度*/
public void setCircleWidth(float circleWidth){
this.mCircleWidth=dip2px(circleWidth);
}
/**设置边框左上右下边距*/
public void setBrokenLineLTRB(float l,float t,float r,float b){
mBrokenLineLeft=dip2px(l);
mBrokenLineTop=dip2px(t);
mBrokenLinerRight=dip2px(r);
mBrokenLineBottom=dip2px(b);
}
public int getViewWidth() {
return mViewWidth;
}
public int getViewHeight() {
return mViewHeight;
}
public float getCircleWidth() {
return mCircleWidth;
}
public float getRadius() {
return radius;
}
public float getBrokenLineLeft() {
return mBrokenLineLeft;
}
public float getBrokenLineTop() {
return mBrokenLineTop;
}
public float getBrokenLineBottom() {
return mBrokenLineBottom;
}
public float getBrokenLinerRight() {
return mBrokenLinerRight;
}
public float getNeedDrawWidth() {
return mNeedDrawWidth;
}
public float getNeedDrawHeight() {
return mNeedDrawHeight;
}
public Point[] getPoints() {
return mPoints;
}
/**数据data*/
public void setValue(float[] value) {
this.value = value;
}
/**图表显示最大值*/
public void setMaxVlaue(float maxVlaue) {
this.maxVlaue = maxVlaue;
}
/**图表显示最小值*/
public void setMinValue(float minValue) {
this.minValue = minValue;
}
/**图表横线数量*/
public void setNumberLine(float numberLine) {
this.numberLine = numberLine;
}
/**边框线颜色*/
public void setBorderLineColor(int borderLineColor) {
mBorderLineColor = borderLineColor;
}
/**边框文本颜色*/
public void setBorderTextColor(int borderTextColor) {
mBorderTextColor = borderTextColor;
}
/**边框文本大小*/
public void setBorderTextSize(float borderTextSize) {
mBorderTextSize = dip2px(borderTextSize);
}
/**框线横线 颜色*/
public void setBorderTransverseLineColor(int borderTransverseLineColor) {
mBorderTransverseLineColor = borderTransverseLineColor;
}
/**边框内折线颜色*/
public void setBrokenLineColor(int brokenLineColor) {
mBrokenLineColor = brokenLineColor;
}
/** 折线文本颜色*/
public void setBrokenLineTextColor(int brokenLineTextColor) {
mBrokenLineTextColor = brokenLineTextColor;
}
/**折线文本大小*/
public void setBrokenLineTextSize(float brokenLineTextSize) {
mBrokenLineTextSize = dip2px(brokenLineTextSize);
}
/**折线圆颜色*/
public void setCircleColor(int circleColor) {
mCircleColor = dip2px(circleColor);
}
/**边框线宽度*/
public void setBorderWidth(float borderWidth) {
mBorderWidth = dip2px(borderWidth);
}
/**边框横线宽度*/
public void setBorderTransverseLineWidth(float borderTransverseLineWidth) {
mBorderTransverseLineWidth = dip2px(borderTransverseLineWidth);
}
/**折线宽度*/
public void setBrokenLineWidth(float brokenLineWidth) {
mBrokenLineWidth = dip2px(brokenLineWidth);
}
/**获取框线画笔*/
public Paint getBorderLinePaint() {
return mBorderLinePaint;
}
/**获取边框文本画笔*/
public Paint getTextPaint() {
return mTextPaint;
}
/**获取折线画笔*/
public Paint getBrokenLinePaint() {
return mBrokenLinePaint;
}
/**获取折线文本画笔*/
public Paint getBrokenLineTextPaint() {
return mBrokenLineTextPaint;
}
/**获取圆画笔*/
public Paint getCirclePaint() {
return mCirclePaint;
}
/**获取边框横线画笔*/
public Paint getHorizontalLinePaint() {
return mHorizontalLinePaint;
}
/**
* 将dip或dp值转换为px值,保证尺寸大小不变
*
* @param dipValue
* @return
*/
private int dip2px( float dipValue) {
final float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
public DrawLineChart(Context context) {
super(context);
initPaint();
}
public DrawLineChart(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initPaint();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mViewHeight = getMeasuredHeight();
mViewWidth = getMeasuredWidth();
/**计算总值*/
calculateValue=maxVlaue-minValue;
initNeedDrawWidthAndHeight();
/**计算框线横线间隔的数据平均值*/
averageValue = calculateValue/(numberLine-1);
}
/**初始化绘制折线图的宽高*/
private void initNeedDrawWidthAndHeight(){
mNeedDrawWidth = mViewWidth-mBrokenLineLeft-mBrokenLinerRight;
mNeedDrawHeight = mViewHeight-mBrokenLineTop-mBrokenLineBottom;
}
/**初始化画笔*/
private void initPaint() {
/**初始化边框文本画笔*/
if(mTextPaint==null){
mTextPaint=new Paint();
initPaint(mTextPaint);
}
mTextPaint.setTextSize(mBorderTextSize);
mTextPaint.setTextAlign(Paint.Align.RIGHT);
mTextPaint.setColor(Color.GRAY);
/**初始化边框线画笔*/
if(mBorderLinePaint==null){
mBorderLinePaint=new Paint();
initPaint(mBorderLinePaint);
}
mBorderLinePaint.setTextSize(mBorderTextSize);
mBorderLinePaint.setStrokeWidth(mBorderWidth);
mBorderLinePaint.setColor(mBorderLineColor);
/**初始化折线画笔*/
if(mBrokenLinePaint==null){
mBrokenLinePaint=new Paint();
initPaint(mBrokenLinePaint);
}
mBrokenLinePaint.setStrokeWidth(mBrokenLineWidth);
mBrokenLinePaint.setColor(mBrokenLineColor);
if(mCirclePaint==null){
mCirclePaint=new Paint();
initPaint(mCirclePaint);
}
mCirclePaint.setStrokeWidth(mCircleWidth);
mCirclePaint.setColor(mCircleColor);
/**折线文本画笔*/
if (mBrokenLineTextPaint == null){
mBrokenLineTextPaint=new Paint();
initPaint(mBrokenLineTextPaint);
}
mBrokenLineTextPaint.setTextAlign(Paint.Align.CENTER);
mBrokenLineTextPaint.setColor(mBrokenLineTextColor);
mBrokenLineTextPaint.setTextSize(mBrokenLineTextSize);
/**横线画笔*/
if (mHorizontalLinePaint == null){
mHorizontalLinePaint=new Paint();
initPaint(mHorizontalLinePaint);
}
mHorizontalLinePaint.setStrokeWidth(mBorderTransverseLineWidth);
mHorizontalLinePaint.setColor(mBorderTransverseLineColor);
}
/**初始化画笔默认属性*/
private void initPaint(Paint paint){
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPoints = getPoints(value,mNeedDrawHeight,mNeedDrawWidth,calculateValue,minValue,mBrokenLineLeft,mBrokenLineTop);
/**绘制边框线和边框文本*/
DrawBorderLineAndText(canvas);
/**根据数据绘制线*/
DrawLine(canvas);
/**绘制圆*/
DrawLineCircle(canvas);
}
/**绘制线上的圆*/
public void DrawLineCircle(Canvas canvas) {
for (int i = 0; i
Point point=mPoints[i];
mCirclePaint.setColor(Color.WHITE);
mCirclePaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(point.x,point.y,radius,mCirclePaint);
mCirclePaint.setColor(mCircleColor);
mCirclePaint.setStyle(Paint.Style.STROKE);
/**
* drawCircle(float cx, float cy, float radius, Paint paint)
* cx 中间x坐标
* xy 中间y坐标
* radius 圆的半径
* paint 绘制圆的画笔
* */
canvas.drawCircle(point.x,point.y,radius,mCirclePaint);
}
}
/**根据值绘制折线*/
public void DrawLine(Canvas canvas) {
Path mPath=new Path();
for (int i = 0; i < mPoints.length; i++) {
Point point=mPoints[i];
if(i==0){
mPath.moveTo(point.x,point.y);
}else {
mPath.lineTo(point.x,point.y);
}
canvas.drawText(value[i]+"",point.x,point.y-radius,mBrokenLineTextPaint);
}
canvas.drawPath(mPath,mBrokenLinePaint);
}
/**绘制边框线和边框文本*/
private void DrawBorderLineAndText(Canvas canvas) {
/**对应的属性
* drawLine(float startX, float startY, float stopX, float stopY, Paint paint);
* startX 开始的x坐标
* startY 开始的y坐标
* stopX 结束的x坐标
* stopY 结束的y坐标
* paint 绘制该线的画笔
* */
/**绘制边框竖线*/
canvas.drawLine(mBrokenLineLeft,mBrokenLineTop-dip2px(5),mBrokenLineLeft,mViewHeight-mBrokenLineBottom,mBorderLinePaint);
/**绘制边框横线*/
canvas.drawLine(mBrokenLineLeft,mViewHeight-mBrokenLineBottom,mViewWidth,mViewHeight-mBrokenLineBottom,mBorderLinePaint);
/**绘制边框分段横线与分段文本*/
float averageHeight=mNeedDrawHeight/(numberLine-1);
for (int i = 0; i < numberLine; i++) {
float nowadayHeight= averageHeight*i;
float v=averageValue*(numberLine-1-i)+minValue;
/**最后横线无需绘制,否则会将边框横线覆盖*/
if(i!=numberLine-1) {
canvas.drawLine(mBrokenLineLeft, nowadayHeight + mBrokenLineTop, mViewWidth, nowadayHeight + mBrokenLineTop, mHorizontalLinePaint);
}
canvas.drawText(floatKeepTwoDecimalPlaces(v)+"",mBrokenLineLeft-dip2px(2),nowadayHeight+mBrokenLineTop,mTextPaint);
}
/**竖线*/
for (int i = 1; i < mPoints.length; i++) {
//canvas.drawLine(mPoints[i].x,mBrok enLineTop,mPoints[i].x,mBrokenLineTop+mNeedDrawHeight,mBorderLinePaint);
}
}
/**保留2位小数*/
private String floatKeepTwoDecimalPlaces(float f){
DecimalFormat decimalFormat=new DecimalFormat("0.00");//构造方法的字符格式这里如果小数不足2位,会以0补足.
String p=decimalFormat.format(f);
return p;
}
/**根据值计算在该值的 x,y坐标*/
public Point[] getPoints(float[] values, float height, float width, float max ,float min, float left,float top) {
float leftPading = width / (values.length-1);//绘制边距
Point[] points = new Point[values.length];
for (int i = 0; i < values.length; i++) {
double value = values[i]-min;
//计算每点高度所以对应的值
double mean = (double) max/height;
//获取要绘制的高度
float drawHeight = (float) (value / mean);
int pointY = (int) (height+top - drawHeight);
int pointX = (int) (leftPading * i + left);
Point point = new Point(pointX, pointY);
points[i] = point;
}
return points;
}
}
android坐标图绘制曲线,Android 曲线图 绘制曲线相关推荐
- android 坐标图绘制曲线,Android艺术之画一条平滑的曲线
前言 说的是曲线,其实想法是来自一个曲线图的需求.图表这种东西,项目开发中也不少见,大多情况找个通用的开源框架改改就得了(老板们别打我),然而通用赶不上脑洞,要做交互和视觉比较特别的图表时,还是自己造 ...
- android坐侧菜单栏,SlidingLayoutDemo android左侧菜单栏的实现 - 下载 - 搜珍网
SlidingLayoutDemo(修正版)/ SlidingLayoutDemo(修正版)/SlidingLayoutDemo/ SlidingLayoutDemo(修正版)/SlidingLayo ...
- Android 曲线图绘制
最近项目里要做一个简单的曲线图来标识数据,开始以为很简单,android已经有那么多的开源图表库了,什么achartenginee,hellochart,mpandroidchart等等,下载Demo ...
- android 动态绘制布局,Android代码和绘制曲线中按钮和绘图板的动态布局
时间: 2019年1月11日 本文向您介绍Android代码中的按钮和绘图板的动态布局和绘制曲线,主要包括示例android 动态绘制曲线,应用技巧,基本知识和知识android 动态绘制曲线,包括A ...
- Android之使用AchartEngineActivity引擎绘制柱状图、曲线图
1.简介 AChartEngine(简称ACE)是Google的一个开源图表库(for Android).它功能强大,支持散点图.折线 .关于里面类的具体使用,请下载响应的文档说明(主页上有). 2. ...
- android 布局中绘制语音曲线,Android仿百度地图小度语音助手的贝塞尔曲线动画
本文为大家分享了Android仿小度语音助手的贝塞尔曲线动画,供大家参考,具体内容如下 废话不多说,看下面的动图,和百度的还是有点点差别,我也不修改了,很简单,我实在是没有多余的时间,还要学习其他的东 ...
- python绘制坐标系_python库matplotlib绘制坐标图
很多时候我们数据处理的时候要画坐标图,下面我用第三方库matplotlib以及scipy绘制光滑的曲线图 需要安装的库有 matplotlib,scipy, numpy import matplotl ...
- android折线图,简单的android折线图绘制
上图 说到android的折线图,我就必须要说一下关于绘制view的几个重要的工具,Canvas(画布),Paint(画笔),Path(路径). Canvas顾名思义就是用来作画的板子或者说是布.没有 ...
- 运用python库matplotlib绘制坐标图
很多时候我们数据处理的时候要画坐标图,下面我用第三方库matplotlib以及scipy绘制光滑的曲线图 需要安装的库有 matplotlib,scipy, numpy import matplotl ...
最新文章
- Py之PyAutoGUI:python库之PyAutoGUI的简介、安装、使用方法
- JSP简单练习-定时刷新页面
- 安装flex碰到的一个问题及其解决方法(原创)
- java web 通过servlet访问web_inf jsp跳转_WEB-INF下的jsp通过servlet中超链接跳转
- C++ 虚函数表解析 继承
- Linux里面nginx显示Hello,Nginx得知——Hello World模
- Flask - 基础
- Hacker Plus:Facebook 推出漏洞奖励 “忠诚计划”
- php判断是不是手机端访问
- vxworks中断初始化以及挂接分析
- 在python中、下列代码的输出是什么-智慧树知到《Python程序设计基础》章节测试答案...
- matlab自定义颜色代码,自定义颜色为matlab表面图
- http错误码分析和解决
- 节点name在graph中无法展示_小节点 · 大奥秘│这正是你想学习的精妙休闲观景空间!(内含视频讲解)...
- 黑盒测试---等价类划分
- Python 元组大全
- 为什么说衰老先从血管开始?
- WPF UnhandledException
- android状态栏右上角增加图标的方法
- 1t硬盘怎么分区最好_1t硬盘怎么分区合理
热门文章
- cesium-加载DEM数据
- java从入门到精通 pdf
- iconfont阿里巴巴矢量图标库的使用
- c语言俄罗斯方块代码及实验报告,c语言俄罗斯方块实验报告.doc
- android的本地通讯录获取以及RecyclerView展示
- Nachos Lab4 文件系统
- python excel 之 按格式生成图表和数据
- 软件需求规格说明书模板有吗
- SkeyeVSS国标视频汇聚云服务使用Onvif、GB28181协议对监控摄像机设备进行PTZ云台控制
- stm32 adc输入电压范围_正点原子【STM32-F407探索者】第二十五章 光敏传感器实验...