TYPO3 FAL upload frontend add title, alternative and description - upload

I have an extension where user can upload in frontend some images to their frontend-profile. Image upload and saving to user-profile works fine, I user following code - but is there a simple way to add title, alternative and description too?
Thanks for help!
Martin
/** #var \TYPO3\CMS\Core\Resource\StorageRepository $storageRepository */
$storageRepository = $this->objectManager->get('TYPO3\CMS\Core\Resource\StorageRepository');
/** #var \TYPO3\CMS\Core\Resource\ResourceStorage $storage */
$storage = $storageRepository->findByUid('1');
#$storageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
#$storage = $storageRepository->findByUid(1); # Fileadmin = 1
#$saveFolder = $storage->getFolder($this->settings['uploadFolder']);
$fileData = array();
$fileData['name'] = $_FILES['tx_key_datenwartung']['name']['logo'][0];
$fileData['type'] = $_FILES['tx_key_datenwartung']['type']['logo'][0];
$fileData['tmp_name'] = $_FILES['tx_key_datenwartung']['tmp_name']['logo'][0];
$fileData['size'] = $_FILES['tx_key_datenwartung']['size']['logo'][0];
// this will already handle the moving of the file to the storage:
$newFileObject = $storage->addFile(
$fileData['tmp_name'], $saveFolder, $userUid.'_'.$fileData['name']
);
$newFileObject = $storage->getFile($newFileObject->getIdentifier());
#$newFile = $this->fileRepository->findByUid($newFileObject->getProperty('uid'));
$newFile = $newFileObject->getUid();
$persistenceManager = $this->objectManager->get('TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager');
$persistenceManager->persistAll();
/** #var \Vendor\Myextension\Domain\Model\FileReference $newFileReference */
$newFileReference = $this->objectManager->get('Ven\Key\Domain\Model\FileReference');
$newFileReference->setFile($newFile);
$user->addLogo($newFileReference);

.... could solve it myself. just add setter to model and add texts:
/**
* Set alternative
*
* #param \xx\yy\Domain\Model\File $file
*/
public function setAlternative($alternative) {
$this->alternative = $alternative;
}
and to controller:
$newFileReference->setAlternative('your alternative text for image');

Related

TYPO3 8 LTS how to generate frontend page URL in CLI/Scheduler context

