const n = 200; // 旋转点的个数 const omegaTheta = 60000; // 旋转一个周期用的时间,ms // 几个长度 m const R = 7e6; // 类似公转 const r = 2e6; // 类似自转 const p = 2e6; // 一个基本长度常量
let theta = 2 * Math.PI * frameState.time / omegaTheta; // 计算当前帧弧度 let coordinates = []; // 存放每个点位置的数组
在demo代码中的数组是像下面这样循环出来的,首先t不难理解,theta是当前帧的弧度,加上2 * Math.PI * i / n以后,也就是每一个点都偏移一定的弧度,形成一条连线。
1 2 3 4 5 6
for (let i = 0; i < n; ++i) { let t = theta + 2 * Math.PI * i / n; let x = (R + r) * Math.cos(t) + p * Math.cos((R + r) * t / r); let y = (R + r) * Math.sin(t) + p * Math.sin((R + r) * t / r); coordinates.push([x, y]); }
这一块代码最难理解的地方是x和y,所以可以把他分开来理解,先只取x和y的前半部分:
1 2 3 4 5 6
for (let i = 0; i < n; ++i) { let t = theta + 2 * Math.PI * i / n; let x = (R + r) * Math.cos(t); // 只保留前半部分 let y = (R + r) * Math.sin(t); // 只保留前半部分 coordinates.push([x, y]); }
结果的到的图片如下所示,可以发现,圆点排列组合成了一个很大的圆,类似于一种公转的效果:
接下来,再只取x和y的后半部分:
1 2 3 4 5 6
for (let i = 0; i < n; ++i) { let t = theta + 2 * Math.PI * i / n; let x = p * Math.cos((R + r) * t / r); // 只保留后半部分 let y = p * Math.sin((R + r) * t / r); // 只保留后半部分 coordinates.push([x, y]); }
<body> <divid="map"class="map"></div> <scripttype="text/javascript"> // 定义一个使用OSM源的瓦片图层 let tileLayer = new ol.layer.Tile({ source: new ol.source.OSM() }); // 初始化地图 let map = new ol.Map({ layers: [tileLayer], target: 'map', view: new ol.View({ center: [0, 0], zoom: 2 }) }); // 定义几种不同的样式 // imageStyle:每个普通圆 // headInnerImageStyle:开头的圆的内圈 // headOuterImageStyle:开头圆的外圈 let imageStyle = new ol.style.Style({ image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: 'yellow' }), stroke: new ol.style.Stroke({ color: 'red', width: 1 }) }) });
let headInnerImageStyle = new ol.style.Style({ image: new ol.style.Circle({ radius: 2, fill: new ol.style.Fill({ color: 'blue' }) }) });
let headOuterImageStyle = new ol.style.Style({ image: new ol.style.Circle({ radius: 5, fill: new ol.style.Fill({ color: 'black' }) }) }); // 定义几个常量 const n = 200; // 200个点 const omegaTheta = 60000; // 旋转时间,ms // 几个长度 m const R = 7e6; const r = 2e6; const p = 2e6; // 回调 tileLayer.on('postrender', event => { // 获取矢量上下文和当前帧 let vectorContext = ol.render.getVectorContext(event); let frameState = event.frameState; let theta = 2 * Math.PI * frameState.time / omegaTheta; console.log(frameState.time, theta) let coordinates = []; for (let i = 0; i < n; ++i) { let t = theta + 2 * Math.PI * i / n; let x = (R + r) * Math.cos(t) + p * Math.cos((R + r) * t / r); let y = (R + r) * Math.sin(t) + p * Math.sin((R + r) * t / r); // var x = (R + r) * Math.cos(t) // var y = (R + r) * Math.sin(t) // var x = p * Math.cos((R + r) * t / r); // var y = p * Math.sin((R + r) * t / r); coordinates.push([x, y]); } vectorContext.setStyle(imageStyle); vectorContext.drawGeometry(new ol.geom.MultiPoint(coordinates)); let headPoint = new ol.geom.Point(coordinates[coordinates.length - 1]); vectorContext.setStyle(headOuterImageStyle); vectorContext.drawGeometry(headPoint); vectorContext.setStyle(headInnerImageStyle); vectorContext.drawGeometry(headPoint); map.render(); }); map.render(); </script> </body>