共享单车之数据可视化

news2025/1/19 20:23:00

文章目录

  • 第1关:绘制地图
  • 第2关:绘制流量最高的五条线路的路程图


第1关:绘制地图

任务描述
本关任务:使用JSP在百度地图上绘制一条共享单车起始路程。

相关知识
为了完成本关任务,你需要掌握:

如何创建地图实例;
如何在地图上绘制路程线。
创建地图实例
我们需要先在jsp中引入百度地图api。

myMap
引入之后我们便可使用api中BMap对象来创建地图实例:

经过上述设置我们访问jsp则为如下效果:

在地图上绘制路径线
首先我们需要绘制路径必须知道起始点的经纬度及终点的经纬度才能够绘制成线,现提供起始点经纬度为(116.44516,39.925338),终点经纬度为(116.403838,39.919141),通过这两个点来绘制路径线:

var start_longitude=116.44516;//开始经度
var start_latitude=39.925338;//开始纬度
var stop_longitude=116.403838;//结束经度
var stop_latitude=39.919141;//结束纬度
var polyline = new BMap.Polyline([
new BMap.Point(start_longitude, start_latitude),
new BMap.Point(stop_longitude, stop_latitude)
],{strokeColor:“red”,strokeWeight:3,strokeOpacity:0.5});//创建一条宽度为3外边框透明度为0.5的红色线
map.addOverlay(polyline);//将线添加到地图上
效果如下:

给路程线设置标注和添加箭头
上图可以看到路程,但只有一条线并无法详细的向我们展示信息,因此我们可以通过给路程线添加标注位置和方向箭头。

添加标注
var address=“北京市朝阳区朝外街道三丰里社区”;
var marker = new BMap.Marker(new BMap.Point(start_longitude,start_latitude)); //创建开始位置标注
var label = new BMap.Label(address, {offset: new BMap.Size(20, 0)});//给标注设置文字描述
marker.setLabel(label);//将文字描述设置到标注上
map.addOverlay(marker);//将标注添加到地图中
通过鼠标滚轮将地图放大,可得到如下效果:

绘制箭头

上图中,线段AB是路程线,只要绘制出CBD就可以实现箭头效果,为了灵活绘制箭头,需要用户自定义箭头的长度(r)和角度(angle)。
实现步骤如下:
变量定义:pixelStart(路程线起点坐标)、pixelEnd(路程线终点坐标)、r:(单位像素,并不是CB对应的箭头的长度,而是橘色线段对应的距离)、angle:箭头线((CB或者DB)与AB的夹角),函数定义为addArrow(polyline,r,angel):

首先要将AB两点的经纬度坐标转化成屏幕坐标
然后根据AB两点屏幕坐标以及r长度,计算绿色小绿点的屏幕坐标pixelTem。
再根据B点、小绿点的屏幕坐标及angle角度,计算出C,D两点的屏幕坐标
利用map的坐标转换方法,将C,D两点的屏幕坐标转成经纬度表示的坐标。
利用画线方法,绘制CBD折线。
代码我们已为你提供,在右侧任务代码中addArrow函数中体现。

编程要求
在右侧编辑器补充代码,绘制出一条河北省保定市雄县(经纬度为116.10,38.98)一共享单车使用的路程线,具体信息如下:

起点经纬度为(39.04607,116.233093);
终点经纬度为(39.041691,116.235352);
要求设置路程线为红色,宽度为3,透明度为0.5;
给起点和终点都创建标注,描述起点为乡里乡情铁锅炖南228米,终点为擎天矿用材料有限公司北609米,要求设置的字体大小为20
调用提供绘制箭头函数addArrow函数添加r=10,angle=Math.PI/7的箭头。
注意:直接使用已定义的变量,且已定义的变量名不要私自修改。

最终实现效果如下:

测试说明
平台会对你编写的代码进行测试:

测试输入:无
预期输出:测试通过

