Merge pull request #138 from vizicities/0.2.0-layers-ui

Adding Layers UI
0.2
Robin Hawkes 2015-03-08 18:44:03 +00:00
commit 6e94442b1c
36 zmienionych plików z 438 dodań i 49 usunięć

1
.gitignore vendored
Wyświetl plik

@ -1,5 +1,6 @@
### ViziCities ###
bower_components
src/UI/*.js
# Created by https://www.gitignore.io

Wyświetl plik

@ -5,11 +5,19 @@
// - https://github.com/cvisco/grunt-smash
// TODO: Add code style tests
// - https://github.com/jscs-dev/node-jscs
// TODO: Make React compilation dynamic
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
react: {
vizicities: {
files: {
"src/UI/LayersUI.js": "src/UI/LayersUI.jsx"
}
}
},
uglify: {
vizicities: {
options: {
@ -38,7 +46,7 @@ module.exports = function(grunt) {
},
concat: {
vizicities: {
src: ["src/Vizi.js", "src/Core/*.js", "src/Geo/CRS.js", "src/WebGL/*.js", "src/Controls/Controls.js", "src/**/*.js"],
src: ["src/Vizi.js", "src/Core/*.js", "src/Geo/CRS.js", "src/WebGL/*.js", "src/Controls/Controls.js", "src/UI/*.js", "src/**/*.js"],
dest: "build/vizi.js"
},
bower: {
@ -47,11 +55,11 @@ module.exports = function(grunt) {
banner: "/*! ViziCities - v<%= pkg.version %> - " +
"<%= grunt.template.today('yyyy-mm-dd') %> */\n"
},
src: ["bower_components/**/*min.js", "bower_components/proj4/dist/proj4-src.js", "bower_components/wildemitter/wildemitter-bare.js", "build/vizi.js"],
src: ["bower_components/**/*min.js", "bower_components/proj4/dist/proj4-src.js", "bower_components/wildemitter/wildemitter-bare.js", "build/vizi.js", "!bower_components/react/react-with-addons.min.js"],
dest: "build/vizi.js"
},
bower_min: {
src: ["bower_components/**/*min.js", "bower_components/proj4/dist/proj4.js", "bower_components/wildemitter/wildemitter-bare.js", "build/vizi.min.js"],
src: ["bower_components/**/*min.js", "bower_components/proj4/dist/proj4.js", "bower_components/wildemitter/wildemitter-bare.js", "build/vizi.min.js", "!bower_components/react/react-with-addons.min.js"],
dest: "build/vizi.min.js"
},
vizicities_worker: {
@ -119,6 +127,7 @@ module.exports = function(grunt) {
grunt.loadNpmTasks("grunt-mocha-slimer");
grunt.loadNpmTasks("grunt-contrib-concat");
grunt.loadNpmTasks("grunt-contrib-uglify");
grunt.loadNpmTasks("grunt-react");
// Default task(s).
grunt.registerTask("default", ["test"]);
@ -129,6 +138,6 @@ module.exports = function(grunt) {
grunt.registerTask("test", ["jshint", "mocha_slimer"]);
// Build
grunt.registerTask("build", ["concat:vizicities", "uglify:vizicities", "concat:bower", "concat:bower_min"]);
grunt.registerTask("build_worker", ["concat:vizicities_worker", "uglify:vizicities_worker", "concat:bower_worker", "concat:bower_worker_min"]);
grunt.registerTask("build", ["react:vizicities", "concat:vizicities", "uglify:vizicities", "concat:bower", "concat:bower_min"]);
grunt.registerTask("build_worker", ["react", "concat:vizicities_worker", "uglify:vizicities_worker", "concat:bower_worker", "concat:bower_worker_min"]);
};

Wyświetl plik

@ -42,5 +42,8 @@
"proj4": "~2.3.3",
"d3": "~3.4.13",
"operative": "https://github.com/padolsey/operative/archive/0-4-rc1.zip"
},
"dependencies": {
"react": "~0.12.2"
}
}

Wyświetl plik

