I'm new to Web WorldWind and forgive me if this is a simple question, but I haven't found a solution in the documentation or elsewhere. I have the following:
<div style="position: absolute; top: 5px; left: 5px;">
<!-- Create a canvas for Web WorldWind. -->
<canvas id="canvasOne" width="1040" height="630">
Your browser does not support HTML5 Canvas.
</canvas>
</div>
<script>
var wwd;
window.addEventListener("load", eventWindowLoaded, false);
// Define the event listener to initialize Web WorldWind.
function eventWindowLoaded() {
// Create a WorldWindow for the canvas.
wwd = new WorldWind.WorldWindow("canvasOne");
// Add some image layers to the WorldWindow's globe
//wwd.addLayer(new WorldWind.BingAerialWithLabelsLayer());.
wwd.addLayer(new WorldWind.BingRoadsLayer());
// Add a compass, a coordinates display and some view controls to the WorldWindow.
wwd.addLayer(new WorldWind.CompassLayer());
wwd.addLayer(new WorldWind.CoordinatesDisplayLayer(wwd));
wwd.addLayer(new WorldWind.ViewControlsLayer(wwd));
}
</script>
When the map is displaying, I'd like to add a toggle to switch between the roads layer and the high resolution aerial window. Any help is appreciated.
Set the boolean enabled property to show/hide an individual layer.
// Create the roads and aerial imagery layers and set the initial visability
var aerialLayer = new WorldWind.BingAerialWithLabelsLayer(),
roadsLayer = new WorldWind.BingRoadsLayer();
aerialLayer.enabled = true;
roadsLayer.enabled = false;
// Add the layers to the WorldWindow (globe)
wwd.addLayer(aerialLayer);
wwd.addLayer(roadsLayer);
// Toggles the display of the roads and aerial imagery layers
function toggleLayers() {
aerialLayer.enabled = !aerialLayer.enabled;
roadsLayer.enabled = !roadsLayer.enabled;
}
FYI: The WorldWindow (wwd) object has a layers array property where you can access the layers.
See: WorldWind.Layer
See also: layers in WorldWind.WorldWindow
Related
I have the following question: How to show panorama images (that can be moved with mouse, or in cardboard googles) that can have a sliders controlling an image blend between two panoramas?
Description: I am trying to make an app, where user can see a panorama image and move around in it (I used PANOLENS for it), and then using sliders be able to make the images blend with each other. The blend is made using SCREEN BLEND function (basically, as the sliders move to one side, some brighter elements from one panorama start to appear on the other panorama - so in a way, two panorama images are displayed at the same time).
I think I kinda figured the way to do it for normal rectangular images - I use p5js library with IMAGE BLEND SCREEN function with 3 sliders - it is in the script called sketch.js:
let DAYLIGHT;
let LAMPS1;
let LAMPS2;
function preload() {
DAYLIGHT = loadImage('../img/OFFICEDL.JPG');
LAMPS1 = loadImage('../img/OFFICEL2.JPG');
LAMPS2 = loadImage('../img/OFFICEL1.JPG');
}
function setup() {
canvas = createCanvas(1200,600).parent("recimage");
DAYLIGHT.resize(1200,600);
LAMPS1.resize(1200,600);
LAMPS2.resize(1200,600);
DLslider = createSlider(0, 255, 0).parent('slidersimage');
DLslider.position(10, 0).parent('slidersimage');
DLslider.style('width', '200px');
L1slider = createSlider(0, 255, 0).parent('slidersimage');
L1slider.position(10, 30).parent('slidersimage');
L1slider.style('width', '200px');
L2slider = createSlider(0, 255, 0).parent('slidersimage');
L2slider.position(10, 60).parent('slidersimage');
L2slider.style('width', '200px');
}
function draw() {
background(0);
blendMode(SCREEN);
const DLvalue = DLslider.value();
const L1value = L1slider.value();
const L2value = L2slider.value();
tint(255, 255-DLvalue);
image(DAYLIGHT,0,0);
tint(255, L1value);
image(LAMPS1,0,0);
tint(255, L2value);
image(LAMPS2,0,0);
blendMode(BLEND);
}
Now for displaying the panoramas for now I have only used a workflow from tutorial to display the panorama, and for that I load three.min.js and panolens.js, and finally in the script main.js I use tell the app to display the panorama picture:
const panoImage = document.querySelector('.pano-image');
const testPano1 = '../img/OFFICEDL.jpg';
const panorama = new PANOLENS.ImagePanorama(testPano1);
const viewer = new PANOLENS.Viewer({
container: panoImage,
});
viewer.add( panorama );
Finally, in my html it looks like this:
<!DOCTYPE html><html><head>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8">
</head>
<body>
<h1> PANORAMA TEST</h1>
<p>
This is the panorama view of the room
</p>
<div class="centering">
<div class="pano-image"> </div>
</div>
<p>
This is the stretched out panorama (equirectangular image view) with adjustable level of lighting
</p>
<div class="centering">
<p id="recimage"></p>
<p id="slidersimage"></p>
</div>
<p>
End text
</p>
<script src="js/p5.js"></script>
<script src="js/sketch.js"></script>
<script src="js/three.min.js"></script>
<script src="js/panolens.min.js"></script>
<script src="js/main.js"></script>
</body></html>
For now, altogether there is a panorama image on the top, and equirectangular version of it on the bottom, which has the sliders controlling it. Is there a way to implement similar control to the panoramic version?
Also, a side question: my sliders do not seem to position themselves relatively to the canvas, but rather to the whole website...anyone has any tips for that?
Any help would be greatly appreciated!
I have a very simple Bing maps program where I want to allow the user to draw one shape on the map, I've got the drawing tools and everything set up however Bing's events don't seem to fire in the correct way -
Drawing started - fires when I change my drawing tool to either a line or a polygon
Drawing Changed - fires when I change my drawing tool to either a line or a polygon
I simply want to clear the existing polygons from the map when I begin to draw a new polygon - however making a call to the getPrimitives function on the drawing manager clears the drawing mode, So then I thought about caching the drawing mode, reading the primitives to delete them and then resetting the drawing mode but then the setDrawingMode method on the drawing Manager calls the drawing started again which triggers the whole process again.
Does anyone know how to overcome this.
Does look odd that the drawing started event is firing when you click the mode. Will have the team look into that.
However, what you are trying todo would have some potential issues. If you clear the drawing manager when the user has started drawing a polygon on the map, that polygon will also be removed from the map as well. What you can do is when finished drawing a polygon, is move it to a separate layer, then you can clear that layer without effecting the drawing manager. If you are only interested in drawing polygons, you don't even need the drawing manager as you can handle this yourself using the drawing tools and a button. For example: http://bingmapsv8samples.azurewebsites.net/#DrawingTools_CreateShape
Here is a code sample that achieves what you are asking using the drawing manager:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script type='text/javascript'>
var map, baseLayer, drawingManager;
function GetMap() {
map = new Microsoft.Maps.Map('#myMap', {
credentials: 'YourBingMapsKey'
});
//Load the DrawingTools module
Microsoft.Maps.loadModule('Microsoft.Maps.DrawingTools', function () {
//Create a base layer to add drawn shapes.
baseLayer = new Microsoft.Maps.Layer();
map.layers.insert(baseLayer);
//Create an instance of the DrawingTools class and bind it to the map.
var tools = new Microsoft.Maps.DrawingTools(map);
//Show the drawing toolbar and enable editting on the map.
tools.showDrawingManager(function (manager) {
drawingManager = manager;
Microsoft.Maps.Events.addHandler(drawingManager, 'drawingEnded', function (e) {
//When use finisihes drawing a shape, removing it from the drawing layer and add it to the base layer.
var shapes = drawingManager.getPrimitives();
if (shapes) {
drawingManager.clear();
baseLayer.add(shapes);
}
});
Microsoft.Maps.Events.addHandler(drawingManager, 'drawingChanging', function (e) {
//When the drawing is changing, clear the base layer.
baseLayer.clear();
});
})
});
}
</script>
<script type='text/javascript' src='https://www.bing.com/api/maps/mapcontrol?callback=GetMap' async defer></script>
</head>
<body>
<div id="myMap" style="position:relative;width:600px;height:400px;"></div>
</body>
</html>
Here is a similar code sample that does this without the drawing manager and a custom button to start drawing a polygon.
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script type='text/javascript'>
var map, baseLayer, tools, currentShape;
function GetMap() {
map = new Microsoft.Maps.Map('#myMap', {
credentials: 'YourBingMapsKey'
});
//Create a base layer to add drawn shapes.
baseLayer = new Microsoft.Maps.Layer();
map.layers.insert(baseLayer);
//Load the DrawingTools module.
Microsoft.Maps.loadModule('Microsoft.Maps.DrawingTools', function () {
//Create an instance of the DrawingTools class and bind it to the map.
tools = new Microsoft.Maps.DrawingTools(map);
Microsoft.Maps.Events.addHandler(tools, 'drawingChanging', function (e) {
//When the drawing is changing, clear the base layer.
baseLayer.clear();
});
//When the user presses 'esc', take the polygon out of edit mode and re-add to base map.
document.getElementById('myMap').onkeypress = function (e) {
if (e.charCode === 27) {
tools.finish(shapeDrawn);
currentShape = null;
}
};
});
}
function drawPolygon() {
//Stop any current drawing.
if (currentShape) {
tools.finish(shapeDrawn);
currentShape = null;
}
//Create a new polygon.
tools.create(Microsoft.Maps.DrawingTools.ShapeType.polygon, function (s) {
currentShape = s;
});
}
function shapeDrawn(s) {
baseLayer.add(s);
}
</script>
<script type='text/javascript' src='https://www.bing.com/api/maps/mapcontrol?callback=GetMap' async defer></script>
</head>
<body>
<div id="myMap" style="position:relative;width:600px;height:400px;"></div><br />
<input type="button" onclick="drawPolygon()" value="Draw Polygon" />
</body>
</html>
Hi everyone (or should I say "anyone [who would read this...]?) :)
I have tried to find the answer for two days but without success (most likely because I am a brand new user). I have on a leaflet map markers organized in a Layergroup so I can manage them with Layercontrol. I would like that when a marker is clicked it triggers an event (in my case the creation of a circle representing a specific distance around this marker). I would like to manage that outside of the individual markers because I want also to set some different options for the radius of the circle according to the distance selected by the user.
Below are different pieces of code showing what I mean :
<!DOCTYPE html>
<head>
<title>Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="https://unpkg.com/leaflet#1.0.2/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.0.2/dist/leaflet.css"/>
<style>
body {
font-family: Helvetica;
margin:0;
}
#map{
position:absolute;
top:0;
bottom:0;
width:100%;}
</style>
</head>
<body>
<div id="map"></div>
<script>
var sites = [
{'loc':[42.2793869135936,9.53257201027757],'title':'TORRA A I CASELLI'},
{'loc':[42.2713622720985,9.50678498185463],'title':'TOUR GIANDINELLI'},
{'loc':[42.641518105666,9.00587322013212],'title':'TOUR DE LOSARI'},];
var map = new L.Map('map');
map.addLayer(new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'));
map.setView([42.5,9.2210706018535],9);
var marks = new L.LayerGroup();
for(i in sites) {
var title = sites[i].title,
loc = sites[i].loc,
markersites = new L.Marker(new L.latLng(loc), {title: title});
markersites.bindPopup('<strong>'+title+'</strong><br>');
marks.addLayer(markersites);
}
marks.addTo(map);
// for now it is all good, the next part is where I fail
marks.on('click',function(){
console.log("Yeah!");
new L.circle(this.getLatLng(), 10000, {color:'red', fillOpacity:0.3}).addTo(map)});
</script>
</body>
</html>
Any help would be much appreciated, thank you for your attention.
Cheers,
Guillaume.
The fact you are using a LayerGroup is not part of your problem.
First, you have to attach a 'click' listener on all your markers. This way, you can draw your circle when the popup is opened. You also must keep a reference to this circle in the javascript popup object.
// keep a reference on the current active circle
var activeCircle = false;
markersites.on('click', function(e) {
// marker clicked is e.target
// remove active circle if any
if(activeCircle) {
map.removeLayer(activeCircle);
}
// draw a 10km circle with the same center as the marker
activeCircle = L.circle(e.target.getLatLng(), { radius: 10000 , color: "#ff0000" }).addTo(map);
});
Example is here: http://plnkr.co/edit/OufPbq07ywEZh1N5VA8Y?p=preview
Since you are binding popups to your markers, a leaflet popup is going to open up in response to click events. However, you can hook into those events by adding your own callbacks, too like:
map.on('popupopen', function (e) {
currentPopup = e.popup; // keep track of current popup
// Do stuff with the popup or inspect it's marker here...
});
There are probably other ways to solve this with the leaflet api which is very flexible. This approach has worked for me in the past.
Also at the time you are creating popups, you can bind additional info if necessary like this:
var content = '<b>'+ something + '</b>: '+ etc;
var popup = L.popup();
popup.setContent(content);
popup.markerId = 'some id';
layer.bindPopup(popup);
The code snippet shown below (HTML5/javascript) loads Microsoft Bing Map (VirtualEarth 6.3), then adds two Shape layers and two sample Pushpins, one per each layer.
QUESTION: What pure javascript function (or solution) to use in order to clear all pushpins from just the 1st layer keeping the other layer intact?
Note: clear layer function should be implemented without deleting the entire layer.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Bing VE Map w/layers</title>
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.3"></script>
<script type="text/javascript">
// VE map
var _map;
// 1st shape layer
var _layer1 ;
// 2nd shape layer
var _layer2;
function MapLoad() {
// load map
_map = new VEMap('Map');
_map.LoadMap();
// center point (Columbus Circle NY)
var _center = new VELatLong(40.7681, -73.9819);
// set center point and initial zoom level
_map.SetCenterAndZoom(_center, 12);
// set Map style
_map.SetMapStyle(VEMapStyle.Shaded);
// add 1st shape layer1 to Map obj
_layer1 = new VEShapeLayer()
_map.AddShapeLayer(_layer1);
// add 2nd shape layer2 to Map obj
_layer2 = new VEShapeLayer()
_map.AddShapeLayer(_layer2);
// add pushpin to layer1
var _pushpin1 = new VEShape(VEShapeType.Pushpin, _center);
_layer1.AddShape(_pushpin1);
// add pushpin (Apple Store on 5th) to layer2
var _pushpin2 = new VEShape(VEShapeType.Pushpin, new VELatLong(40.7639, -73.9725));
_layer2.AddShape(_pushpin2);
// QUESTION: HOW TO CLEAR ALL SHAPES FROM LAYER 1, (BUT NOT DELETING THE ENTIRE LAYER)?
}
</script>
</head>
<body onload="MapLoad();">
<div id="Map" style="position:absolute; top:100px; height:90%; width:100%;"></div>
</body>
</html>
You could use the dedicated method DeleteAllShapes() of the VEShapeLayer class, see the MSDN:
https://msdn.microsoft.com/en-us/library/bb412473.aspx
See the example:
// Delete all shapes within the layer at the selected index.
function DeleteAllShapes()
{
layer = map.GetShapeLayerByIndex(selIndex);
layer.DeleteAllShapes();
IndexChanged(selIndex);
}
Also, I would recommend to use AJAX v7.0 instead of v6.3 since it's now deprecated and due to be out of support on November 30, 2016.
I'm working on a simple diagram editor using KineticJS. I would like to use two separate canvases for the palette area (that contains a number of Kinetic.Groups that represent the different nodes of the network I might create), and the diagramming area where I can add nodes from the palette via drag and drop, and then add connections between the various nodes as specific anchor points. I'm having trouble figuring out the drag and drop process from the palette canvas of (stationary) Kinetic.Groups over to the other canvas containing diagramming area. I'm guessing that I need to fire off of the dragstart event for the palette objects (although I don't want these themselves to be draggable), and then do something like create an opague copy of the palette object that can be dragged around, and finally dropped into the diagramming area (with full opacity).
Can groups be dragged outside of a the staging canvases boundaries? Maybe I need to generate an image when I start to drag from the palette, drag that image over, and then create another group when dropping into the diagramming area.
Does any one know of any examples that might point me in the right direction, or who can offer some insight (even code) into the required process. I've searched the KineticJS examples but can't quite find enough to get me going.
Here’s one way to drag nodes from a source palette into a destination group:
A Fiddle: http://jsfiddle.net/m1erickson/xtVyL/
Network nodes are represented by small icons (which are really small kinetic image objects).
The user can drag any icon from the source palette to any destination group.
The groups are just defined areas on the canvas, but could be Kinetc.Groups for more flexibility.
During the dragend event, a new duplicate copy of the dragged icon is created in the destination group.
After the dragend event is complete, the original palette icon is automatically moved from
The newly created duplicate icon can be dragged around the destination group (but not outside that group).
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/xtVyL/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.5.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
// image loader
var imageURLs=[];
var imagesOK=0;
var imgs=[];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/tempPC.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/tempServer.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/tempRouter.png");
loadAllImages();
function loadAllImages(callback){
for (var i = 0; i < imageURLs.length; i++) {
var img = new Image();
imgs.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK==imageURLs.length ) {
start();
}
};
img.src = imageURLs[i];
}
}
// top icon positions
var nextIconX=20;
var nextIconY=20;
// define groups
var groups=[];
groups.push({x:0,y:100,w:175,h:250,fill:"skyblue"});
groups.push({x:175,y:100,w:175,h:250,fill:"cornsilk"});
// add boundary info to each group
// draw colored rect to show group area
for(var i=0;i<groups.length;i++){
var g=groups[i];
g.left=g.x;
g.right=g.x+g.w;
g.top=g.y;
g.bottom=g.y+g.h;
var rect=new Kinetic.Rect({
x:g.x,
y:g.y,
width:g.w,
height:g.h,
fill:g.fill,
stroke:"gray"
});
layer.add(rect);
}
// hittest for each group
function groupHit(x,y){
for(var i=0;i<groups.length;i++){
var g=groups[i];
if(x>g.left && x<g.right && y>g.top && y<g.bottom){return(i);}
}
return(-1);
}
function start(){
makePaletteIcon(imgs[0]);
makePaletteIcon(imgs[1]);
makePaletteIcon(imgs[2]);
layer.draw();
}
function makePaletteIcon(img){
// make an icon that stays in the pallette tray
var fixedIcon=newImage(nextIconX,nextIconY,img,false);
layer.add(fixedIcon);
// make an icon that is dragged from the tray to a group
var dragIcon=makeDraggableIcon(nextIconX,nextIconY,img);
layer.add(dragIcon);
// calc the next icon position
nextIconX+=(img.width+20);
}
function makeDraggableIcon(x,y,img){
var i=newImage(x,y,img,true);
//
i.trayX=x;
i.trayY=y;
//
i.setOpacity(0.50);
i.on("dragend",function(){
var x=this.getX();
var y=this.getY();
// if this pallette icon was not dropped in a group
// put the icon back in the tray and return
var hit=groupHit(x,y);
if(hit==-1){
this.setPosition(this.trayX,this.trayY);
return;
}
// add a copy of this icon to the drop group
var component=newImage(x,y,this.getImage(),true);
// set drag limits
var group=groups[hit];
component.maxDragLeft=group.left;
component.maxDragRight=group.right;
component.maxDragTop=group.top;
component.maxDragBottom=group.bottom;
// limit component dragging to inside the assigned group
component.setDragBoundFunc(function(pos) {
var xx=pos.x;
var yy=pos.y;
var w=this.getWidth();
var h=this.getHeight();
if(pos.x<this.maxDragLeft){xx=this.maxDragLeft;}
if(pos.x+w>this.maxDragRight){xx=this.maxDragRight-w;}
if(pos.y<this.maxDragTop){yy=this.maxDragTop;}
if(pos.y+h>this.maxDragBottom){yy=this.maxDragBottom-h;}
return{ x:xx, y:yy };
});
layer.add(component);
// move the dragIcon back into the pallette tray
this.setPosition(this.trayX,this.trayY);
layer.draw();
});
return(i);
}
// make a new Kinetic.Image
function newImage(x,y,img,isDraggable){
var i=new Kinetic.Image({
image:img,
x: x,
y: y,
width: img.width,
height: img.height,
draggable:isDraggable
});
return(i);
}
}); // end $(function(){});
</script>
</head>
<body>
<p>Drag any icon from top into blue or yellow group</p>
<div id="container"></div>
</body>
</html>