中山市网站建设公司,广告设计与制作工资,智能制造,seo快速优化方法初始化创建画布我目前正在为Three.js编写下一本书#xff0c;其中一章涉及可视化开放数据。 在寻找可以使用的数据时#xff0c;我遇到了来自NOAA的一组数据。 通过此站点#xff0c;您可以以网格格式下载一组全世界的每月降水报告。 因此#xff0c;我下载了它们#xff… 初始化创建画布 我目前正在为Three.js编写下一本书其中一章涉及可视化开放数据。 在寻找可以使用的数据时我遇到了来自NOAA的一组数据。 通过此站点您可以以网格格式下载一组全世界的每月降水报告。 因此我下载了它们然后开始处理数据以查看其外观和使用方式。 在本文中我不会向您展示基于Three.js的结果但是我将为您提供一个快速概述如何获得最初用于调试目的的格式 在此图像中您可以看到2012年7月全球对月降水量的对数。我还创建了一个简单的站点来显示此动画以及正在运行的动画。 因此您需要做什么才能将可以从NOAA站点下载的集转换为可视的内容。 下载并转换NetCDF格式。 加载生成的CSV文件 将CSV数据处理到世界网格中 动画化两个月之间的过渡 作为奖励还可以创建图例以显示什么颜色表示什么 但是首先我们需要获取数据。 下载并转换NetCDF格式 我们需要做的第一件事就是获取数据。 我使用了以下链接您可以在其中定义要下载的数据范围。 在此示例中我使用了2012年1月至2012年12月的范围并选择了创建子集而不绘制图的选项。 但是下载它的格式不能直接用作我们基于HTML5画布的可视化的输入。 您可以使用ncdump-json创建一个JSON文件但是仍然需要能够解释它因此我选择了另一种方法。 我刚刚编写了一个简单的Java程序将NetCDF格式转换为简单的CSV文件。 我使用了以下Maven依赖项 dependenciesdependencygroupIdedu.ucar/groupIdartifactIdnetcdf/artifactIdversion4.2.20/version/dependencydependencygroupIdcommons-io/groupIdartifactIdcommons-io/artifactIdversion2.4/version/dependency/dependencies 并使用以下一段Java代码 public class NetCDFDump {public static void main(String[] args) throws IOException, InvalidRangeException {String year 2012;NetcdfFile nc NetcdfFile.open(src/main/resources/X84.31.143.145.44.1.47.49.nc);Variable precip nc.findVariable(precip);// use the shapes to create an arrayint[] shapes precip.getShape();// month, lat, lonfloat[][][] data new float[shapes[0]][shapes[1]][shapes[2]];// iterate over 12 (or 11) monthsint[] pos new int[3];int[] shape {1,1,1};for (int i 0 ; i shapes[0] ; i) {pos[0]i;for (int lat 0 ; lat shapes[1]; lat) {pos[1] lat;for (int lon 0 ; lon shapes[2]; lon) {pos[2] lon;Array result precip.read(pos, shape);data[pos[0]][pos[1]][pos[2]] result.getFloat(0);}}}// output data like this// month, lat, lon, humidityfloat[][] combined new float[data[0].length][data[0][0].length];for (int m 0 ; m data.length ; m) {File outputM new File(year -out- m .csv);for (int lat 0 ; lat data[m].length ; lat) {for (int lon 0 ; lon data[m][lat].length; lon) {float value data[m][lat][lon];if (value -1000) {combined[lat][lon]value;} else {combined[lat][lon]-1000;}// write the string for outputfileStringBuffer bOut new StringBuffer();bOut.append(m);bOut.append(,);bOut.append(lat);bOut.append(,);bOut.append(lon);bOut.append(,);bOut.append(value);bOut.append(\n);// write to month fileFileUtils.write(outputM,bOut,true);}}}// now process the combinedFile outputM new File(year -gem.csv);for (int i 0; i combined.length; i) {for (int j 0; j combined[0].length; j) {StringBuffer bOut new StringBuffer();bOut.append(i);bOut.append(,);bOut.append(j);bOut.append(,);bOut.append(combined[i][j]/data.length);bOut.append(\n);FileUtils.write(outputM, bOut, true);}}}
} 我不会详细介绍正在发生的事情但是这段代码会生成许多文件每个文件一个月其中一个包含平均值。 每月以以下格式显示 ...
0,65,78,32.65
0,65,79,35.09
0,65,80,31.14
0,65,81,42.7
0,65,82,49.57
... 这些值分别表示月份纬度经度和降水。 对于平均值除了省略第一个条目外它看起来几乎相同。 ...
59,94,59.874165
59,95,65.954994
59,96,57.805836
... 现在我们已经获得了易于使用的格式的数据可以使用它来创建可视化。 加载生成的CSV文件 要加载文件我们只使用一个简单的XMLHttpRequest如下所示 // create an XMLHttpRequest to get the datavar xmlhttp new XMLHttpRequest();xmlhttp.onreadystatechange function() {if (xmlhttp.readyState 4 xmlhttp.status 200) {var coords CSVToArray(xmlhttp.responseText,,);// and process each of the coordinates...}}// make the call and use the callback to process the resultxmlhttp.open(GET, location/of/the/file, true);xmlhttp.send(); 现在coords变量包含所有坐标并为每个坐标显示值。 实际上将其转换为画布非常容易。 将CSV数据处理到世界网格中 在XMLHttpRequest的回调中我们检查是否已接收到数据并将其转换为一组坐标。 我们唯一需要做的就是将这些坐标转换为画布上的可视化图像。 var coords CSVToArray(xmlhttp.responseText,,);coords.forEach(function(point) {var offset 0;if (point.length 3) {offset 1;}if (parseFloat(point[2offset]) 0) {var lat parseInt(point[0offset]);var lon parseInt(point[1offset]);var value parseFloat(point[2offset]);if (value max) max value;// lat is from 0 to 180// lon is from 0 to 360var x canvas.width/360*((lon)-180);if (x0) {xcanvas.width-(x*-1);}var y canvas.height/180*lat;if (value 0) {context.beginPath();context.rect(x,y,4,4);context.fillStyle scale(value).hex();context.fill();}}}); 如您所见非常简单的代码就是我们将位置取下来将它们转换为画布上的X和Y坐标并创建具有特定颜色的小方块。 为了生成颜色我们使用Chroma.js比例尺。 var scale chroma.scale([red , yellow, green, blue]).domain([1,1700], 100, log); 此调用创建从红色到黄色到绿色到蓝色的色标。 值的范围是1到1700分为100步并使用对数刻度。 这将产生以下图像这次是2012年1月的降水 由于我们拥有所有月份的数据因此我们现在可以轻松创建简单的动画。 动画化两个月之间的过渡 对于动画我们将创建类似于以下电影中所示的内容其中我们在各个月份之间缓慢过渡 只需将图像彼此叠加显示并更改不透明度即可轻松创建此动画。 因此首先设置一些css它将大部分图像隐藏起来然后将它们全部放在另一个顶部。 #cf {position:relative;margin:0 auto;height: 700px;}#cf img {position:absolute;left:0;width: 1600px;} 现在我们可以添加图像并使用“ bottom”类仅显示第一个图像 div idcfimg idimg-1 classtop src./assets/images/2012-01-perc.png /img idimg-2 classbottom src./assets/images/2012-02-perc.png /img idimg-3 classbottom src./assets/images/2012-03-perc.png /img idimg-4 classbottom src./assets/images/2012-04-perc.png /img idimg-5 classbottom src./assets/images/2012-05-perc.png /img idimg-6 classbottom src./assets/images/2012-06-perc.png /img idimg-7 classbottom src./assets/images/2012-07-perc.png /img idimg-8 classbottom src./assets/images/2012-08-perc.png /img idimg-9 classbottom src./assets/images/2012-09-perc.png /img idimg-10 classbottom src./assets/images/2012-10-perc.png /img idimg-11 classbottom src./assets/images/2012-11-perc.png /img idimg-12 classbottom src./assets/images/2012-12-perc.png /
/div 现在我们只需要一些JavaScript即可将所有内容捆绑在一起 var month[];month[0]January;month[1]February;month[2]March;month[3]April;month[4]May;month[5]June;month[6]July;month[7]August;month[8]September;month[9]October;month[10]November;month[11]December;var allTweens;init();animate();function init() {// create a chain of tweensallTweens setupTweens(12);allTweens[0].start();}function setupTweens(imageCount) {var tweens [];for (var i 0 ; i imageCount ; i) {var tween new TWEEN.Tween( { opac: 0, image: i, max: imageCount } ).to( { opac: 100 }, 2500 ).easing( TWEEN.Easing.Linear.None ).onUpdate( function () {// on update, lower the opacity of image i and update the opacity of// image i1;var currentImage document.getElementById(img-(this.image1));if (this.image imageCount -1) {var nextImage document.getElementById(img-1);} else {var nextImage document.getElementById(img-(this.image2));}currentImage.style.opacity 1- this.opac / 100;nextImage.style.opacity this.opac / 100;} );tween.onComplete(function() {document.getElementById(title-2012).textContent Showing precipitation: month[this.image] 2012;// Set the inner variable to 0.this.opac 0;// were done, restartif (this.max-1 this.image) {allTweens[0].start();}});// connect to each anotherif (i 0) {tweens[i-1].chain(tween);}tweens.push(tween);tweens[0].repeat();}return tweens;}function animate() {requestAnimationFrame(animate);TWEEN.update();} 在这里我们使用tween.js设置图像之间的过渡。 作为奖励还可以创建图例以显示什么颜色表示什么 在动画中您可以在底部看到图例。 此图例创建为简单的画布另存为图像。 为了完整起见此处显示执行此操作的代码 var canvas document.createElement(canvas);canvas.width 435;canvas.height 30;var context canvas.getContext(2d);var domains scale.domain();document.body.appendChild(canvas);// from 1 to 1700for (var i 0 ; i domains.length ; i) {context.beginPath();context.rect(10i*4,0,4,20);console.log(domains[i]);context.fillStyle scale(domains[i]).hex();context.fill();}context.fillStyle black;context.fillText(0 mm, 0, 30);context.fillText(Math.round(domains[25]) mm, 100, 30);context.fillText(Math.round(domains[50]) mm, 200, 30);context.fillText(Math.round(domains[75]) mm, 300, 30);context.fillText(1700 mm, 390, 30); 在这里我们只使用我们更容易看到的比例并遍历各个域以创建彩色图例。 参考 使用HTML5Canvas创建全球降水降雨可视化并从Smart Java博客的JCG合作伙伴 Jos Dirksen 打开数据 。 翻译自: https://www.javacodegeeks.com/2014/02/create-global-precipitation-rain-visualizations-with-html5-canvas-and-open-data.html初始化创建画布