开发者问题收集

Drupal 中的 Cesium:在 Drupal 的页面上加载查看器

2016-09-10
536

重要提示 在普通项目中实例化 Cesium 对象时,它没有任何以下划线为前缀的属性(_dataSourceCollection、_dataSourceDisplay 等)。然而,在 Drupal 中实例化时,除了通常的属性外,对象上还设置了大约 40-45 个属性(所有属性都以下划线为前缀)。这发生在 Drupal 7 或 8 中,虽然我不确定这是否与我遇到的问题有关,但这是一个明显的差异,因此我认为应该分享它。

我已将 Cesium 库添加到 Drupal 项目中,方法是将文件放在 sites/all/libraries/cesium/Cesium.js 以及 Assets 和 Widgets 文件夹中,然后还在自定义模块中调用 hook_library_info

function cesium_library_info() {
  $libraries['cesium'] = array(
    'files' => array(
      'js' => 'Cesium.js',
    ),
    'path' => 'js',
    'library path' => libraries_get_path('cesium'),
    'version' => '1'
  );
  return $libraries;
}

然后我使用 hook_menu 返回以下页面回调:

function cesium_page()  {
  drupal_add_js(libraries_get_path('cesium') . '/Cesium.js');
  drupal_add_js(drupal_get_path('module', 'cesium') . '/js/mCesium.js');
  drupal_add_css(libraries_get_path('cesium') . '/Widgets/widgets.css');

  $page = array();

  $page['ces-container'] = array(
    '#prefix' => '<div id="myApp-cesium">',
    '#suffix' => '</div>',
    '#markup' => '<h1>Welcome to Cesium!',
  );
  return $page;
}

mCesium.js 包含从 Drupal.behaviors 中调用 Cesium 的代码,以将查看器附加到我的 #myApp-cesium 元素。

Drupal.behaviors.cesium = {
  attach: function (context, settings) {

    var viewer = new Cesium.Viewer('myApp-cesium', {
        imageryProvider : new Cesium.createOpenStreetMapImageryProvider({
            url : 'http://thebestmaptiles.map.tile.com/',
        }),
        baseLayerPicker : false
    });
  }
}

这成功地在Drupal 页面。然而,查看器完全没有内容,控制台中出现以下错误:

Cesium.js:169769 Uncaught TypeError: this._dataSourceAdded is not a function

“this”的值不为空或未定义,但似乎是暗示 Viewer 对象形成不完整的结构。此对象缺少所有以下划线为前缀的属性,例如 _dataSourceAdded。

有人知道为什么会这样吗?

最后,就在发布此文之前,我看到 Cesium 有一个 Drupal 模块,在 hook_libraries_info_alter 中发生了一些有趣的事情,其中​​ Cesium 代码库被保存为 public://cesium_base_url.js。

请参阅 https://www.drupal.org/project/cesium 上 cesium.module 的第 50-59 行>

 47 function cesium_libraries_info_alter(&$libraries) {                                                                             
 48   $library = libraries_detect('cesium');                                                                                        
 49                                                                                                                                 
 50   if ($library['installed'] == TRUE) {                                                                                          
 51     $data = "var CESIUM_BASE_URL = '" . url($library['library path'] . '/Build/Cesium/') . "';";                                
 52     $jsfile = file_unmanaged_save_data($data, 'public://cesium_base_url.js', FILE_EXISTS_REPLACE);                              
 53                                                                                                                                 
 54     $libraries['cesium']['files']['js'][$jsfile] = array(                                                                       
 55       'data' => $jsfile,                                                                                                        
 56       'weight' => 0,                                                                                                            
 57       'group' => JS_LIBRARY,                                                                                                    
 58     );                                                                                                                          
 59   }                                                                                                                             
 60 }            

我不确定这种方法是否相关,但我认为值得一提,以防万一。无论如何,我还应该提到,我尝试了一个新项目来测试该模块是否可行,但我相信下载库的代码必须更新。

编辑

我还想提一下,我在 Drupal 7 和 Drupal 8 上都复制了同样的情况,出现了同样的错误。

这是在没有 Drupal.behaviors 的情况下加载的代码,它再次创建了与加载不充分的 Cesium.Viewer 对象相同的情况:

setTimeout(function() {

    var viewer = new Cesium.Viewer('myApp-cesium', {
        imageryProvider : new Cesium.createOpenStreetMapImageryProvider({
            url : 'http://thebestmaptiles.map.tile.com/',
        }),
        baseLayerPicker : false
    });
}, 5000);

另一个更新:

将 javascript 放在 jQuery 包装器中似乎没有任何好处。

我也试过看看在 hook_init() 函数中添加库是否有帮助,但没有帮助。

另一个更新:

值得注意的差异 - HelloWorld 应用程序中的查看器对象与Drupal

用于观察的环境变量:

在所有私有属性都已设置(以 _ 下划线为前缀的属性)之后,并且在调用 Viewer 对象上的 _dataSourceAdded 函数之前(在我修改过的、未缩小的 Cesium.js 上的第 169769 行),我将“this”发送到 Cesium.js 的 Viewer 函数内的 console.log

console.log(this);
var dataSourceLength = dataSourceCollection.length;
for (var i = 0; i < dataSourceLength; i++) {
    this._dataSourceAdded(dataSourceCollection, dataSourceCollection.get
   (i));          

以下是主要区别:

HelloWorld 应用 - 41 个属性(根据 console.log(Object.keys(this).length);)

  • 识别为“Viewer”对象

  • 循环遍历“key in obj”发现 61 个属性

  • 其中 53 个是私有的

Drupal 应用 - 41 个属性 (Object.keys(this).length))

  • 识别为“Object”对象

  • 循环遍历“key in obj”发现 61 个属性

  • 其中 0 个是私有的

2个回答

上述代码原本包含以下行来创建查看器:

var viewer = Cesium.Viewer('myApp-cesium',

缺少 new 关键字:

var viewer = new Cesium.Viewer('myApp-cesium',

需要 new 关键字才能正确构建 Cesium 查看器的新实例。有关 new 的具体功能的详细信息,请参阅 Stack Overflow 上的此答案

emackey
2016-10-04

这方面取得了一些进展。事实证明,每个 Assets/Widgets/Workers 目录都必须位于 libraries/cesium/Build/Cesium/ 内

现在,地球仪显示正常,似乎可以正常工作(需要测试是否存在限制)。但是,“this._dataSourceAdded 不是函数”错误仍然存​​在,尽管据我所知,它似乎没有引起任何问题。

我会在进行更多测试后更新。

Emmanuel Buckshi
2016-09-12