开始你的任务吧,祝你成功!

示例代码如下:

<%@ page language="java" contentType="text/html; charset=utf-8"
         pageEncoding="utf-8"%>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style type="text/css">
        body, html,#allmap {
            width: 100%;
            height: 100%;
            overflow: hidden;
            margin:0;
        }
    </style>
    <script type="text/javascript" src="http://api.map.baidu.com/api?v=1.4"></script>
    <title>step1</title>
</head>
<body>
<div id="allmap"></div>
</body>
</html>
<script type="text/javascript">
    var map = new BMap.Map("allmap");// 创建地图实例
    var point = new BMap.Point(116.10 ,38.98);// 创建点坐标
    map.centerAndZoom(point, 13);//设初始化地图。 如果center类型为Point时,zoom必须赋值,范围3-19级,若调用高清底图(针对移动端开发)时,zoom可赋值范围为3-18级。如果center类型为字符串时,比如“北京”,zoom可以忽略,地图将自动根据center适配最佳zoom级别
    map.addControl(new BMap.NavigationControl());//缩放平移控件
    map.enableScrollWheelZoom();//利用鼠标滚轮控制大小
    var start_longitude=116.233093;//开始经度
    var start_latitude=39.04607;//开始纬度
    var stop_longitude=116.235352;//结束经度
    var stop_latitude=39.041691;//结束纬度
    var address=["乡里乡情铁锅炖南228米","擎天矿用材料有限公司北609米"];
    /**********  Begin  **********/
    //1.初始化路程线
    var polyline = new BMap.Polyline([
        new BMap.Point(start_longitude, start_latitude),
        new BMap.Point(stop_longitude, stop_latitude)
    ], {strokeColor:"red", strokeWeight:3, strokeOpacity:0.5});
    //2.将线添加到地图上
    map.addOverlay(polyline);
    //3.调用绘制箭头线函数
    addArrow(polyline,10,Math.PI/7);
    //4.设置起始点标注
    var marker = new BMap.Marker(new BMap.Point(start_longitude,start_latitude));
    var label = new BMap.Label(address[0],{offset: new BMap.Size(20, 0)});
    marker.setLabel(label);
    map.addOverlay(marker);
    var marker = new BMap.Marker(new BMap.Point(stop_longitude,stop_latitude));
    var label = new BMap.Label(address[1], {offset: new BMap.Size(20, 0)});
    marker.setLabel(label);
    map.addOverlay(marker);
    /**********  End  **********/
    //绘制箭头的函数
    function addArrow(polyline,r,angle){
        var linePoint=polyline.getPath();//线的坐标串(里面存的就是起始点的坐标点)
        var arrowCount=linePoint.length;
        for(var i =1;i<arrowCount;i++){ //在拐点处绘制箭头
            var pixelStart=map.pointToPixel(linePoint[i-1]);
            var pixelEnd=map.pointToPixel(linePoint[i]);
            var pixelTemX,pixelTemY;//临时点坐标
            var pixelX,pixelY,pixelX1,pixelY1;//定义箭头两个点坐标
            var delta=(pixelEnd.y-pixelStart.y)/(pixelEnd.x-pixelStart.x);//主线斜率,垂直时无斜率
            var param=Math.sqrt(delta*delta+1);//代码简洁考虑
            if((pixelEnd.x-pixelStart.x)<0){ //第二、三象限
                pixelTemX=pixelEnd.x+ r/param;
                pixelTemY=pixelEnd.y+delta*r/param;
            }else{ //第一、四象限
                pixelTemX=pixelEnd.x- r/param;
                pixelTemY=pixelEnd.y-delta*r/param;
            }
            //已知直角三角形两个点坐标及其中一个角,求另外一个点坐标算法
            pixelX=pixelTemX+ Math.tan(angle)*r*delta/param;
            pixelY=pixelTemY-Math.tan(angle)*r/param;
            pixelX1=pixelTemX- Math.tan(angle)*r*delta/param;
            pixelY1=pixelTemY+Math.tan(angle)*r/param;
            var pointArrow=map.pixelToPoint(new BMap.Pixel(pixelX,pixelY));
            var pointArrow1=map.pixelToPoint(new BMap.Pixel(pixelX1,pixelY1));
            var Arrow = new BMap.Polyline([
                pointArrow,linePoint[i],pointArrow1
            ], {strokeColor:"blue", strokeWeight:3, strokeOpacity:0.5});
            map.addOverlay(Arrow);
            return Arrow;
        }
    }
