结合自己的一些理解和整理 将Json数据格式 (只展现一部分 )中的经纬度 转化为 x,y 坐标 在Canvas 中画线
实现思路:
(1)首先根据一串经纬度中的最小的经度最小纬度创建坐标原点。
(2)根据设备屏幕大小与最大的经纬度差求得宽高比。
(3)格式化经纬度点,将其转为X Y坐标点。需要注意的是:安卓手机的坐标原点是手机的左上角,Y轴越往下数值越大,但是(北)纬度越往下越小,需要做绝对值转换;
1.布局文件 一定要设置id 这个就是Canvas 可以根据需求自己设定大小
2.Activity
该activity主要处理经纬度数据、获取屏幕的宽高,具体的绘制过程在DrawView中。
代码简单贴一下:
(1)获取传来的经纬度数组【经度 纬度分开传输】;
(2)剔除数组里面为0.0的数据;如保证无此类数据,可删除此段代码;
(3)获取屏幕的宽高,这里可以自己根据上方 布局文件的 宽高 写成固定值 在下方有代码展示;
(4)实例化canvas,DrawView,将context,屏幕宽,屏幕高,纬度坐标数组,经度坐标数组)传进去;
(5)绘制组件
在点击事件中调用 initView 进行初始化 我这里的点击事件是响应item点击事件
private ContentAdapter.MyClickListener mListener = new ContentAdapter.MyClickListener() {
@Override
public void myOnClick(int position, View v) {
initView((JSONArray) listItem.get(position).get("stations"));
}
};
或者最简单的点击调用
public void onClick(View v) {
switch (v.getId()) {
case R.id.charge:
initView(输入的数据)
}
}
//jsonArray 为数据 就是你要传入的数据 我这里传入的是json数组
private void initView(JSONArray jsonArray) {
RelativeLayout layout = (RelativeLayout) findViewById(R.id.can);
DrawView views = new DrawView(this);
views.setJsonArray(jsonArray);
views.setMinimumHeight(500);
views.setMinimumWidth(300);
//通知view组件重绘
views.invalidate();
layout.addView(views);
}
3.DrawView 主要的绘制工作在此View中进行
3.1实例化 接收数据;
public class DrawView extends View {
private JSONArray jsonArray;
private double latData[] = null; //经纬度存放数据的数组
private double lonData[] = null; //经纬度存放数据的数组
private double latDataSort[];
private double lotDataSort[];
double lonOrigin;
double latOrigin;
double[] lonDataFormat;
double[] latDataFormat;
double maxWidth;
double maxHeight;
double heightRate;
double widthRate;
double screenHeight = 300; //画布的大小
double screenWidth = 300;//画布的大小
public void setJsonArray(JSONArray jsonArray) {
this.jsonArray = jsonArray;
}
public DrawView(Context context) {
super(context);
}
// 我在这里进行数据的 处理
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.BLUE);
latData = new double[jsonArray.length()];
lonData = new double[jsonArray.length()];
for (int i = 0; i < jsonArray.length(); i++) {
try {
JSONObject jsonObjK = new JSONObject(TcpClient.JSONTokener(jsonArray.get(i).toString()));
latData[i] = (double) jsonObjK.get("lat");
lonData[i] = (double) jsonObjK.get("lon");
} catch (JSONException e) {
e.printStackTrace();
}
}
pushData(canvas, paint);
}
// 生成经纬度坐标点数据
private void pushData(Canvas canvas, Paint p) {
getMinLonLat();
lonDataFormat = new double[lonData.length];
latDataFormat = new double[latData.length];
for (int i = 0; i < latData.length; i++) {
latDataFormat[i] = yLatPointFormat(latData[i]);
}
for (int i = 0; i < lonData.length; i++) {
lonDataFormat[i] = xLonPointFormat(lonData[i]);
}
latDataSort = latDataFormat;
lotDataSort = lonDataFormat;
getMaxWidth(lotDataSort);
getMaxHeight(latDataSort);
drawPolygon(canvas, p);
// drawPoint(canvas, p);
}
//3.6 画线
private void drawPolygon(Canvas canvas, Paint p) {
p.reset();
p.setColor(Color.RED);
p.setStrokeWidth(3);
p.setStyle(Paint.Style.STROKE);
Path path1 = new Path();
double orgX = xLonPointFormat(lonOrigin);
double orgY = yLatPointFormat(latOrigin);
path1.moveTo((float) orgX, (float) orgY);
float maginX=250;//x偏移量 设置 线整体 距离x 偏移
float maginY=50;//y偏移量
float overSizeRata=1.8; // 线在图中缩放比例 线在Canvas显示不完整 根据需要调整
for (int i = 0; i < lonDataFormat.length; i++) {
double x = lonDataFormat[i] * widthRate/overSizeRata;
double y = latDataFormat[i] * heightRate/overSizeRata;
if (i == 0) {
path1.moveTo((float) x+maginX, (float) y+maginY);
} else {
path1.lineTo((float) x+maginX, (float) y+maginY);
}
}
path1.close();
canvas.drawPath(path1, p);
}
//获取最小的经纬度
private void getMinLonLat() {
double minLon = lonData[0];
double maxLat = latData[0];
for (int i = 0; i < lonData.length; i++) {
if (minLon > lonData[i]) {
minLon = lonData[i];
}
}
for (int i = 0; i < lonData.length; i++) {
if (maxLat < latData[i]) {
maxLat = latData[i];
}
}
lonOrigin = minLon;
latOrigin = maxLat;
}
//用经纬度减去最小经纬度,取绝对值 *10000(本项目中经纬度间隔较小,已实测间隔2M~1公里没啥问题如
果经纬度间隔较大,可调整10000这个数值的大小,根据我得经纬度 我调整为100000
private Double xLonPointFormat(Double x) {
x = Math.abs(x - lonOrigin) * 100000;
x = Double.valueOf(Math.round(x * 100) / 100);
return x;
}
private Double yLatPointFormat(Double y) {
y = Math.abs(y - latOrigin) * 100000;
y = Double.valueOf(Math.round(y * 100) / 100);
return y;
}
//获取坐标点最大经度差/纬度差与屏幕最大宽度/高度之间的比率
private void getMaxWidth(double data[]) {
double maxIndex = 0;
double minIndex = 0;
for (int i = 0; i < data.length; i++) {
if (maxIndex < data[i]) {
maxIndex = data[i];
}
if (minIndex > data[i]) {
minIndex = data[i];
}
}
maxWidth = (maxIndex - minIndex);
if (Double.doubleToLongBits(maxWidth) == Double.doubleToLongBits(0.0)) {
widthRate = 1;
} else {
widthRate = screenWidth / maxWidth;
}
}
private void getMaxHeight(double data[]) {
double maxIndex = 0;
double minIndex = 0;
for (int i = 0; i < data.length; i++) {
if (maxIndex < data[i]) {
maxIndex = data[i];
}
if (minIndex > data[i]) {
minIndex = data[i];
}
}
maxHeight = (maxIndex - minIndex);
if (Double.doubleToLongBits(maxHeight) == Double.doubleToLongBits(0.0)) {
heightRate = 1;
} else {
heightRate = screenHeight / maxHeight;
}
}
}
4 效果展示
结合转载 啥啥啥啥啥啥啥:https://www.jianshu.com/p/ed61d70a7fd2