I'm trying to figure out how to generate absolute frontend page URLs from CLI/Scheduler context. I've created the following helper class:
class FrontendUrlProvider
{
/**
* #var ObjectManagerInterface
*/
private $objectManager;
/**
* #var LoggerInterface
*/
private $logger;
/**
* #param ObjectManagerInterface $objectManager
* #param LoggerInterface $logger
*/
public function __construct(ObjectManagerInterface $objectManager, LoggerInterface $logger)
{
$this->objectManager = $objectManager;
$this->initializeTimeTracker();
$this->logger = $logger;
}
/**
* #param int $pageId
* #param int $languageId
* #return Uri
*/
public function pageUrl($pageId, $languageId)
{
$url = '';
$this->logger->error('generating preview link');
try {
$this->initializeTypoScriptFrontend($pageId);
$this->setUpPageDomainIfCliContext($pageId);
$contentRenderer = $this->objectManager->get(ContentObjectRenderer::class);
$command = $this->linkCommand($pageId, $languageId);
$url = $contentRenderer->typoLink_URL($command);
$this->logger->error("preview link is: $url");
} catch (\Exception $exception) {
$this->logger->error($exception->getMessage());
$this->logger->error($exception->getTraceAsString());
}
return new Uri($url);
}
private function initializeTimeTracker()
{
if (!is_object($GLOBALS['TT'])) {
$GLOBALS['TT'] = new \TYPO3\CMS\Core\TimeTracker\NullTimeTracker();
}
}
/**
* #param int $pageId
*/
private function initializeTypoScriptFrontend($pageId)
{
if (isset($GLOBALS['TSFE']) && is_object($GLOBALS['TFSE'])) {
return;
}
$GLOBALS['TSFE'] = $this->objectManager->get(TypoScriptFrontendController::class, $GLOBALS['TYPO3_CONF_VARS'], $pageId, '');
$GLOBALS['TSFE']->sys_page = $this->objectManager->get(PageRepository::class);
$GLOBALS['TSFE']->sys_page->init(false);
$GLOBALS['TSFE']->tmpl = $this->objectManager->get(TemplateService::class);
$GLOBALS['TSFE']->tmpl->init();
$GLOBALS['TSFE']->connectToDB();
$GLOBALS['TSFE']->initFEuser();
$GLOBALS['TSFE']->determineId();
$GLOBALS['TSFE']->initTemplate();
$GLOBALS['TSFE']->getConfigArray();
}
/**
* #param int $pageId
*/
private function setUpPageDomainIfCliContext($pageId)
{
if (!isset($_SERVER['HTTP_HOST']) || !$_SERVER['HTTP_HOST']) {
$domainData = $GLOBALS['TSFE']->getDomainDataForPid($pageId);
if (is_array($domainData) && isset($domainData['domainName']) && !empty($domainData['domainName'])) {
$_SERVER['HTTP_HOST'] = $domainData['domainName'] ?: '';
}
}
}
/**
* #param int $pageId
* #param int $languageId
* #return array
*/
private function linkCommand($pageId, $languageId)
{
$languageQuery = http_build_query(['L' => $languageId], null, '&', PHP_QUERY_RFC3986);
return array(
'parameter' => $pageId,
'useCacheHash' => false,
'forceAbsoluteUrl' => true,
'linkAccessRestrictedPages' => true,
'additionalParams' => '&' . $languageQuery,
);
}
}
I'm at the point that it works fine in TYPO3 7 LTS, as long as there's a domain record for the root line.
However this same snippet doesn't work in TYPO3 8 LTS and I need it working for both 7 and 8 at the same time. Obviously, I have set the domain record on the root line in v8, I cleared all the caches, etc. but I can't get an absolute URL in place. I only get the relative URL. At this point I'm not that interested in realUrl or anything like that.
For TYPO3 7 I basically reverse engineered it but with TYPO3 8 it seems a bit more complicated. Do you know what can I do more to get the page frontend URL?
It seems that the issue was an internal cache of the GeneralUtility, which cached a null value for the HTTP_HOST of $_SERVER superglobal.
Therefore the following line from my example above had no effect
$_SERVER['HTTP_HOST'] = $domainData['domainName'] ?: '';
In order to make it work under the CLI/Scheduler scope I had to clear the internal cache of the GeneralUtility by calling
TYPO3\CMS\Core\Utility\GeneralUtility::flushInternalRuntimeCaches();
before making a call to $contentRenderer->typoLink_URL($command);
Now frontend URL generation works fine on both TYPO3 7 and 8 LTS.
https://wissen.netzhaut.de/typo3/extensionentwicklung/typolink-realurl-in-scheduler-tasks/
But really: I'd recommend using a curl call against a custom page which will deliver the link (sort of as a rest API) - because thereby you go around almost all issues - and there are more beyond not having tsfe (e.g. safePath \ images).

hyperledger composer #returns not working