@ -1,4 +1,4 @@
/*! ViziCities - v0.2.0 - 2015-01-23 */
/*! ViziCities - v0.2.0 - 2015-03-03 */
// Underscore.js 1.7.0
// http://underscorejs.org
// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -19,4 +19,54 @@
.vizicities-attribution a:hover {
color: #2bb2ed;
text-decoration: underline;
}
}
.vizicities-ui {
height: 100%;
position: absolute;
pointer-events: none;
z-index: 9998;
width: 100%;
}
.vizicities-ui .vizicities-layers-ui {
background: #fff;
border-radius: 3px;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
font-family: Arial, Verdana, sans-serif;
font-size: 16px;
pointer-events: auto;
position: absolute;
right: 20px;
top: 20px;
width: 200px;
}
.vizicities-ui .vizicities-layers-ui header {
background: #222;
border-radius: 3px 3px 0 0;
color: #fff;
}
.vizicities-ui .vizicities-layers-ui h2 {
font-size: 16px;
font-weight: normal;
margin: 0;
padding: 12px 15px 10px;
text-transform: uppercase;
}
.vizicities-ui .vizicities-layers-ui ul {
list-style: none;
margin: 0;
padding: 10px 0 10px;
}
.vizicities-ui .vizicities-layers-ui li {
margin: 0;
padding: 5px 15px;
}
.vizicities-ui .vizicities-layers-ui li input {
vertical-align: text-bottom;
}

File diff suppressed because one or more lines are too long

26
build/vizi.min.js vendored

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -1,5 +1,6 @@
var world = new VIZI.World({
viewport: document.querySelector("#vizicities-viewport")
viewport: document.querySelector("#vizicities-viewport"),
layersUI: true
// center: new VIZI.LatLon(40.01000594412381, -105.2727379358738) // Collada
});

Wyświetl plik

@ -36,6 +36,7 @@
"grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-uglify": "^0.6.0",
"grunt-mocha-slimer": "0.0.2",
"grunt-react": "^0.10.0",
"mocha": "^1.21.5",
"sinon": "^1.10.3",
"sinon-chai": "^2.6.0"

Wyświetl plik

@ -25,6 +25,8 @@
// [{name: "actionName", arguments: ["argName1", "argName2"]}, ...]
self.actions = [];
self.name = "";
// TODO: How do you ensure the layer abides by fustrum culling when inner objects are referencing the world coordinate space
// self.layer = new VIZI.Layer();
};

Wyświetl plik

@ -26,7 +26,8 @@
_.defaults(self.options, {
materialType: "MeshLambertMaterial",
materialOptions: {},
workerURL: "vizi-worker.min.js"
workerURL: "vizi-worker.min.js",
name: "Building tiles"
});
_.defaults(self.options.materialOptions, {
@ -46,6 +47,8 @@
{name: "outputBuildingTile", arguments: ["buildings", "tile"]}
];
self.name = self.options.name;
// Grids
// {16: {
// grid: VIZI.BlueprintHelperTileGrid,

Wyświetl plik

@ -21,7 +21,8 @@
_.defaults(self.options, {
colourRange: ["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"],
layer: 10
layer: 10,
name: "Choropleth"
});
// Triggers and actions reference
@ -33,6 +34,8 @@
{name: "outputChoropleth", arguments: ["data"]}
];
self.name = self.options.name;
self.world;
};

Wyświetl plik

@ -18,7 +18,9 @@
VIZI.BlueprintOutput.call(self, options);
_.defaults(self.options, {});
_.defaults(self.options, {
name: "Collada"
});
// Triggers and actions reference
self.triggers = [
@ -29,6 +31,8 @@
{name: "outputCollada", arguments: ["collada"]}
];
self.name = self.options.name;
self.world;
};

Wyświetl plik

@ -16,7 +16,9 @@
VIZI.BlueprintOutput.call(self, options);
_.defaults(self.options, {});
_.defaults(self.options, {
name: "Debug lines"
});
// Triggers and actions reference
self.triggers = [
@ -27,6 +29,8 @@
{name: "outputLines", arguments: ["data"]}
];
self.name = self.options.name;
self.world;
};

Wyświetl plik

@ -16,7 +16,9 @@
VIZI.BlueprintOutput.call(self, options);
_.defaults(self.options, {});
_.defaults(self.options, {
name: "Debug points"
});
// Triggers and actions reference
self.triggers = [
@ -27,6 +29,8 @@
{name: "outputPoints", arguments: ["data"]}
];
self.name = self.options.name;
self.world;
};

Wyświetl plik

