Drupal 中的 Cesium:在 Drupal 页面上加载查看器
Cesium in Drupal: Load Viewer on a Page in Drupal
重要提示
在正常项目中实例化Cesium Object时,它没有任何以下划线为前缀的属性(_dataSourceCollection、_dataSourceDisplay等)。然而,当在 Drupal 中实例化时,除了通常的属性外,还会在对象上设置大约 40-45 个属性(所有属性都带有下划线前缀)。这发生在 Drupal 7 或 8 中,虽然我不确定这是否与我遇到的问题相关,但这是一个明显的差异,因此我认为应该共享它。
我已将 Cesium 库添加到 Drupal 项目中,方法是将文件与 Assets 和 Widgets 文件夹一起放在 sites/all/libraries/cesium/Cesium.js 中,然后还在自定义模块中调用 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 来 return 以下页面回调:
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" 的值不是 null 或未定义,但似乎是暗示未完全形成的 Viewer 对象的结构。此对象缺少所有以下划线为前缀的属性,例如 _dataSourceAdded。
有没有人知道为什么会这样?
最后,就在发布这篇文章之前,我看到有一个 Cesium 的 Drupal 模块,它在 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 中的查看器对象
观察的环境变量:
我在 Cesium.js 的 Viewer 函数内发送 "this" 到 console.log,在设置所有私有属性(属性前缀为 _underscore)之后,就在之前在 Viewer 对象上调用 _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;)
识别为"Viewer"对象
循环 "key in obj" 找到 61 个属性
其中 53 个是私有的
Drupal 应用程序
- 41 个属性 (Object.keys(this).length))
识别为"Object"对象
循环 "key in obj" 找到 61 个属性
其中 0 个是私有的
这方面取得了一些进展。事实证明,每个 Assets/Widgets/Workers 目录都必须位于 libraries/cesium/Build/Cesium/
内
现在,地球仪显示正常并且似乎在运行(需要测试看是否有限制)。 "this._dataSourceAdded is not a function" 错误仍然存在,但据我所知,它似乎没有引起任何问题。
我会在更多测试后更新。
上面的代码最初使用这一行来创建查看器:
var viewer = Cesium.Viewer('myApp-cesium',
缺少 new
关键字:
var viewer = new Cesium.Viewer('myApp-cesium',
需要 new
关键字才能正确构造 Cesium 查看器的新实例。有关 new
确切功能的详细信息,请参阅 this answer on Stack Overflow。
重要提示 在正常项目中实例化Cesium Object时,它没有任何以下划线为前缀的属性(_dataSourceCollection、_dataSourceDisplay等)。然而,当在 Drupal 中实例化时,除了通常的属性外,还会在对象上设置大约 40-45 个属性(所有属性都带有下划线前缀)。这发生在 Drupal 7 或 8 中,虽然我不确定这是否与我遇到的问题相关,但这是一个明显的差异,因此我认为应该共享它。
我已将 Cesium 库添加到 Drupal 项目中,方法是将文件与 Assets 和 Widgets 文件夹一起放在 sites/all/libraries/cesium/Cesium.js 中,然后还在自定义模块中调用 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 来 return 以下页面回调:
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" 的值不是 null 或未定义,但似乎是暗示未完全形成的 Viewer 对象的结构。此对象缺少所有以下划线为前缀的属性,例如 _dataSourceAdded。
有没有人知道为什么会这样?
最后,就在发布这篇文章之前,我看到有一个 Cesium 的 Drupal 模块,它在 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 中的查看器对象
观察的环境变量:
我在 Cesium.js 的 Viewer 函数内发送 "this" 到 console.log,在设置所有私有属性(属性前缀为 _underscore)之后,就在之前在 Viewer 对象上调用 _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;)
识别为"Viewer"对象
循环 "key in obj" 找到 61 个属性
其中 53 个是私有的
Drupal 应用程序 - 41 个属性 (Object.keys(this).length))
识别为"Object"对象
循环 "key in obj" 找到 61 个属性
其中 0 个是私有的
这方面取得了一些进展。事实证明,每个 Assets/Widgets/Workers 目录都必须位于 libraries/cesium/Build/Cesium/
内现在,地球仪显示正常并且似乎在运行(需要测试看是否有限制)。 "this._dataSourceAdded is not a function" 错误仍然存在,但据我所知,它似乎没有引起任何问题。
我会在更多测试后更新。
上面的代码最初使用这一行来创建查看器:
var viewer = Cesium.Viewer('myApp-cesium',
缺少 new
关键字:
var viewer = new Cesium.Viewer('myApp-cesium',
需要 new
关键字才能正确构造 Cesium 查看器的新实例。有关 new
确切功能的详细信息,请参阅 this answer on Stack Overflow。