In Hyperledger Composer, v 19.12, I am trying to use the #returns decorator to return an asset. When I call the function through the REST API though I get a succesful transaction (200 return code) but do not get the Account object in the Response Body. Here is the transaction as defined in the data model file, the associated transaction function, and the Response Body from the REST API call. The Account object is defined in the same model file.
I expect to get an Account JSON object back. What am I doing wrong?
Transaction model
/*
Read only transaction to load account
*/
#commit(false)
#returns(Account)
transaction LoadAccountTx {
o String accountId
}
Transaction function
/**
* function to load account
* #param {org.scsvault.history.LoadAccountTx} loadAccountTx
* #returns {org.scsvault.history.Account} The resulting array of accounts
* #transaction
*/
async function loadAccount(loadAccount)
{
var i = 2;
var factory = getFactory();
var NS = 'org.scsvault.history';
var account = factory.newResource(NS, 'Account', 'ACCOUNT_1');
account.accountType = 'CREDITCARD';
account.balance = 100;
account.openingbalance = 1000;
account.opendate = new Date(2017, i, i);
if (i % 2) {
account.approvalStatus = 'REQUEST_PENDING';
}
else {
account.approvalStatus = 'CREATE';
}
account.status = 'PENDING_APPROVAL';
account.creditlimit = i * 1000;
account.term_months = i;
account.encryptedDescription = account.accountType + ' from Chase';
account.apr = i;
return account;
}
Response Body:
{
"$class": "org.scsvault.history.LoadAccountTx",
"accountId": "ACCOUNT_1",
"transactionId": "09c9eb722fe3adda41fe0a4d1060ab4efff4c2ca9ad817a763dae81374123b4c"
}
EDIT:
To test further, I changed the code above to be a simple string return value and do not receive the test string back throught the REST API.
#returns(String)
transaction LoadAccountTx {
o String accountId
}
/**
* function to load account
* #param {org.scsvault.history.LoadAccountTx} loadAccountTx
* #returns {string} (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/string)
* #transaction
*/
async function loadAccount(loadAccount)
{
return "This is a test string";
}
just adding to what #nicolapaoli wrote: this is fixed in Hyperledger Composer release v0.19.13 FYI - you do get the return value.
I had very similar issue. I've just opened an issue with general example on GitHub here with ref to this question and to the message on Rocketchat as well. Hope this will be fixed soon.

Absolute path in Magento2

