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

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

我通过将文件放置在sites/all/libraries/cesium/Cesium.js中并附带资源和小部件文件夹来将Cesium库添加到Drupal项目中,然后在自定义模块中调用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以将Viewer附加到我的#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"的值不是null或undefined,但似乎是一个暗示未完整形成的Viewer对象结构。该对象缺少所有前缀为下划线的属性,例如_dataSourceAdded。

有人知道这可能是什么原因吗?

最后,在发布之前,我看到Drupal中有一个Cesium模块,在hook_libraries_info_alter中有一些有趣的事情发生,其中Cesium代码库被保存为public://cesium_base_url.js。请参阅cesium.module中的第50-59行,该文件位于https://www.drupal.org/project/cesium

 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对象

用于观察的环境变量:

我将“this”发送到Cesium.js中Viewer函数内,在设置完所有私有属性(前缀为_underscore的属性)之后,并在调用查看器对象上的_dataSourceAdded函数之前(在我修改的未压缩的Cesium.js上的第169769行)。

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));

  • 被识别为“查看器”对象;

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

  • 其中53个是私有的。

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

  • 被识别为“对象”对象;

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

  • 其中0个是私有的。


你的代码中有一行写着 var viewer = Cesium.Viewer...,这里缺少了一个 new 关键字。应该改为 var viewer = new Cesium.Viewer... - emackey
你说得对!添加“new”可以大大减少对象上的属性数量,尽管它仍然没有加载数据源并且仍然缺少任何私有属性。我很快会更新我的问题。再次感谢! - Emmanuel Buckshi
好的,问题解决了!请发布一个答案,以便我可以给你那些赏金分。错过这样一个小细节真是太傻了,太高兴你能发现它了。 - Emmanuel Buckshi
2个回答

4

上述代码最初有一行用于创建查看器的代码:

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

缺少了 new 关键字:

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

使用new关键字可以正确构建Cesium Viewer的新实例。有关new的详细信息,请参见Stack Overflow上的此答案


3

对此已经有了一些进展。原来,Assets/Widgets/Workers目录中的每一个都必须位于libraries/cesium/Build/Cesium/内。

现在,地球仪看起来正常,并且似乎正在运作(需要测试是否存在限制)。但是,“this._dataSourceAdded不是一个函数”的错误仍然存在,不过据我所知并没有引起任何问题。

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


更新:所有功能似乎都正常,直到我尝试加载数据源。数据源中的数据看起来很好,但地图上没有构建任何要素。 - Emmanuel Buckshi
我所见过的关于这个错误的唯一其他参考资料:https://groups.google.com/forum/#!msg/cesium-dev/MAVRdeFWYjk/s31zbc9tAQAJ - Emmanuel Buckshi
更新:我尝试在没有Drupal.behaviors的情况下运行代码。相反,我只是将它放在了一个setTimeout函数中,但仍然导致相同的错误信息。至少我们可以假设Drupal.behaviors与问题无关。 - Emmanuel Buckshi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接