</script>

在这里插入图片描述

第2关:绘制流量最高的五条线路的路程图

任务描述
本关任务:在地图上绘制共享单车中流量最高的五条路线的路程。

相关知识
本实训数据基于共享单车之数据分析最后一关的数据(流量最高的五条数据)。

为了完成本关任务,你需要掌握:

如何在后台传数据给JSP页面;
JSP页面中如何获取后台传的数据;
如何在地图上绘制多条路程线。
如何在后台传数据给JSP页面
我们可以通过直接访问servlet在其doGet或doPost方法中将值传递到jsp中,示例如下:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute(“key”,“value”);//以键值对的形势存值
request.getRequestDispatcher(“index.jsp”).forward(request,response);//使用转发将数据带到页面中
}
JSP获取后台传过来的数据

但若传的数据类型为集合,则直接获取会被当成字符串,因此需要做一些数据处理,如:

List list=new ArrayList<>();
list.add(“abc”);
list.add(“ABC”);
request.setAttribute(“key”,list);

如何在地图上绘制多条路程线
上一章节我们学习了如何绘制一条路程线,现在我们要绘制多条,本质上是一样的操作,只需将后端获取的数据进行循环遍历即可:

为了方便存取数据,我们将之前章节中HbaseUtil类中用来扫描表显示结果的scanTable方法做了修改,改为将流量最高的五条路程线数据存到了自定义的BickMap对象中,(上诉的相关类和方法都可在右侧文件夹中进行查看)具体操作如下:

servlet
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
BickMap bickMap = HBaseUtil.scanTable();//获取存进去的五条数据
for (String key : bickMap.getKeys()) {
request.setAttribute(key,bickMap.get(key));//遍历将最高五条流量的数据以“字段名-结果集合”形式传到后台
}
request.getRequestDispatcher(“step2.jsp”).forward(request,response);
}
jsp

编程要求
在右侧编辑器补充代码,绘制流量最高的五条数据的路程线,具体要求如下:

在servlet中将字段名为key,bickMap.get(key)为value作为键值对方式传值给jsp;
绘制路程线样式为红色,宽度为3,透明度为0.5;
调用提供绘制箭头函数addArrow,绘制以r=10,angle=Math.PI/7的箭头;
绘制起始地点的标注信息,文字大小仍为20。
最终实现效果如下:

注意:为了方便测试,右侧编辑器中已有的变量名请勿私自改动。

测试说明
平台会对你编写的代码进行测试:

测试输入:无
预期输出:测试通过

开始你的任务吧,祝你成功!

说点什么
示例代码如下:
在该位置选择代码文件
在这里插入图片描述
BickMapServlet:

package com.educoder.servlet;
import com.educoder.util.HBaseUtil;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class BickMapServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        /**********   Begin   **********/
        //1.通过HbaseUtil类获取数据
        BickMap bickMap =HBaseUtil.scanTable();
        //2.遍历将数据以键值对的方式传给jsp
        for (String key : bickMap.getKeys()) {
            request.setAttribute(key, bickMap.get(key));
        }
        /**********   End    **********/
        
        request.getRequestDispatcher("step2.jsp").forward(request,response);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

