【问题标题】:Function returns array with dates of tiles函数返回包含瓷砖日期的数组
【发布时间】:2017-12-01 22:12:06
【问题描述】:

我有 js 代码,它返回存储在我的 PC 上的图层日期(使用 OpenLayers 和 Momentjs)。

正如我们所见,该函数以 60 秒的步长返回文件夹(文件夹)中两个日期之间的所有日期。但我只想返回我在 PC 上拥有文件(图层)的日期,因为我没有所有日期的图层。

所以我需要一个函数返回一个我只有瓦片的日期数组,然后根据输入的日期从该图层添加到地图

function loopLayer() {
  const FromDateTime = document.getElementById("fromdate").value;
  const dateFrom = moment(FromDateTime, "YYYY-MM-DD HH:mm:ss", true);
  if (!dateFrom.isValid()) {
    log("something");
    return;
  }

  const ToDateTime = document.getElementById("todate").value;
  const dateTo = moment(ToDateTime, "YYYY-MM-DD HH:mm:ss", true);
  if (!dateTo.isValid()) {
    log("something");
    return;
  }

  let loopDate = dateFrom;
  for(let i=0; dateFrom.isSameOrBefore(dateTo) && i < 100; i++) {
    // preventing from loading thousands of layers
    loopLayerByDate(loopDate);
    loopDate = loopDate.add(60, 'seconds');

  }
}

function loopLayerByDate(dateObject) {
  const folderDate = dateObject.format("YYYY-MM-DD_HHmmss");
  const source = new ol.source.XYZ({
    projection: 'EPSG:3854',
    // adapt url and source tile type to your setup
    url: "folder/" + folderDate + "/{z}/{x}/{-y}.png"

  });


  const layer = new ol.layer.Tile({
    source: source,
    title: "layer"
  });
  map.addLayer(layer)
}

【问题讨论】:

    标签: javascript momentjs openlayers layer


    【解决方案1】:

    出于安全原因,网站通常无法从您的本地文件系统中读取数据。否则任何网站都可能监视您的硬盘。

    正如您已经发现的那样,该规则有一个例外:当您打开本地 HTML 文件时,它可以从硬盘读取文件内容。但是您无法浏览文件夹,因此我们无法读取可用日期的列表。

    你现在有两个选择:

    1. 添加&lt;input type="file" multiple&gt;,上传文件并使用FileAPI(此处为example)。
    2. 你的东西是你从硬盘打开的本地 html 文件。您可以使用试错法猜测方法
    3. 找到一种无需猜测即可构建日期列表的方法,例如使用不断增加的数字而不是时间戳来命名文件夹!
    4. 使用服务于一切的服务器软件。服务器可以访问文件系统并向“前端”发送所需的日期列表。我不会在这里提供操作方法,stackoverflow 和搜索引擎上有大量的软件解决方案和操作方法。

    选项 2,本地 html:

    由于您大致知道文件名的范围,您可以使用蛮力方法,只查询一个范围内的所有日期,看看哪些日期实际响应。请注意,这种方法远非理想,而且可能非常缓慢

    function guessValidDates(arrayOfDates){
        const validDates = [];
        arrayOfDates.forEach((date) => {
            var xhttp = new XMLHttpRequest();
            xhttp.open("GET", "time/" + date + "/1.png", true);
            xhttp.send();
        console.log('request returned', xhttp);
            if (xhttp.response) {
                validDates.push(date;
            }
        });
        return validDates;
    }
    

    示例用法:

    // example from loopLayer function
    let loopDate = dateFromObject;
    const allDates = [];
    for(let i=0; dateFromObject.isSameOrBefore(dateToObject) && i < 100; i++) {
      // the i counts as a failsafe, preventing us from loading billions of 
      // or whatever the pattern is for your file path
      allDates.push(loopDate.format("YYYY-MM-DD_HHmmss"));
    
      // step forward by X
      loopDate = loopDate.add(1, 'minutes');
    }
    
    const validDates = guessValidDates(allDates);
    // now you know the valid dates and can use them. Example:
    validDates.forEach(function(someDate){ 
      loopLayerByDate(someDate);
    });
    

    或者,如果您有一个模式,即一天内所有层的数量都在增加,例如"time/" + yearMontDay + '_' + increasingNumber + "/{z}/{x}/{-y}.png",则继续添加层,直到您得到无效响应:

    function isValidLayer(someDateString, someNumber) {
      var xhttp = new XMLHttpRequest();
      xhttp.open("GET", "time/" + someDateString + "_" + someNumber + "/1.png", true);
      xhttp.send();
      if (xhttp.response) {
          return true;
      }
      return false;
    }
    
    // you can now count up until you don't get a valid response anymore:
    
    let someDateString = dateObject.format("YYYY-MM-DD_HHmmss");
    let increasingNumber = 0;
    while(increasingNumber < 1000) {
        // the condition is just a failsafe
        if(isValidLayer(someDateString, increasingNumber) {
          // add layer with that number to your map
          const source = new ol.source.XYZ({
            projection: 'EPSG:4326',
            wrapX: false,
            url: "time/" + folderDate + "_" + increasingNumber + "/{z}/{x}/{-y}.png"
          });
          // TODO add layer here and so on....
        } else {
          // no more layers, stop!
          console.log('stopped after' + increasingNumber + 'layers on date ' + someDateString);
          break;
        }
    }
    

    【讨论】:

    • 只需将它们命名为“1”、“2”、“3”……或者其他一些可预测的模式。
    • 是的,但用户将为 ex (yyyy-mm-dd hh:mm:ss) 输入两个日期,结果是这两个日期之间的日期文件夹中的所有层的循环!所以我仍然需要他们的名字并使用 momentjs
    • 既然您在谈论“用户”,您很可能不会将您的数据文件夹发送给用户,对吗?然后选择选项 4(请参阅更新的答案)并提供服务器!我知道这对初学者来说并不容易,但是有很多关于如何通过网络提供东西的教程,例如使用 node.js
    • 除非你想出一个可预测的模式,否则你就迷路了。如果您可以更改文件夹名称,只需使用 2006-04-01_{increasingnumberhehre} 或其他模式。或者,生成图层数据的东西也可以写入文本文件,因此您可以使用上面的示例获取该文本文件并从那里解析日期?有非常简单的服务器解决方案可用,您可以直接放入项目中。例如。 npmjs.com/package/simple-http-server
    • 我做了选项2,没有调试错误,但是没有结果!我在哪里可以在我的代码中实现它,以便它与我的循环函数正常工作?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-29
    • 1970-01-01
    • 2018-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多