openlayers3+中模拟晨昏线

最近在flightware上看到一个好玩的功能,根据季节和一天中的时间,计算太阳的光照线,并模拟出白天黑夜分界线。这里分享一下。

1.结果

夏至日:北半球光照最多,白天最长,黑夜最短,北极圈极昼,南极圈极夜(下图为夏至日北京时间12点)


冬至日:北半球光照最少,白天最短,黑夜最长,北极圈极夜,南极圈极昼(下图为冬至日北京时间12点)


春分秋分:南北半球光照相当,日夜等长(下图为春分秋分日北京时间12点)


春分秋分:(下图为春分秋分日北京时间24点)


2.原理

原理大概就是根据客户端的时区和时间,计算出太阳分界线,并添加到地图上,计算过程太麻烦我看不太懂,如果有谁知道原理麻烦告知一下。

3.代码

先引入Javascript日期处理类库:moment.js,用于函数中的日期处理。

代码是一个函数,直接调用即可,我在原函数计算结果的基础上稍微修改了一下。

function addDayNightTerminator(){
	var twilightWidth = 667918;
	var twilightSteps = 13;
	var points = 288;
	var maxDimension = ol.proj.get('EPSG:3857').getExtent()[3];
	var minDimension = ol.proj.get('EPSG:3857').getExtent()[1];
	this.dayFeatures = [];
	this.nightFeatures = [];
	this._terminatorCurveSetCache = {};
	this._generateTerminatorCurveSet = function(dayOfYear) {
		offsetX = maxDimension;
		var declination = 0.40927971 * Math.sin((2 * Math.PI / 365) * (dayOfYear - 81.5));
		var termFunction = function(lon) {
				var cosFactor = -Math.cos((lon + offsetX) * (Math.PI / maxDimension));
				return (2 * maxDimension / Math.PI) * Math.atan(cosFactor / Math.tan(declination));
			};
		var lonPrimeFunction = function(t) {
				return (maxDimension - minDimension) / points;
			};
		var latPrimeFunction = function(t) {
				var aFactor = 2 * maxDimension / Math.PI;
				var bFactor = offsetX;
				var cFactor = Math.PI / maxDimension;
				var dFactor = Math.tan(declination);
				var cosOperand = ((minDimension + (((maxDimension - minDimension) / points) * t)) + bFactor) * cFactor;
				return (aFactor / (1 + Math.pow((-Math.cos(cosOperand) / dFactor), 2))) * (Math.sin(cosOperand) / dFactor) * (cFactor * (maxDimension - minDimension)) / points;
			};
		var lonParallelFunction = function(dist, t) {
				return (dist * latPrimeFunction(t)) / Math.sqrt(Math.pow(lonPrimeFunction(t), 2) + Math.pow(latPrimeFunction(t), 2));
			}
		var latParallelFunction = function(dist, t) {
				return (dist * lonPrimeFunction(t)) / Math.sqrt(Math.pow(lonPrimeFunction(t), 2) + Math.pow(latPrimeFunction(t), 2));
			}
		var lineCoords = [];
		for (var i = 0; i < twilightSteps; i++) {
			lineCoords.push([]);
		}
		for (var i = 0; i < points; i++) {
			var lon = minDimension + ((maxDimension - minDimension) / points * i);
			var lat = termFunction(lon);
			lineCoords[0].push([lon, lat]);
			var latDeg = ol.proj.toLonLat([lon, lat])[1];
			var latRad = latDeg * Math.PI / 180;
			var baseDist = (twilightWidth / (twilightSteps - 1)) / Math.cos(latRad);
			var steps = (twilightSteps - 1) / 2
			for (var j = 1; j <= steps; j++) {
				var dist = baseDist * j;
				lineCoords[j].push([lon + lonParallelFunction(dist, i), Math.max(lat - latParallelFunction(dist, i), minDimension)]);
				lineCoords[j + steps].push([lon - lonParallelFunction(dist, i), Math.min(lat + latParallelFunction(dist, i), maxDimension)]);
			}
		}
		var dayShimCoord = (declination < 0) ? minDimension : maxDimension;
		var nightShimCoord = (declination < 0) ? maxDimension : minDimension;
		return {
			curves: lineCoords,
			dayShimCoord: dayShimCoord,
			nightShimCoord: nightShimCoord
		};
	};
	this.getTerminatorCurveSet = function(dayOfYear) {
		if (!(dayOfYear in this._terminatorCurveSetCache)) {
			this._terminatorCurveSetCache[dayOfYear] = this._generateTerminatorCurveSet(dayOfYear);
		}
		return $.extend(true, {}, this._terminatorCurveSetCache[dayOfYear]);
	};
	this.setClock = function(clock) {
		var now = moment.unix(clock).utc();
		var baseCurveData = this.getTerminatorCurveSet(now.dayOfYear());
		var dayFraction = (now.hour() * 3600 + now.minute() * 60 + now.second()) / 86400;
		var offsetX = dayFraction * 2 * maxDimension;
		offsetX = Math.round(offsetX / ((2 * maxDimension) / points)) * ((2 * maxDimension) / points);
		$.each(baseCurveData.curves, $.proxy(function(k1, curve) {
			$.each(curve, function(k2, coord) {
				curve[k2][0] -= offsetX;
			});
			var count = 0;
			while (true) {
				if (count > curve.length) {
					break;
				}
				if (curve[0][0] < minDimension) {
					var coord = curve.shift();
					coord[0] += (maxDimension - minDimension);
					curve.push(coord);
				} else {
					break;
				}
				count++;
			}
			curve.push([curve[0][0] + (maxDimension - minDimension), curve[0][1]]);
			var nightCoords = curve.slice(0);
			nightCoords.push([maxDimension, baseCurveData.nightShimCoord], [minDimension, baseCurveData.nightShimCoord], curve[0]);
			/*$.each(nightCoords, function(i, coord) {					//如果地图是4326坐标系,需要在这里转化
				nightCoords[i] = ol.proj.transform(nightCoords[i],'EPSG:3857','EPSG:4326')
			});*/
			var nightGeometry = new ol.geom.Polygon([nightCoords]);
			this.nightFeatures[k1].setGeometry(nightGeometry);
		}, this));
	};
	for (var i = 0; i < twilightSteps; i++) {
		this.nightFeatures.push(new ol.Feature({
			type: 'night'
		}));
	}
	this.setClock(Math.round(new Date().getTime()/1000));//设置时间,不设置则为当前时间 '2017-03-22 12:00'

	var twilightLayer = new ol.layer.Vector({
		source: new ol.source.Vector({
			features: [].concat(this.nightFeatures)
		}),
		opacity:0.1,
		style:new ol.style.Style({
		 fill: new ol.style.Fill({
		   color: 'rgba(0,0,0,0.4)'
		 })
	   })
	});
	map.addLayer(twilightLayer);
};



  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
