网页绘制可实时变色的路网地图 D3 + OSM + STOMP

1.关于osm数据处理与可视化可以参见我这篇::(我是另一个快乐引流标签^ _ ^)

2.关于stomp可以看我这篇:(我是快乐引流标签^ _ ^)

这次的效果是一旦打开网页就自动向服务器发送请求获取数据并自动绘制到网页

不多废话,按照步骤上代码:

Stomp连接部分(JS)

 /**
 * 建立连接,我这里控制异步处理全部用的是setTimeout,建议为了代码可读和可维护,尽量使用事件监听
 * 这里偷懒还是采用的广播模式,建议使用1对1通讯哈
 */
		function setCon(getData){
				stompClient.connect({},function (frame){
				//console.log("服务器连接"+frame);
				setTimeout(2000);
				getData();
				});
	
		};
                
		//自动订阅消息频道并交互
		//订阅以获取消息	
	 	//订阅之后发送send开启交流,每收到一次就再发送一个send
		function getData(){
			setTimeout(function(){
				stompClient.subscribe("/system/china_motor", function(mes){
	 		    	dataLog = JSON.parse(mes.body);
	 		    	//处理得到的数据
				temp = Object.keys(dataLog);
	 		    	arr=(Object.values(dataLog));
				arr = arr[0];
                                //刷新数据
				refreshData(arr,temp);
                                //确定循环好了就再发送请求    
                                stompClient.send("/app/china_motor",{},"iamready");
				})
			},1000)
                        setTimeout(function(){stompClient.send("/app/china_motor",{},"iamready")},1000);
		};
                
		//遍历形式刷新path标签
		function refreshData(arr,temp){
			svg.selectAll("path").each(function (d,i) {
		            if (arr.includes(i)) {
		                d3.select(this).attr("stroke",temp);
		              }
		            })
		}
		
	//链接关闭
	function sendGoodBye(){
		stompClient.send("/app/china_motor",{},"iamfinished");
	}
	function disconnect(){
	 	stompClient.disconnect();
	 }

JS客户端部分

    	<svg class ="china"></svg>
	<script>
        //设定大小
    const svgWidth = 1200;
    const svgHeight =900;
    const padding = 1;
    
    const svg = d3.select(".china")
        .attr("height", svgHeight)
        .attr("width", svgWidth);

		/*
		 * 创建一个地理投影
		 * .center 设置投影中心位置
		 * .scale 设置缩放系数 
		 */
	const x0 = padding;
	const y0 = padding;
	const x1 = svgWidth - padding * 2;
	const y1 = svgHeight - padding * 2;
	const projection = d3.geoMercator().fitExtent(
			[
				[x0,y0],
				[x1,y1],
			],china
		 );
		//中心对齐可以再修改一下,提高速度-。-
		//  创建路径生成器path
		var path = d3.geoPath().projection(projection);

		 //渲染地图 
	const mapPath = svg.selectAll("path");
        //加载数据,这里我没有给出数据源,可以看我之前的博客
		  mapPath.data(china.features)
			.join('path')
			.attr('d', path)
			//.attr('id',china.features.properties.valueof(osm_id))
			.attr("stroke-width", 2)
			.attr("stroke", "#00cc00")
			.attr("fill", "#000000");
			
	//前面全部处理好了就建立连接开始通信
	var linstener = "/system/china_motor"
	socket = new SockJS('/stomp');
	stompClient = Stomp.over(socket);
	var data;
	setCon(getData);
	</script>

<script>
//当退出页面或者改变页面时就关闭链接,防止占用
 window.onbeforeunload = function(e) {
	sendGoodBye();
	disconnect();
	} 
</script>
    

服务器部分:

//这里还没有接入数据库,使用随机数测试一下。。
    	@MessageMapping("/china_motor")
	@SendTo("/system/china_motor")
	public void sentMotor(@Payload String name) throws InterruptedException {
		int size = 0;
		int a = 0;
		int max = 248306;
		int big = 0;
		String color;
		System.out.println(name);
		trafficStream ts = new trafficStream();
		if(name.equals("iamready")) {
                //生成随机数测试
			Random rd = new Random();
			a = rd.nextInt(3);
			switch(a) {
			case 0: 
				color="#ff0000";
				size = 1000;
				break;
			case 1:
				color="#ffff00";
				size = 10000;
				break;
			case 2:
				color="##00cc00";
				size = 10000;
				break;
			default:
				color = "##00cc00";
				size = 10000;
				;
			}
			int[] sort = new int [size];
			sort = ts.randomArray(0, max, size);
			Map<String,int[]> msg = new HashMap<String, int[]>();
			msg.put(color, sort);
			Thread.sleep(6000);
			peopelFlow.convertAndSend("/system/china_motor",msg);
		}
                //处理完毕事件
		else if(name.equals("iamfinished")) {
				System.out.println("connect finished");
				peopelFlow.setSendTimeout(j);
		}
	}	

stompConfig部分:

    public static final String BROKER_CHINA = "/system/china_motor";
	@Override
	public void configureMessageBroker(MessageBrokerRegistry config) {
			//用于指定客户端可以订阅哪些地址
			config.enableSimpleBroker(BROKER_CHINA);
			//客户端发送消息的服务端地址前缀
			config.setApplicationDestinationPrefixes("/app");
			//服务端发给 制定 客户端的前缀 /system/msg 是广播 /user/system/msg则是制定客户端
			config.setUserDestinationPrefix("/user");
		}
	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		//SockJS 用于定义连接节点
		registry.addEndpoint("/stomp")//.setHandshakeHandler(new CustomHandler())//.setAllowedOrigins("*")
                        .withSockJS();		
	}
	//配置线程数量(pool),防止错顺序
	@Override
    public void configureClientOutboundChannel(ChannelRegistration registration) {
        registration.taskExecutor().corePoolSize(1).maxPoolSize(1);
    }

效果展示:

image.png

放大看看~

image.png

image.png

根据设置的数据量和随即概率,黄色很快就填满了

由于是随机数据,所以看起来有点假,但是确实是根据服务器端的数据实时更新的。

后台数据也看得到:

image.png

存在的主要问题:

  1. 上文提过的js应该使用事件监听处理异步事件

  2. 算法没有优化,占用了大量的计算和内存资源

  3. 数据量太大导致网页加载慢以及stomp报文处理慢

  4. 数据不完整,可以再加入OSM_Roads里面的’motor_link’以完整数据

其实还有蛮多其他小瑕疵的。

害,以后有心情再优化吧-。-

希望各位多多指教,提出意见。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值