step2.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style type="text/css">
        body, html,#allmap {
            width: 100%;
            height: 100%;
            overflow: hidden;
            margin:0;
        }
    </style>
    <script type="text/javascript" src="http://api.map.baidu.com/api?v=1.4"></script>
    <title>step2</title>
</head>
<body>
<div id="allmap"></div>
</body>
</html>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript">
    var map = new BMap.Map("allmap");// 创建地图实例
    var point = new BMap.Point(116.10 ,38.98);// 创建点坐标
    map.centerAndZoom(point, 13);//设初始化地图。 如果center类型为Point时,zoom必须赋值,范围3-19级,若调用高清底图(针对移动端开发)时,zoom可赋值范围为3-18级。如果center类型为字符串时,比如“北京”,zoom可以忽略,地图将自动根据center适配最佳zoom级别
    map.addControl(new BMap.NavigationControl());//缩放平移控件
    map.enableScrollWheelZoom();//利用鼠标滚轮控制大小
    /**********   Begin  **********/
    //1.获取后台传过来的数据 调用已写好的change函数清理数据
    var start_longitude = change('<%=request.getAttribute("start_longitude") %>');
    var start_latitude = change('<%=request.getAttribute("start_latitude") %>');
    var stop_longitude = change('<%=request.getAttribute("stop_longitude") %>');
    var stop_latitude = change('<%=request.getAttribute("stop_latitude") %>');
    var start_address = change('<%=request.getAttribute("start_address") %>');
    var stop_address = change('<%=request.getAttribute("stop_address") %>');
    //2.初始化路程线
    for (var i=0;i<start_latitude.length;i++){
        var polyline = new BMap.Polyline([
            new BMap.Point(start_longitude[i], start_latitude[i]),
            new BMap.Point(stop_longitude[i], stop_latitude[i])
        ], {strokeColor:"red", strokeWeight:3, strokeOpacity:0.5});
        //3.将线添加到地图上
        map.addOverlay(polyline);
        //4.调用绘制箭头线函数
        addArrow(polyline,10,Math.PI/7);
        //5.设置起始点标注
        var marker = new BMap.Marker(new BMap.Point(start_longitude[i],start_latitude[i]));
        var label = new BMap.Label(start_address[i],{offset: new BMap.Size(20, 0)});
        marker.setLabel(label);
        map.addOverlay(marker);
        var marker = new BMap.Marker(new BMap.Point(stop_longitude[i],stop_latitude[i]));
        var label = new BMap.Label(stop_address[i], {offset: new BMap.Size(20, 0)});
        marker.setLabel(label);
        map.addOverlay(marker);
    }
    /**********   End   **********/
    //数据转化函数
    function change(obj) {
        obj = obj.substring(1,obj.length - 1).split(",");
        return obj;
    }
    //绘制箭头的函数
    function addArrow(polyline,r,angle){
        var linePoint=polyline.getPath();//线的坐标串(里面存的就是起始点的坐标点)
        var arrowCount=linePoint.length;
        for(var i =1;i<arrowCount;i++){ //在拐点处绘制箭头
            var pixelStart=map.pointToPixel(linePoint[i-1]);
            var pixelEnd=map.pointToPixel(linePoint[i]);
            var pixelTemX,pixelTemY;//临时点坐标
            var pixelX,pixelY,pixelX1,pixelY1;//定义箭头两个点坐标
            var delta=(pixelEnd.y-pixelStart.y)/(pixelEnd.x-pixelStart.x);//主线斜率,垂直时无斜率
            var param=Math.sqrt(delta*delta+1);//代码简洁考虑
            if((pixelEnd.x-pixelStart.x)<0){ //第二、三象限
                pixelTemX=pixelEnd.x+ r/param;
                pixelTemY=pixelEnd.y+delta*r/param;
            }else{ //第一、四象限
                pixelTemX=pixelEnd.x- r/param;
                pixelTemY=pixelEnd.y-delta*r/param;
            }
            //已知直角三角形两个点坐标及其中一个角,求另外一个点坐标算法
            pixelX=pixelTemX+ Math.tan(angle)*r*delta/param;
            pixelY=pixelTemY-Math.tan(angle)*r/param;
            pixelX1=pixelTemX- Math.tan(angle)*r*delta/param;
            pixelY1=pixelTemY+Math.tan(angle)*r/param;
            var pointArrow=map.pixelToPoint(new BMap.Pixel(pixelX,pixelY));
            var pointArrow1=map.pixelToPoint(new BMap.Pixel(pixelX1,pixelY1));
            var Arrow = new BMap.Polyline([
                pointArrow,linePoint[i],pointArrow1
            ], {strokeColor:"blue", strokeWeight:3, strokeOpacity:0.5});
            map.addOverlay(Arrow);
            return Arrow;
        }
    }