@ -25,7 +25,8 @@
_.defaults(self.options, {
materialType: "MeshBasicMaterial",
materialOptions: {}
materialOptions: {},
name: "Image tiles"
});
_.defaults(self.options.materialOptions, {
@ -44,6 +45,8 @@
{name: "outputImageTile", arguments: ["image", "tile"]}
];
self.name = self.options.name;
// Grids
// {16: {
// grid: VIZI.BlueprintHelperTileGrid,

Wyświetl plik

@ -13,7 +13,7 @@
VIZI.Controls.call(self, camera, options);
self.controls = new THREE.FirstPersonControls(camera.camera, self.options.viewport);
self.controls = new THREE.FirstPersonControls(camera.camera, self.options.viewport.querySelector("canvas"));
self.controls.movementSpeed = 750;
self.controls.lookSpeed = 0.075;

Wyświetl plik

@ -14,7 +14,7 @@
VIZI.Controls.call(self, camera, options);
self.controls = new THREE.MapControls(camera.camera, self.options.viewport);
self.controls = new THREE.MapControls(camera.camera, self.options.viewport.querySelector("canvas"));
self.controls.maxPolarAngle = 1.5533430342749535; // 89 degrees
self.controls.addEventListener("start", function(event) {

Wyświetl plik

@ -14,7 +14,7 @@
VIZI.Controls.call(self, camera, options);
self.controls = new THREE.OrbitControls(camera.camera, self.options.viewport);
self.controls = new THREE.OrbitControls(camera.camera, self.options.viewport.querySelector("canvas"));
self.controls.addEventListener("start", function(event) {
self.onStart();

Wyświetl plik

@ -19,7 +19,8 @@
crs: VIZI.CRS.EPSG3857,
center: new VIZI.LatLon(51.50358, -0.01924),
zoom: 16,
suppressRenderer: false // Set true for tests
suppressRenderer: false, // Set true for tests
layersUI: true
});
if (!self.options.viewport) {
@ -36,6 +37,19 @@
self.switchboards = [];
self.layers = [];
// Add UI container
// TODO: Move into a separate UI class
var uiContainer = document.createElement("div");
// Styling is adding via vizicities.css
uiContainer.classList.add("vizicities-ui");
self.options.viewport.appendChild(uiContainer);
// Set up layer UI
if (self.options.layersUI) {
self.layersUI = new VIZI.LayersUI(self.layers);
}
// TODO: Ability to override this with a scene passed into the options
// TODO: Pass-through options that tweak scene (antialias, etc)
self.scene = new VIZI.Scene({
@ -114,6 +128,11 @@
self.layers.push(layer);
self.scene.add(layer.object);
// Update layers UI
if (self.layersUI) {
self.layersUI.onChange();
}
};
VIZI.World.prototype.addSwitchboard = function(switchboard) {

Wyświetl plik

@ -0,0 +1,93 @@
/* globals window, _, React, VIZI */
/**
* Layers UI class
* @author Robin Hawkes - vizicities.com
*/
// TODO: Sort out scoping issues
// TODO: Work out a neater structure for defining the render method
(function() {
"use strict";
VIZI.LayersUI = function(layers) {
var self = this;
var scope = self;
self.layers = layers;
self.layerControl = React.createClass({
render: function() {
var self = this;
// TODO: De-dupe checkbox setup
var layers = self.props.layers.map(function(layer) {
var visibilityButton;
if (layer.hidden) {
visibilityButton = <input type="checkbox" onClick={self.props.onShow.bind(scope, layer.object.id)}></input>
} else {
visibilityButton = <input type="checkbox" checked onClick={self.props.onHide.bind(scope, layer.object.id)}></input>
}
return (
<li key={layer.object.id}>
{visibilityButton} {layer.name}
</li>
);
});
return (
<section className="vizicities-layers-ui">
<header>
<h2>Layers</h2>
</header>
<ul>
{layers}
</ul>
</section>
);
}
});
self.onChange();
};
VIZI.LayersUI.prototype.onHideLayer = function(id) {
var self = this;
var layer = _.find(self.layers, function (layer) {
return layer.object.id === id;
});
if (layer) {
layer.hide();
layer.hidden = true;
}
self.onChange();
};
VIZI.LayersUI.prototype.onShowLayer = function(id) {
var self = this;
var layer = _.find(self.layers, function (layer) {
return layer.object.id === id;
});
if (layer) {
layer.show();
layer.hidden = false;
}
self.onChange();
};
VIZI.LayersUI.prototype.onChange = function() {
var self = this;
var LayerControl = self.layerControl;
React.render(<LayerControl layers={self.layers} onHide={self.onHideLayer} onShow={self.onShowLayer} />, document.querySelector(".vizicities-ui"));
};
})();

Wyświetl plik

@ -40,6 +40,17 @@
self.object.remove(object);
};
// UI handlers
VIZI.Layer.prototype.hide = function() {
var self = this;
self.object.visible = false;
};
VIZI.Layer.prototype.show = function() {
var self = this;
self.object.visible = true;
};
VIZI.Layer.prototype.applyVertexColors = function( geom, colour ) {
geom.faces.forEach( function( f ) {
var n = ( f instanceof THREE.Face3 ) ? 3 : 4;

Wyświetl plik

@ -75,7 +75,8 @@
};
} else {
renderer = new THREE.WebGLRenderer({
antialias: self.options.antialias
antialias: self.options.antialias,
domElement: document.createElement("canvas")
});
}

Wyświetl plik

@ -4,7 +4,7 @@ describe("VIZI.BlueprintHelperTileGrid", function() {
before(function() {
world = new VIZI.World({
viewport: document.createElement("div"),
viewport: document.body,
camera: new VIZI.Camera({
aspect: 1024 / 768
}),

Wyświetl plik

@ -6,7 +6,7 @@ describe("VIZI.BlueprintOutputBuildingTiles", function() {
before(function() {
world = new VIZI.World({
viewport: document.createElement("div"),
viewport: document.body,
camera: new VIZI.Camera({
aspect: 1024 / 768
}),

Wyświetl plik

@ -6,7 +6,7 @@ describe("VIZI.BlueprintOutputChoropleth", function() {
before(function() {
world = new VIZI.World({
viewport: document.createElement("div"),
viewport: document.body,
camera: new VIZI.Camera({
aspect: 1024 / 768
}),

Wyświetl plik

@ -6,7 +6,7 @@ describe("VIZI.BlueprintOutputCollada", function() {
before(function() {
world = new VIZI.World({
viewport: document.createElement("div"),
viewport: document.body,
camera: new VIZI.Camera({
aspect: 1024 / 768
}),

Wyświetl plik

@ -6,7 +6,7 @@ describe("VIZI.BlueprintOutputDebugLines", function() {
before(function() {
world = new VIZI.World({
viewport: document.createElement("div"),
viewport: document.body,
camera: new VIZI.Camera({
aspect: 1024 / 768
}),

Wyświetl plik

@ -6,7 +6,7 @@ describe("VIZI.BlueprintOutputDebugPoints", function() {
before(function() {
world = new VIZI.World({
viewport: document.createElement("div"),
viewport: document.body,
camera: new VIZI.Camera({
aspect: 1024 / 768
}),

Wyświetl plik

@ -6,7 +6,7 @@ describe("VIZI.BlueprintOutputImageTiles", function() {
before(function() {
world = new VIZI.World({
viewport: document.createElement("div"),
viewport: document.body,
camera: new VIZI.Camera({
aspect: 1024 / 768
}),

Wyświetl plik

@ -5,7 +5,7 @@ describe("VIZI.BlueprintSwitchboard", function() {
before(function() {
world = new VIZI.World({
viewport: document.createElement("div"),
viewport: document.body,
camera: new VIZI.Camera({
aspect: 1024 / 768
}),

Wyświetl plik

@ -4,8 +4,11 @@ describe("VIZI.ControlsFirstPerson", function() {
// TODO: Use VIZI.Camera
before(function() {
var fakeViewport = document.body;
fakeViewport.appendChild(document.createElement("canvas"));
camera = new VIZI.Camera({aspect: 1024 / 768})
controls = new VIZI.ControlsFirstPerson(camera);
controls = new VIZI.ControlsFirstPerson(camera, {viewport: fakeViewport});
});
it("exists in VIZI namespace", function() {

Wyświetl plik

@ -4,8 +4,11 @@ describe("VIZI.ControlsMap", function() {
// TODO: Use VIZI.Camera
before(function() {
var fakeViewport = document.body;
fakeViewport.appendChild(document.createElement("canvas"));
camera = new VIZI.Camera({aspect: 1024 / 768})
controls = new VIZI.ControlsMap(camera);
controls = new VIZI.ControlsMap(camera, {viewport: fakeViewport});
});
it("exists in VIZI namespace", function() {

Wyświetl plik

@ -4,8 +4,11 @@ describe("VIZI.ControlsOrbit", function() {
// TODO: Use VIZI.Camera
before(function() {
var fakeViewport = document.body;
fakeViewport.appendChild(document.createElement("canvas"));
camera = new VIZI.Camera({aspect: 1024 / 768})
controls = new VIZI.ControlsOrbit(camera);
controls = new VIZI.ControlsOrbit(camera, {viewport: fakeViewport});
});
it("exists in VIZI namespace", function() {

Wyświetl plik

@ -3,7 +3,7 @@ describe("VIZI.World", function() {
var viewport;
before(function() {
viewport = document.createElement("div");
viewport = document.body;
world = new VIZI.World({
viewport: viewport,
camera: new VIZI.Camera({