diff --git a/README.md b/README.md index f16e22b420840b14e2eb893a46610e19230ff7e0..8763224cd8af556d458bfebc9b4f4bee346d8933 100644 --- a/README.md +++ b/README.md @@ -1 +1,55 @@ -x3dom + leaflet \ No newline at end of file +# x3dom + leaflet + +You can either run the demo: +- On a web server with PHP support +- Using the "Standalone installation" instructions below (could taint your system) +- Using the "Docker image" instructions below (without tainting your system) + +## 1. Standalone installation +### 1.1. Install dependencies + +You need php-cgi installed. + +Change to the x3domlet directory +``` +cd x3domlet +``` + +If you don't have nodejs installed you may install it as a standard user through nvm with the following command: +``` +docker/install-nodejs.sh +``` + +When nodejs is installed you can run: +``` +npm install && bower install +``` + +### 1.2. Copy the test data +You need to copy the data to be displayed in directories models/ and kml/ + +### 1.3. Run the test server and open a browser window +File modifications will trigger the page reload +``` +gulp +``` + +## 2. Docker image + +The docker image allow you to run the demo in a virtual container +without tainting your system. + +The current user should be allowed to run docker. Otherwise use 'sudo'. + +### 2.1. Build the docker image +- Change to the ./docker directory. +- Run "make" to build the docker image. + +### 2.2. Test +From the directory containing the "/models" and "/kml" folders you want to use, run: +``` +x3domlet/docker/run.sh +``` +It will start the x3domlet docker image and open a browser window. +On exit the script should stop and (WARNING) will remove the container and associated volumes. + diff --git a/bower.json b/bower.json new file mode 100644 index 0000000000000000000000000000000000000000..32c3aaa85ce70d95e12d9abc31d3dadee1d86598 --- /dev/null +++ b/bower.json @@ -0,0 +1,20 @@ +{ + "name": "x3domlet", + "description": "", + "main": "", + "authors": [ + "Oleg Dzhimiev <oleg@elphel.com>" + ], + "license": "GPL-3.0", + "homepage": "https://git.elphel.com/Elphel/x3domlet", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "dependencies": { + "jquery": "^3.2.1" + } +} diff --git a/docker/.dockerignore b/docker/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..270fdb709c706e01b9f648b525b1c4711e2658b1 --- /dev/null +++ b/docker/.dockerignore @@ -0,0 +1,2 @@ +README.txt +Makefile diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..2199d6768b9b16a7d486cc8f32433a514cbf545c --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,24 @@ +FROM debian:jessie-slim +RUN apt-get update \ + && apt-get install -y \ + git \ + wget \ + php5-cgi \ + vim +RUN useradd --create-home --shell /bin/bash elphel +COPY install-nodejs.sh /tmp +USER elphel +RUN /tmp/install-nodejs.sh +WORKDIR /home/elphel +RUN cd /home/elphel \ + && git clone --single-branch -b gulp https://git.elphel.com/Elphel/x3domlet \ + && export NVM_DIR="/home/elphel/.nvm" \ + && [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" \ + && npm install -g bower gulpjs/gulp-cli \ + && cd x3domlet \ + && npm install \ + && bower install \ + && gulp build +WORKDIR /home/elphel/x3domlet +COPY docker-entrypoint.sh /home/elphel/ +ENTRYPOINT ["/home/elphel/docker-entrypoint.sh"] diff --git a/docker/Makefile b/docker/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..9eb646e6a057abe639206486910f6e6da984b7e0 --- /dev/null +++ b/docker/Makefile @@ -0,0 +1,4 @@ +all: x3domlet + +x3domlet: + docker build -t x3domlet . diff --git a/docker/README.txt b/docker/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..e7fbc7c3f5fb43b89fef13a3669cec127d8878a5 --- /dev/null +++ b/docker/README.txt @@ -0,0 +1,10 @@ +BUILD +- Run "make" to build the docker image. + +USE +- Run "docker-run.sh" from the directory containing the "/models" + and "/kml" folders you want to use. It will start the docker image + and open a browser window. + + +NOTE: The current user must be allowed to run docker. Otherwise use 'sudo'. diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh new file mode 100755 index 0000000000000000000000000000000000000000..fd5665b7c857fa01fc580a93b622a3d9eb55837a --- /dev/null +++ b/docker/docker-entrypoint.sh @@ -0,0 +1,5 @@ +#!/bin/bash +export NVM_DIR="/home/elphel/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" +exec "$@" + diff --git a/docker/docker-run.sh b/docker/docker-run.sh new file mode 100755 index 0000000000000000000000000000000000000000..937d3267614773a88a55f31e44b54493b55d5bb6 --- /dev/null +++ b/docker/docker-run.sh @@ -0,0 +1,12 @@ +#!/bin/bash +docker run -i \ + -v $(pwd)/models:/home/elphel/x3domlet/models \ + -v $(pwd)/kml:/home/elphel/x3domlet/kml \ + -p 8080:8080 \ + -p 35729:35729 \ + x3domlet \ + gulp connect & + +sleep 5 +xdg-open http://localhost:8080/index.html + diff --git a/docker/install-nodejs.sh b/docker/install-nodejs.sh new file mode 100755 index 0000000000000000000000000000000000000000..695b6b0654c47d621fd31f132c760696afa6b78b --- /dev/null +++ b/docker/install-nodejs.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -e + +echo checking for installed node version +node --version && exit + +echo get latest nvm release number ... +NVM_VERSION=$(git ls-remote --tags https://github.com/creationix/nvm master v\* | sed -r -n -e 's/.*(v[0-9\.]+)$/\1/p' | sort -V | tail -n 1) + +echo downloading nvm $NVM_VERSION +# download nvm installer +wget -q -O /tmp/install.sh https://raw.githubusercontent.com/creationix/nvm/$NVM_VERSION/install.sh + +echo installing nvm +. /tmp/install.sh +export NVM_DIR="$HOME/.nvm" +test -s "$NVM_DIR/nvm.sh" +. "$NVM_DIR/nvm.sh" + +echo get latest node LTS release number +NODE_VERSION=$(nvm ls-remote | grep LTS | tail -n 1 | sed -r -n -e 's/.*(v[0-9\.]+).*/\1/p') + +echo install nodejs +nvm install $NODE_VERSION + +# disable npm progress +touch $HOME/.npmrc +grep -q progress= $HOME/.npmrc || echo progress=false >> $HOME/.npmrc + +echo install latest npm +npm install -g npm + +echo done diff --git a/docker/run.sh b/docker/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..907ad7117ad73baae35ed409a676f9739bf354a1 --- /dev/null +++ b/docker/run.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# start the container in the background +CONTAINER=$(docker run -i \ + -d \ + -v $(pwd)/models:/home/elphel/x3domlet/models \ + -v $(pwd)/kml:/home/elphel/x3domlet/kml \ + -p 8080:8080 \ + -p 35729:35729 \ + x3domlet \ + gulp connect) || exit + +echo $CONTAINER + +# temporize +sleep 5 + +# open in browser +xdg-open http://127.0.0.1:8080/index.html + +# display container startup log +docker logs --since 0 $CONTAINER & + +# attach to container +docker attach $CONTAINER + +# on exit remove the container and its associated volumes +docker rm -f -v $CONTAINER diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000000000000000000000000000000000000..7cde97928c2e639e8f54a55bebca45754ce1e954 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,273 @@ +"use strict"; + +var gulp=require('gulp'), + bower=require('gulp-bower'), + wiredep=require('wiredep').stream, + foreach=require('gulp-foreach'), + usemin=require('gulp-usemin'), + htmlmin=require('gulp-htmlmin'), + sourcemaps=require('gulp-sourcemaps'), + uglify=require('gulp-uglify'), + cleanCss=require('gulp-clean-css'), + rev=require('gulp-rev'), + connect=require('gulp-connect'), + express=require('express'), + php=require('node-php'), + cors=require('cors'), + opn=require('opn'), + fs=require('fs'), + path=require('path'), + extend=require('extend'), + Q=require('q'), + clean=require('gulp-clean'); + +var app; +var config={ + documentRoot: './', + host: '0.0.0.0', + port: 8080, + home: 'index.html', + bowerDir: './bower_components', + dist: './dist', + +} + +function abort(err) { + console.log(JSON.stringify(err,false,4)); + process.exit(1); +} + +function getHtmlFiles() { + return gulp.src('*.html'); +} + +// handle error events and synchronous chaining using promises +function wrap(taskName,stream,q) { + stream=stream.on('error',function errorHandler(err){ + console.log('ERROR: '+taskName+' failed !'); + console.log(JSON.stringify(err,false,4)); + if (q) { + q.reject(err); + } else { + process.exit(1); + } + }).on('end',function(){ + if (q) + q.resolve(stream); + }); + if (q) return q.promise; + else return stream; +} + +// download bower dependencies +gulp.task('bower', function(cb){ + return bower() + .pipe(gulp.dest(config.bowerDir)); +}); + +// merge bower.json with file specific options +function getBowerJson(srcFile) { + try { + var srcFileJson=require(srcFile+'.json'); + } catch(e) {} + var options=(srcFileJson && srcFileJson.bower)||{}; + var bowerJson=extend(true,{},require('./bower.json'),options); + return bowerJson; +} + +// inject bower dependencies +gulp.task('wiredep', function(cb){ + return getHtmlFiles() + .pipe(foreach(function(stream,file){ + var filepath=path.join(file.cwd,file.relative); + console.log('wiredep: '+filepath); + return stream.pipe( + wrap('wiredep', wiredep({ + verbose: true, + bowerJson: getBowerJson(filepath) + })) + ); + })) + .pipe( + gulp.dest('.') + ); +}); + +// replace references to scripts and stylesheets in html files +// and store resulting files in directory "build" +gulp.task('usemin', function(cb){ + return getHtmlFiles() + .pipe(foreach(function(stream,file){ + console.log('usemin: '+path.join(file.cwd,file.relative)); + return stream.pipe(usemin({ + css: [ +// sourcemaps.init({ +// loadMaps: true +// }), + wrap('cleanCss', cleanCss()), +// 'concat', + rev(), +// sourcemaps.write() + ], + html: [ + function() { + return wrap('htmlmin', htmlmin({ + collapseWhitespace:true + })); + } + ], + js: [ + sourcemaps.init({ + loadMaps: true + }), + wrap('uglify js', uglify()), + 'concat', + rev(), + sourcemaps.write() + ], + inlinejs: [ + wrap('uglify inlinejs', uglify()) + ], + inlinecss: [ + wrap('cleanCss', cleanCss()), + 'concat' + ] + })); + })) + .pipe(gulp.dest('build/')) +}); + +gulp.task('cleanbuild', function(){ + return gulp.src('./build', {read: false}) + .pipe(clean()) +}); + +// copy files to directory "dist" +gulp.task( + 'dist', + function(cb) { + var count=3; + function goon(){ + if (--count==0) { + cb(null); + } + } + + // copy assets + wrap( + 'copy assets', + gulp.src('./assets/**/*') + .pipe(gulp.dest(config.dist)), + Q.defer() + ) + .catch(abort) + .then(goon) + .done(); + + // copy files + wrap( + 'copy files', + gulp.src([ + './build/**/*', + '*.php' + ]) + .pipe(gulp.dest(config.dist)), + Q.defer() + ) + .catch(abort) + .then(goon) + .done(); + + // copy images + wrap( + 'copy images', + gulp.src([ + './js/**/*.png' + ]).pipe(gulp.dest(path.join(config.dist,'js'))), + Q.defer() + ) + .catch(abort) + .then(goon) + .done(); + } +); +// serve content through express and php-cgi +function php_cgi(connect,options) { + app=express(); + app.use('/', php.cgi(config.documentRoot)); + return app; +} + +gulp.task('server',function(cb){ + connect.server({ + root: config.documentRoot, + host: config.host, + port: config.port, + middleware: function(connect,opt){ + return [ + cors(), + php_cgi() + ]; + }, + livereload: true + }); + cb(null); +}); + +// watch for changes +gulp.task('watch', function(cb){ + + // trigger reloading html pages when specified files change + gulp.watch( + [ + '**.html', + '**.php', + '**.css', + '**.js', + '**.kml', + '**.x3d', + '!build/**/*', + '!gulpfile.js' + ], + gulp.series('html') + ); + + // trigger package injection/removal on bower.json change + gulp.watch('bower.json', gulp.series('inject')); + + cb(null); + +}); + +// open browser +gulp.task('open', function(cb){ + opn('http://'+config.host+':'+config.port+'/'+config.home); + cb(null); +}); + +gulp.task('connect', gulp.series('server','watch','open')); + +// reload html pages on change +gulp.task('html', function(){ + return getHtmlFiles() + .pipe(connect.reload()); +}); + +// inject bower dependencies +gulp.task('inject', gulp.series('bower','wiredep')); + +// inject bower dependencies and generate directory 'build' content with usemin +gulp.task('build', gulp.series('bower','wiredep','usemin')); + +gulp.task('prod-root', function(cb){ + config.documentRoot=config.dist; + cb(null); +}); + +// start server with frorm "build" directory +gulp.task('prod', gulp.series('prod-root','build','dist','connect')); + +gulp.task( + 'default', + gulp.series('inject','connect') +); diff --git a/index.html b/index.html index 23e818e4f1877be6d84b82eed998411a594b7282..474cbaa7287a2563ffee8eaaa4e8bd98f9b5ee9a 100644 --- a/index.html +++ b/index.html @@ -4,12 +4,20 @@ <meta charset="utf-8"/> <title>x3d models index</title> - <script type='text/javascript' src='js/jquery/jquery-3.1.1.js'></script> - <script type='text/javascript' src='js/leaflet/leaflet-src.js'></script> - <script type='text/javascript' src='js/index.js'></script> - + <!-- build:css css/index.css --> + <!-- bower:css --> + <!-- endbower --> <link rel='stylesheet' type='text/css' href='js/leaflet/leaflet.css'></link> <link rel='stylesheet' type='text/css' href='js/index.css'></link> + <!-- endbuild --> + + <!-- build:js js/index.js --> + <!-- bower:js --> + <script src='bower_components/jquery/dist/jquery.js'></script> + <!-- endbower --> + <script type='text/javascript' src='js/leaflet/leaflet-src.js'></script> + <script type='text/javascript' src='js/index.js'></script> + <!-- endbuild --> </head> <body> diff --git a/js/ui_init.js b/js/ui_init.js index dcc30f8bcf832351156b899e38cb90f0394bfed2..cf075eee67f9eff1974aee638dc001901c053dd6 100644 --- a/js/ui_init.js +++ b/js/ui_init.js @@ -122,23 +122,23 @@ function light_init(){ var model_url = SETTINGS.basepath+"/"+SETTINGS.path+"/"+SETTINGS.version+"/"+SETTINGS.path+".x3d"; var model_back_url = SETTINGS.basepath+"/"+SETTINGS.path+"/"+SETTINGS.version+"/"+SETTINGS.path+"-texture-bgnd-ext.jpeg"; - var model = $(` - <group> - <inline name='mymodel' namespacename='mymodel' url='`+model_url+`'></inline> - </group> - <group> - <Background - id="Background" - class="Background" - backUrl= "js/images/background_side.jpeg" - bottomUrl="js/images/background_floor.jpeg" - frontUrl= "`+model_back_url+`" - leftUrl= "js/images/background_side.jpeg" - rightUrl= "js/images/background_side.jpeg" - topUrl= "js/images/background_sky.jpeg"> - </Background> - </group> - `); + var model = $([ + '<group>', + ' <inline name="mymodel" namespacename="mymodel" url="'+model_url+'"></inline>', + '</group>', + '<group>', + ' <Background ', + ' id="Background"', + ' class="Background"', + ' backUrl= "js/images/background_side.jpeg"', + ' bottomUrl="js/images/background_floor.jpeg"', + ' frontUrl= "'+model_back_url+'"', + ' leftUrl= "js/images/background_side.jpeg"', + ' rightUrl= "js/images/background_side.jpeg"', + ' topUrl= "js/images/background_sky.jpeg">', + ' </Background>', + '</group>' + ].join('\n')); x3delement.append(model); @@ -175,7 +175,6 @@ function light_init(){ Scene.initResize(); $.getScript("js/x3dom/x3dom-full.debug.js",function(){ - Map = new LeafletObject('leaflet_map',Data,{}); //wait until it DOM is extended x3dom.runtime.ready = function(){ @@ -189,7 +188,6 @@ function light_init(){ }; }); - }, }); diff --git a/js/x3dom_init.js b/js/x3dom_init.js index beeaa05d260bd5eaeb882b2d70fb648a914b2c8e..c46e1b292cb20940c2cc7a9f63fb29c3633046da 100644 --- a/js/x3dom_init.js +++ b/js/x3dom_init.js @@ -441,24 +441,24 @@ X3DOMObject.prototype.createMarker = function(x,y,z,id){ size = self.data.markers[index].size/2; } - var html = ` - <group id='`+id+`' class='`+sph_class+`'> - <switch whichChoice='0'> - <transform translation='`+x+` `+y+` `+z+`' rotation='0 0 0 0'> - <shape class='shapemarker'> - <appearance> - <material diffuseColor='`+color+`' transparency='0.0' myColor='`+color+`'></material> - </appearance> - <Sphere DEF="sphere" radius="`+size+`" /> - </shape> - </transform> - </switch> - </group> - `; + var html = [ + '<group id="'+id+'" class="'+sph_class+'">', + ' <switch whichChoice="0">', + ' <transform translation="'+x+' '+y+' '+z+'" rotation="0 0 0 0">', + ' <shape class="shapemarker">', + ' <appearance>', + ' <material diffuseColor="'+color+'" transparency="0.0" myColor="'+color+'"></material>', + ' </appearance>', + ' <Sphere DEF="sphere" radius="'+size+'" />', + ' </shape>', + ' </transform>', + ' </switch>', + '</group>' + ].join('\n'); var sphere_element = $(html); - $(this.element).find("scene").append(sphere_element); + $('scene',this.element).append(sphere_element); //var shape = $(sphere_element).find("shape"); //var id_prefix = $(sphere_element).attr("id").substr(0,7); diff --git a/map.html b/map.html index ccc430484c9f2e210d2214e82e9869cce45875f0..0bd6d19a0050ebf5f1923f8d645125b1aacbd206 100644 --- a/map.html +++ b/map.html @@ -3,16 +3,25 @@ <head> <title>Ze Map</title> <meta charset="utf-8"/> - <script type='text/javascript' src='js/jquery/jquery-3.1.1.js'></script> +<!-- build:css css/map.css --> +<!-- bower:css --> +<!-- endbower --> + <link rel='stylesheet' type='text/css' href='js/leaflet/leaflet.css'></link> + <link rel='stylesheet' type='text/css' href='js/map.css'></link> +<!--endbuild--> +<!-- build:js js/map.js --> +<!-- bower:js --> +<script src='bower_components/jquery/dist/jquery.js'></script> +<!-- endbower --> <script type='text/javascript' src='js/leaflet/leaflet-src.js'></script> <script type='text/javascript' src='js/leaflet/leaflet.camera-view-marker-controls.js'></script> <script type='text/javascript' src='js/leaflet/leaflet.camera-view-marker.js'></script> <script type='text/javascript' src='js/leaflet/leaflet.camera-view-marker.measure.js'></script> <script type='text/javascript' src='js/map.js'></script> - <link rel='stylesheet' type='text/css' href='js/leaflet/leaflet.css'></link> - <link rel='stylesheet' type='text/css' href='js/map.css'></link> +<!--endbuild--> </head> <body> <div id="leaflet_map"></div> </body> </html> +ls diff --git a/package.json b/package.json new file mode 100644 index 0000000000000000000000000000000000000000..5f35bb81bd701be065a318ad844df62800f8d7e7 --- /dev/null +++ b/package.json @@ -0,0 +1,42 @@ +{ + "name": "x3domlet", + "version": "1.0.0", + "repository": { + "type": "git", + "url": "https://git.elphel.com/Elphel/x3domlet" + }, + "author": "Oleg Dzhimiev <oleg@elphel.com>", + "license": "GPL-3.0", + "devDependencies": { + "cors": "^2.8.3", + "express": "^4.15.3", + "extend": "^3.0.1", + "gulp": "github:gulpjs/gulp#4.0", + "gulp-bower": "0.0.13", + "gulp-clean-css": "^3.4.1", + "gulp-concat": "^2.6.1", + "gulp-connect": "^5.0.0", + "gulp-cssmin": "^0.2.0", + "gulp-foreach": "^0.1.0", + "gulp-htmlmin": "^3.0.0", + "gulp-rev": "^7.1.2", + "gulp-sourcemaps": "^2.6.0", + "gulp-uglify": "^3.0.0", + "gulp-usemin": "^0.3.28", + "gulp4": "^4.0.1", + "node-php": "0.0.1", + "opn": "^5.0.0", + "q": "^1.5.0", + "shelljs": "^0.7.8", + "wiredep": "^4.0.0", + "gulp-clean": "^0.3.2" + }, + "description": "x3dom + leaflet", + "dependencies": { + }, + "scripts": { + "postinstall": "node scripts/postinstall.js", + "start": "node scripts/postinstall.js && gulp" + }, + "main": "gulpfile.js" +} diff --git a/scripts/postinstall.js b/scripts/postinstall.js new file mode 100755 index 0000000000000000000000000000000000000000..9fec7520244a76e0677639455c78e34d2bca4d16 --- /dev/null +++ b/scripts/postinstall.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node +var shelljs=require('shelljs'); +if (!shelljs.which('php-cgi')) { + console.log('php-cgi not found. Maybe you can install it with:'); + console.log('sudo apt-get install php5-cgi'); + process.exit(1); +} diff --git a/test.html b/test.html index d08ea4a8392c0c2f8f91840dd3cb967e7041bc87..2ab688a86a5871a28c7a9ebba5cde0eed9db3399 100644 --- a/test.html +++ b/test.html @@ -4,7 +4,19 @@ <meta charset="utf-8"/> <title>Scene+Map</title> - <script type='text/javascript' src='js/jquery/jquery-3.1.1.js'></script> + <!-- build:css css/test.css --> + <!-- bower:css --> + <!-- endbower --> + <link rel='stylesheet' type='text/css' href='js/leaflet/leaflet.css'></link> + <link rel='stylesheet' type='text/css' href='js/x3dom/x3dom.css'></link> + + <link rel='stylesheet' type='text/css' href='js/ui.css'></link> + <!-- endbuild --> + + <!-- build:js js/test.js --> + <!-- bower:js --> + <script src='bower_components/jquery/dist/jquery.js'></script> + <!-- endbower --> <script type='text/javascript' src='js/leaflet/leaflet-src.js'></script> <script type='text/javascript' src='js/leaflet/L.extra.js'></script> @@ -12,6 +24,7 @@ <script type='text/javascript' src='js/leaflet/leaflet.camera-view-marker.js'></script> <script type='text/javascript' src='js/leaflet/leaflet.camera-view-marker.measure.js'></script> + <!---script type='text/javascript' src='js/x3dom/x3dom-full.debug.js'></script--> <script type='text/javascript' src='js/x3dom_init.js'></script> <script type='text/javascript' src='js/x3dom_functions.js'></script> @@ -25,11 +38,7 @@ <script type='text/javascript' src='js/ui_align.js'></script> <script type='text/javascript' src='js/util_functions.js'></script> - - <link rel='stylesheet' type='text/css' href='js/leaflet/leaflet.css'></link> - <link rel='stylesheet' type='text/css' href='js/x3dom/x3dom.css'></link> - - <link rel='stylesheet' type='text/css' href='js/ui.css'></link> + <!-- endbuild --> </head> <body>