</script>

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1344847.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript使用教程(二):类型、值和变量

计算机程序通过操作值&#xff08;如数值3.14&#xff09;或文本&#xff08;如“Hello World”&#xff09;来工作。编程语言中这些可以表示和操作的值被称为类型&#xff0c;而一门语言支持的类型集也是这门语言最基本的特征。程序在需要把某个值保存下来以便将来使用时&…

python可视化界面自动生成,python如何做可视化界面

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python gui可视化操作界面制作&#xff0c;python做出的炫酷的可视化&#xff0c;现在让我们一起来看看吧&#xff01; 目录 前言 一.环境配置 插件&#xff1a; 1.python 2.Chinese 3.Open In Default Browser 安装pyt…

链表的一些典型问题

求链表的中间节点/倒数第K个节点 等类似的随机访问&#xff0c;可以考虑用快慢指针 例 求链表的中间节点 可以定义两个指针&#xff0c;一个一次走两步一个一次走一步&#xff0c;当走的快的走到NULL时&#xff0c;走的慢的就是链表的中间节点。&#xff08;此法求出的偶数个…

ES的使用(Elasticsearch)

ES的使用&#xff08;Elasticsearch&#xff09; es是什么&#xff1f; es是非关系型数据库&#xff0c;是分布式文档数据库&#xff0c;本质上是一个JSON 文本 为什么要用es? 搜索速度快&#xff0c;近乎是实时的存储、检索数据 怎么使用es? 1.下载es的包&#xff08;环境要…

软件测试/测试开发丨学习笔记之 Python 函数

python 函数 函数的作用 函数是组织好的&#xff0c;可重复使用的&#xff0c;用来实现单一或相关联功能的代码段函数能提高应用的模块性和代码的重复利用率python 内置函数&#xff1a;docs.python.org/zh-cn/3.8/l… 函数定义 def&#xff1a;函数定义关键词function_nam…

轻松调整视频时长,创意与技术的新篇章

传统的视频剪辑工具往往难以精确控制时间&#xff0c;而【媒体梦工厂】凭借其先进的算法和界面设计&#xff0c;让视频时长的调整变得简单而精确&#xff0c;助你释放无限的创意&#xff0c;用技术为你的创意插上翅膀&#xff0c;让每一秒都有意义。 所需工具&#xff1a; 一…

MongoDB 概念介绍

1、MongoDB 应用场景 传统的关系型数据库&#xff0c;在数据操作的"三高"需求以及应对Web2.0的网站需求面前&#xff0c;显得力不从心。 High performance -对数据库高并发读写的需求。Huge Storage -对海量数据的高效率存储和访问的需求。High Scalability &&…

基于Java图书借阅管理系统设计与实现(源码+部署文档)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

Android : 使用GestureOverlayView进行手势识别—简单应用

示例图&#xff1a; GestureOverlayView介绍&#xff1a; GestureOverlayView 是 Android 开发中用于识别和显示手势的视图组件。它允许用户在屏幕上绘制手势&#xff0c;并且应用程序可以检测和响应这些手势。以下是关于 GestureOverlayView 的主要特点&#xff1a; 手势识别…