在Vue 3 + TypeScript项目使用OpenLayers,您可以按照以下步骤进行操作: 1. 安装OpenLayers:使用npm或yarn安装OpenLayers库。在命令行运行以下命令: ```bash npm install ol ``` 或 ```bash yarn add ol ``` 2. 创建一个Vue组件:在您的Vue 3项目,创建一个新的Vue组件,用于显示地图。打开一个新的`.vue`文件,例如`Map.vue`。 ```vue <template> <div ref="mapContainer" class="map-container"></div> </template> <script lang="ts"> import { defineComponent, onMounted, ref } from 'vue'; import 'ol/ol.css'; import { Map, View } from 'ol'; export default defineComponent({ name: 'Map', setup() { const mapContainer = ref(null); onMounted(() => { const map = new Map({ target: mapContainer.value, view: new View({ center: [0, 0], zoom: 2, }), }); }); return { mapContainer, }; }, }); </script> <style scoped> .map-container { width: 100%; height: 400px; } </style> ``` 3. 在需要显示地图的组件使用Map组件:在需要显示地图的父组件,导入并使用Map组件。 ```vue <template> <div> <h1>My Map</h1> <Map /> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; import Map from './components/Map.vue'; export default defineComponent({ name: 'App', components: { Map, }, }); </script> ``` 现在,您可以在Vue 3 + TypeScript项目使用OpenLayers来显示地图。请注意,这只是一个基本示例,您可以进一步探索OpenLayers文档来了解更多功能和用法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

evomap

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值