How can I get the absolute path of a media file in Magento2?
I write a function to get the absolute path, but it is not working.
public function getAbsolutePath()
{
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
/** #var \Magento\Framework\Filesystem $filesystem */
$filesystem = $objectManager->get('Magento\Framework\Filesystem');
/** #var \Magento\Framework\Filesystem\Directory\WriteInterface $mediaDirectory */
$mediaDirectory = $filesystem->getDirectoryWrite(Magento\Framework\App\Filesystem\DirectoryList::MEDIA);
$mediaPath = $mediaDirectory->getAbsolutePath();
return $mediaPath;
}
app/autoloader.php
contains:
/**
* Shortcut constant for the root directory
*/
define('BP', dirname(__DIR__));
One could do something like:
$mediaPath = BP.'/pub/media/';
That said, Magento\Framework\Filesystem via dependency injection is my preferred method
You can use to get media and base Absolute path in magento 2 like:
$storeManager = $_objectMedia->get('Magento\Store\Model\StoreManagerInterface');
$currentStore = $storeManager->getStore();
$mediaUrl = $currentStore->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
$_baseurl = $storeManager->getStore()->getBaseUrl();
Try it's working fine for me....
/* #var \Magento\Framework\ObjectManagerInterface $om /
$om = \Magento\Framework\App\ObjectManager::getInstance();
$dir = $om->get('Magento\Framework\Filesystem');
$mediadir = $dir->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA);
$path = $mediadir->create('foldername');
try it its working for me..
Relying on the BP isn't a good way to go this, BP should only be used in the low layers in Magento.
Magneto has init config values where the media directory could possibly be outside of the base path. You should rely on the \Magento\Framework\App\Filesystem\DirectoryList object instead.
In the bootstrap you can see:
\Magento\Framework\App\Bootstrap::createFilesystemDirectoryList
class Bootstrap
{
/**
* Creates instance of filesystem directory list
*
* #param string $rootDir
* #param array $initParams
* #return DirectoryList
*/
public static function createFilesystemDirectoryList($rootDir, array $initParams)
{
$customDirs = [];
if (isset($initParams[Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS])) {
$customDirs = $initParams[Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS];
}
return new DirectoryList($rootDir, $customDirs);
}
}
This means if you set $_SERVER variables during bootstrap:
$tmpDir = '/var/tmpfs_mount';
$applicationDir = '/var/www/html/magento';
$loggingDir = '/var/log/restricted';
$params = $_SERVER;
$filesystemsDirs = $params[Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS];
$filesystemsDirs[DirectoryList::CONFIG] = [DirectoryList::PATH => $applicationDir . "/var/cache"];
$filesystemsDirs[DirectoryList::MEDIA] = [DirectoryList::PATH => $tmpDir . "/var/cache"];
$filesystemsDirs[DirectoryList::GENERATED] = [DirectoryList::PATH => $tmpDir . "/generated"];
$filesystemsDirs[DirectoryList::CACHE] = [DirectoryList::PATH => $tmpDir . "/var/cache"];
$filesystemsDirs[DirectoryList::LOG] = [DirectoryList::PATH => $loggingDir . "/var/log"];
$params[Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS] = $filesystemsDirs;
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $params);
To do via the object manager, add the DirectoryList object to the constructor:
use \Magento\Framework\App\Filesystem\DirectoryList;
class MyModuleClass
{
/**
* #var DirectoryList
*/
private $directoryList;
/**
* #param DirectoryList $directoryList
*/
public function __construct(DirectoryList $directoryList)
{
$this->directoryList = $directoryList;
}
/**
* #var DirectoryList
*/
private $mediaPath;
public function getMediaAbsolutePath(){
if (!$this->mediaPath){
$this->mediaPath = $this->directoryList->getPath(DirectoryList::MEDIA);
}
return $this->mediaPath;
}
}
Please note this will only get you the path, but it won't validate if via the PathValidator introduced in Magento 2.3. This PathValidator ensures that the path is allowed within the installation, you'll need to validate it yourself
vendor/magento/framework/Filesystem/Directory/PathValidator.php
P.S I haven't tested the code, I've just eye'd it from memory, so if it breaks let me know.
With Object manager:
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$directoryList = $objectManager->get('Magento\Framework\App\Filesystem\DirectoryList');
$media = $directoryList->getPath('media');
With dependency injection:
Use class `\Magento\Framework\App\Filesystem\DirectoryList
protected $_directoryList;
public function __construct(
...
\Magento\Framework\App\Filesystem\DirectoryList $directoryList
...
) {
$this->_directoryList = $directoryList;
}
For Root Folder
$this->_directoryList->getRoot();
For media Folder
$this->_directoryList->getPath('media');
Other Folders
// Get app folder
$this->_directoryList->getPath('app');
// Get etc Folder
$this->_directoryList->getPath('etc');
// Get public folder
$this->_directoryList->getPath('pub');
// Get var folder
$this->_directoryList->getPath('var');
you can use this:
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$fileSystem = $om->get('Magento\Framework\Filesystem');
$mediaDirectory = $fileSystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA);
Use blow code for geting absolute url of an image you have uploaded in product page.
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$b_url = $objectManager->get('Magento\Store\Model\StoreManagerInterface')
->getStore()
->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
// here product_badge is custom image attribute code, replace it with yours attribute.
$_product = $block->getProduct();
$product_badge = $_product->getResource()->getAttribute('product_badge')->getFrontend()->getValue($_product);
?>
<img src="<?php echo $b_url.'/catalog/product'.$product_badge; ?>" />
$rootDirectory = Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Framework\Filesystem')
->getDirectoryRead(DirectoryList::MEDIA);

ErrorException in PlaceController.php line 101: Trying to get property of non-object - Laravel 5.1*

I am trying to create a page where an user can put some data and save or post it. But when I try to visit my place adding url I get an error "ErrorException in PlaceController.php line 101: Trying to get property of non-object"
My Route:
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/
Route::get('/','FrontView#index');
Route::get('/placesbydiv','FrontView#placesByDiv');
Route::get('/placesbydist','FrontView#placesByDist');
Route::get('/blog',['as' => 'blog', 'uses' => 'PostController#blog']);
//authentication
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
// check for logged in user
Route::group(['middleware' => ['auth']], function()
{
// show new post form
Route::get('new-post','PostController#create');
// save new post
Route::post('new-post','PostController#store');
// edit post form
Route::get('edit/{slug}','PostController#edit');
// update post
Route::post('update','PostController#update');
// delete post
Route::get('delete/{id}','PostController#destroy');
// display user's all posts
Route::get('my-all-posts','UserController#user_posts_all');
// display user's drafts
Route::get('my-drafts','UserController#user_posts_draft');
// add comment
Route::post('comment/add','CommentController#store');
// delete comment
Route::post('comment/delete/{id}','CommentController#distroy');
});
//users profile
Route::get('user/{id}','UserController#profile')->where('id', '[0-9]+');
// display list of posts
Route::get('user/{id}/posts','UserController#user_posts')->where('id', '[0-9]+');
// display list of posts by category
Route::get('category/{id}/posts','UserController#category_posts')->where('id', '[0-9]+');
// display single post
Route::get('/{slug}',['as' => 'post', 'uses' => 'PostController#show'])->where('slug', '[A-Za-z0-9-_]+');
//Places
Route::get('/place',['as' => 'place', 'uses' => 'PlaceController#place']);
// check for logged in user
Route::group(['middleware' => ['auth']], function()
{
// show new post form
Route::get('new-place','PlaceController#create');
// save new post
Route::post('new-place','PlaceController#store');
// edit post form
Route::get('edit/{slug}','PlaceController#edit');
// update post
Route::post('update','PlaceController#update');
// delete post
Route::get('delete/{id}','PlaceController#destroy');
// display user's all posts
Route::get('my-all-places','UserController#user_places_all');
// display user's drafts
Route::get('my-places-drafts','UserController#user_places_draft');
// add comment
//Route::post('comment/add','CommentController#store');
// delete comment
//Route::post('comment/delete/{id}','CommentController#distroy');
});
//users profile
//Route::get('user/{id}','UserController#profile')->where('id', '[0-9]+');
// display list of posts
Route::get('user/{id}/places','UserController#user_places')->where('id', '[0-9]+');
// display single post
Route::get('/{slug}',['as' => 'place', 'uses' => 'PlaceController#show'])->where('slug', '[A-Za-z0-9-_]+');
My Place controller:
<?php
namespace App\Http\Controllers;
use App\Places;
use App\User;
use App\Div;
use Redirect;
use App\Http\Controllers\Controller;
use App\Http\Requests\PlaceFormRequest;
use Illuminate\Http\Request;
class PlaceController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return view('home', array('page' => 'home'));
}
public function place(Request $request){
//fetch 5 posts from database which are active and latest
$places = Places::where('active',1)->orderBy('created_at','desc');
//page heading
$title = 'দর্শনীয় স্থান';
$search_key = $request->input('body');
if(!empty('$search_key')){
$places->where('body','LIKE','%'.$search_key.'%');
}
$places = $places->paginate(5);
//return home.blade.php template from resources/views folder
return view('place')->withPlaces($places)->withTitle($title);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create(Request $request)
{
// if user can post i.e. user is admin or author
if($request->user()->can_post())
{
$divs = \DB::table('divs')->lists('div', 'id');
return view('places.create')->with('divs', $divs);
}
else
{
return redirect('/')->withErrors('You have not sufficient permissions for writing post');
}
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(PlaceFormRequest $request)
{
$place = new Places();
$place->title = $request->get('title');
$place->url = $request->get('url');
$place->location = $request->get('location');
$place->gmap_location = $request->get('gmap_location');
$place->slug = $place->url;
$place->body = $request->get('body');
//$post->slug = str_slug($post->title);
// $place->author_id = $request->user()->id;
$place->div_id = $request->get('div');
$place->source_url = $request->get('source_url');
if($request->has('save'))
{
$place->active = 0;
$message = 'Place saved successfully';
}
else
{
$place->active = 1;
$message = 'Place added successfully';
}
$place->save();
return redirect('edit/'.$place->slug)->withMessage($message);
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($slug)
{
$place = Places::where('slug',$slug)->first();
$div = \DB::table('divs')->where('id',$place->div_id)->first(); **//THIS IS THE ERROR LINE**
if(!$place)
{
return redirect('/')->withErrors('requested page not found');
}
// $comments = $post->comments;
return view('places.show')->withPlace($place)->withDiv($div);
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit(Request $request,$slug)
{
$place = Places::where('slug',$slug)->first();
if($place && ($request->user()->can_post() || $request->user()->is_admin()))
return view('places.edit')->with('place',$place);
return redirect('/')->withErrors('you have not sufficient permissions');
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request)
{
$place_id = $request->input('place_id');
$place = Places::find($place_id);
if($place && ($request->user()->can_post() || $request->user()->is_admin()))
{
$title = $request->input('title');
$slug = str_slug($title);
$duplicate = Places::where('slug',$slug)->first();
if($duplicate)
{
if($duplicate->id != $place_id)
{
return redirect('edit/'.$place->slug)->withErrors('Title already exists.')->withInput();
}
else
{
$place->slug = $slug;
}
}
$place->title = $title;
$place->location = $request->get('location');
$place->gmap_location = $request->get('gmap_location');
$place->body = $request->input('body');
$place->source_url = $request->get('source_url');
if($request->has('save'))
{
$place->active = 0;
$message = 'Place saved successfully';
$landing = 'edit/'.$place->slug;
}
else {
$place->active = 1;
$message = 'Place updated successfully';
$landing = $place->slug;
}
$place->save();
return redirect($landing)->withMessage($message);
}
else
{
return redirect('/')->withErrors('you have not sufficient permissions');
}
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy(Request $request, $id)
{
$place = Places::find($id);
if($place && ($request->user()->is_admin()))
{
$place->delete();
$data['message'] = 'Place deleted Successfully';
}
else
{
$data['errors'] = 'Invalid Operation. You have not sufficient permissions';
}
return redirect('/')->with($data);
}
}
Your check for if(!$place) belongs before you use $place->div_id.
It's possible that $place = Places::where('slug',$slug)->first(); is not returning a model.

Integrating OpenLayers 3 with Cesium Viewer

I'm developing using Cesium built on top of Cesium.Viewer. Cesium lacks some features so I wish to integrate with OpenLayers. I'd like to add existing OpenLayers layers to the Cesium.Viewer as if they were "imagery layers".
I've found ol3-cesium, however this only allows an entire OpenLayers map instance to be visualized on a Cesium.Scene which it creates for you. Cesium.Viewer also creates an instance of Cesium.Scene targeted at a given DOM element.
How can I add OpenLayers layers to a Cesium.Viewer?
Some code snippets for illustration
var olLayer1= new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
});
var olLayer2= new ol.layer.Vector({
source : ol.source.Vector();
});
var map = new ol.Map({
layers: [olLayer1, olLayer2],
target: 'map',
view: new ol.View({
})
});
Existing Cesium viewer
var viewer = new Cesium.Viewer('cesium-map', {});
// viewer setup code
ol3-cesium initialization - but this doesn't allow usage with existing viewer??
var ol3d = new olcs.OLCesium({map: map}); // map is the ol.Map instance
I just looked through the initialization code for OL3-Cesium and while it is essentially a wrapper on top of Cesium, the means that they decided to implement a Cesium environment is not going to play nicely if you want a hybrid Cesium.Viewer and an OL3 object.
I'm not sure of your comfort level with modifying JS libraries, but
what I personally would do is make my own ol3 cesium viewer class. Something like this gist I just threw together.
Just a warning, I have not tested this code yet. You may have to make some additional modifications if you receive errors. There may be a reason that the OL3-Cesium developers choose not to use the Cesium widget or viewer to initialize Cesium in their library, but I see no reason this wouldn't work.
Here is the constructor, but you would want the whole Gist as a separate file in your ol3-cesium library. Put it in the same directory as the ol3Cesium.js file.
excerpt from https://gist.github.com/maikuru/9e650bf88aed84982667
olcs.OLCesiumViewer = function(options) {
/**
* #type {!ol.Map}
* #private
*/
this.map_ = options.map;
var fillArea = 'position:absolute;top:0;left:0;width:100%;height:100%;';
/**
* #type {!Element}
* #private
*/
this.container_ = goog.dom.createDom(goog.dom.TagName.DIV,
{style: fillArea + 'visibility:hidden;'});
var targetElement = goog.dom.getElement(options.target || null);
if (targetElement) {
goog.dom.appendChild(targetElement, this.container_);
} else {
var vp = this.map_.getViewport();
var oc = goog.dom.getElementByClass('ol-overlaycontainer', vp);
if (oc) {
goog.dom.insertSiblingBefore(this.container_, oc);
}
}
/**
* Whether the Cesium container is placed over the ol map.
* #type {boolean}
* #private
*/
this.isOverMap_ = !goog.isDefAndNotNull(targetElement);
/**
* #type {!HTMLCanvasElement}
* #private
*/
this.canvas_ = /** #type {!HTMLCanvasElement} */
(goog.dom.createDom(goog.dom.TagName.CANVAS, {style: fillArea}));
this.canvas_.oncontextmenu = function() { return false; };
this.canvas_.onselectstart = function() { return false; };
goog.dom.appendChild(this.container_, this.canvas_);
/**
* #type {boolean}
* #private
*/
this.enabled_ = false;
/**
* #type {!Array.<ol.interaction.Interaction>}
* #private
*/
this.pausedInteractions_ = [];
/**
* #type {?ol.layer.Group}
* #private
*/
this.hiddenRootGroup_ = null;
/**
* #type {!Object.<Cesium.Viewer.Options>}
* #private
*/
var cesiumViewerConfig_ = (options.viewer || {}).scene3DOnly = true;
/**
* #type {!Cesium.Viewer}
* #private
*/
this.viewer_ = new Cesium.Viewer(this.container_, cesiumViewerConfig_);
/**
* #type {!Cesium.Scene}
* #private
*/
this.scene_ = this.viewer_.scene;
var sscc = this.scene_.screenSpaceCameraController;
sscc.inertiaSpin = 0;
sscc.ineartiaTranslate = 0;
sscc.inertiaZoom = 0;
sscc.tiltEventTypes.push({
'eventType': Cesium.CameraEventType.LEFT_DRAG,
'modifier': Cesium.KeyboardEventModifier.SHIFT
});
sscc.tiltEventTypes.push({
'eventType': Cesium.CameraEventType.LEFT_DRAG,
'modifier': Cesium.KeyboardEventModifier.ALT
});
sscc.enableLook = false;
this.scene_.camera.constrainedAxis = Cesium.Cartesian3.UNIT_Z;
/**
* #type {!olcs.Camera}
* #private
*/
this.camera_ = new olcs.Camera(this.scene_, this.map_);
/**
* #type {!Cesium.Globe}
* #private
*/
this.globe_ = this.scene_.globe;
this.scene_.skyAtmosphere = new Cesium.SkyAtmosphere();
var synchronizers = goog.isDef(options.createSynchronizers) ?
options.createSynchronizers(this.map_, this.scene_) :
[
new olcs.RasterSynchronizer(this.map_, this.scene_),
new olcs.VectorSynchronizer(this.map_, this.scene_)
];
for (var i = synchronizers.length - 1; i >= 0; --i) {
synchronizers[i].synchronize();
}
if (this.isOverMap_) {
// if in "stacked mode", hide everything except canvas (including credits)
var credits = goog.dom.getNextElementSibling(this.canvas_);
if (goog.isDefAndNotNull(credits)) {
credits.style.display = 'none';
}
}
this.camera_.readFromView();
this.cesiumRenderingDelay_ = new goog.async.AnimationDelay(function(time) {
this.scene_.initializeFrame();
this.handleResize_();
this.scene_.render();
this.enabled_ && this.camera_.checkCameraChange();
this.cesiumRenderingDelay_.start();
}, undefined, this);
};
There are some internal classes which emulate layers using the Cesium API calls. These are in the documentation so I'm assuming "public" API.
The layers must be added to a map and cannot be used in isolation. This is required as the map defines the projection etc.
For example VectorSynchronizer creates listeners on the underlying layers and keeps the Cesium scene in sync...
new olcs.VectorSynchronizer(map, viewer.scene);

Resources