RS-485 RS-232 RS-422 区别和理解

RS-485&#xff0c;RS-232&#xff0c;RS-422区别和理解 目录概述需求&#xff1a; 设计思路实现思路分析1.概述2.区别 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a b…

Vue : 监视属性

目录 一个案例 监听属性 handler immediate vm.$watch(xxx) 深度监视 监视的简写 computed和watch之间的区别 一个案例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport"…

湘潭大学-2023年下学期-c语言-作业0x0a-综合1

A 求最小公倍数 #include<stdio.h>int gcd(int a,int b) {return b>0?gcd(b,a%b):a; }int main() {int a,b;while(~scanf("%d%d",&a,&b)){if(a0&&b0) break;printf("%d\n",a*b/gcd(a,b));}return 0; }记住最大公约数的函数&…

java cpu使用率高排查

1、top 找到对应进程&#xff0c;如这里是4060434 2、找线程 ps H -eo pid,tid,%cpu | grep 4060434找到那个线程id 高的 如4066606 3、转化16进制 printf 0x%x\n 40666064、找16进制对应的运行信息 jstack 4060434 | grep 0x3e0d2e -A 20

Hive集群出现报错信息解决办法

一、报错信息&#xff1a;hive> show databases;FAILED: HiveException java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient 解决办法&#xff1a;1.删除mysql中的元数据库&#xff08;metastore&#xff0…

MySQL:权限控制

要授予用户帐户权限&#xff0c;可以用GRANT命令。有撤销用户的权限&#xff0c;可以用REVOKE命令。这里以 MySQl 为例&#xff0c;介绍权限控制实际应用。 GRANT授予权限语法&#xff1a; GRANT privilege,[privilege],.. ON privilege_level TO user [IDENTIFIED BY passwo…

List常见方法和遍历操作

List集合的特点 有序&#xff1a; 存和取的元素顺序一致有索引&#xff1a;可以通过索引操作元素可重复&#xff1a;存储的元素可以重复 List集合的特有方法 Collection的方法List都继承了List集合因为有索引&#xff0c;所以有了很多操作索引的方法 ublic static void main…

【C语言】分支与循环语句

什么是语句&#xff1f; C语句可分为以下五类&#xff1a; 表达式语句函数调用语句控制语句 &#xff08;本篇重点介绍&#xff09;复合语句空语句 控制语句用于控制程序的执行流程&#xff0c;以实现程序的各种结构方式。C语言支持三种结构&#xff1a; 顺序结构选择结构循…

软件测试/测试开发丨Python 虚拟环境及pip环境管理

venv 虚拟环境管理 venv 虚拟环境的优点 独立的 Python 环境&#xff0c;不会产生冲突有助于包的管理删除和卸载方便 venv 使用方法 创建虚拟环境 python3 -m venv test 激活虚拟环境 切换指定文件夹Windows&#xff1a;/Scripts/macOS&#xff1a;/bin/ 执行指令&#xff…

基于STM/APM32F072制作的J-Link OB调试器项目验证

基于STM/APM32F072制作的J-Link OB调试器项目验证 &#x1f4cd;本文基于github项目&#xff1a;https://github.com/geekchun/Jlink-OB/tree/master⚡申明&#xff1a;仅限个人研究学习&#xff0c;无其他用途。&#x1f33f;采用该项目提供的固件&#xff0c;烧录STM32f4时信…

技能分析:这就是人们写在简历上的内容

您希望您的技能部分听起来像其他人一样吗&#xff1f;另一方面&#xff0c;您是否想遗漏一项顶级技能&#xff0c;因为许多其他简历也列出了它&#xff1f;在脱颖而出和涵盖雇主寻求的所有技能之间找到平衡可能是一个挑战。 优秀的简历技能部分会考虑到每个雇主所寻求的特质。…