i'm trying to build something like this:
But the difference is that i have a background image 4096x1024 and i wanted to look like it's some kind of VR look, that the center is a bit far away from the screen and the edges are a bit stretched and closer
I managed to use aframes and set my image to the background of a <a-sky> tag, so it warps my image in a sphere and the view or camera, in the center of the sphere. I get the right type of view that i want, the problem is that i think there are lighter solutions for this.
I also want to put text and i would like it to act the same way the image acts.
Thats what i archived with aframes : Gif on Imgur
I don't want to move around the scene/screen ( with AWDS), just to move the screen horizontal because i will have elements that the user needs to move the screen to see them, just like on the gif and on common carrossel.
Define "lighter". A-Frame is built on WebVR and three.js, so if you don't want A-Frame dependency, maybe you can build the panorama yourself using three.js. It actually already has an example on how to do so:
https://threejs.org/examples/webgl_panorama_equirectangular.html
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - equirectangular panorama</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
background-color: #000000;
margin: 0px;
overflow: hidden;
}
#info {
position: absolute;
top: 0px; width: 100%;
color: #ffffff;
padding: 5px;
font-family:Monospace;
font-size:13px;
font-weight: bold;
text-align:center;
}
a {
color: #ffffff;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
three.js webgl - equirectangular panorama demo. photo by Jón Ragnarsson.<br />
drag equirectangular texture into the page.
</div>
<script>
var camera, scene, renderer;
var isUserInteracting = false,
onMouseDownMouseX = 0, onMouseDownMouseY = 0,
lon = 0, onMouseDownLon = 0,
lat = 0, onMouseDownLat = 0,
phi = 0, theta = 0;
init();
animate();
function init() {
var container, mesh;
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1100 );
camera.target = new THREE.Vector3( 0, 0, 0 );
scene = new THREE.Scene();
var geometry = new THREE.SphereBufferGeometry( 500, 60, 40 );
// invert the geometry on the x-axis so that all of the faces point inward
geometry.scale( - 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( {
map: new THREE.TextureLoader().load( 'https://farm4.staticflickr.com/3289/2294472375_24a3b8ef46_o.jpg' )
} );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'wheel', onDocumentMouseWheel, false );
//
document.addEventListener( 'dragover', function ( event ) {
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
}, false );
document.addEventListener( 'dragenter', function ( event ) {
document.body.style.opacity = 0.5;
}, false );
document.addEventListener( 'dragleave', function ( event ) {
document.body.style.opacity = 1;
}, false );
document.addEventListener( 'drop', function ( event ) {
event.preventDefault();
var reader = new FileReader();
reader.addEventListener( 'load', function ( event ) {
material.map.image.src = event.target.result;
material.map.needsUpdate = true;
}, false );
reader.readAsDataURL( event.dataTransfer.files[ 0 ] );
document.body.style.opacity = 1;
}, false );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseDown( event ) {
event.preventDefault();
isUserInteracting = true;
onMouseDownMouseX = event.clientX;
onMouseDownMouseY = event.clientY;
onMouseDownLon = lon;
onMouseDownLat = lat;
}
function onDocumentMouseMove( event ) {
if ( isUserInteracting === true ) {
lon = ( onMouseDownMouseX - event.clientX ) * 0.1 + onMouseDownLon;
lat = ( event.clientY - onMouseDownMouseY ) * 0.1 + onMouseDownLat;
}
}
function onDocumentMouseUp( event ) {
isUserInteracting = false;
}
function onDocumentMouseWheel( event ) {
var fov = camera.fov + event.deltaY * 0.05;
camera.fov = THREE.Math.clamp( fov, 10, 75 );
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame( animate );
update();
}
function update() {
if ( isUserInteracting === false ) {
lon += 0.1;
}
lat = Math.max( - 85, Math.min( 85, lat ) );
phi = THREE.Math.degToRad( 90 - lat );
theta = THREE.Math.degToRad( lon );
camera.target.x = 500 * Math.sin( phi ) * Math.cos( theta );
//camera.target.y = 500 * Math.cos( phi ); // comment this to disable Y axis
camera.target.z = 500 * Math.sin( phi ) * Math.sin( theta );
camera.lookAt( camera.target );
/*
// distortion
camera.position.copy( camera.target ).negate();
*/
renderer.render( scene, camera );
}
</script>
</body>
</html>
Related
I want to render the map-marker-exclamation icon from the FontAwsome library above a three.js cube, but the icon is not rendered properly as you can see below!
Can you please tell me how can I render a FontAwsome Icon on three.js? thanks in advance.
var camera, scene, renderer;
init();
animate();
/**
* draw cube
**/
function drawCube(pos, scene) {
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
material.transparent = true;
material.opacity = 0.2;
const cube = new THREE.Mesh( geometry, material );
const el = document.createElement('div')
el.innerHTML = 'Hi <i class="fa-solid fa-user"</i>'
const objectCSS = new THREE.CSS2DObject(el)
objectCSS.position.set(pos.x, pos.y+1, pos.z)
cube.add(objectCSS);
scene.add(cube);
}
/**
Create the scene, camera, renderer
*/
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0x21252d);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.x = 1;
camera.position.y = 4;
camera.position.z = 5;
scene.add(camera);
labelRenderer = new THREE.CSS2DRenderer();
labelRenderer.setSize( window.innerWidth, window.innerHeight );
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = '0px';
document.body.appendChild( labelRenderer.domElement );
controls = new THREE.OrbitControls(camera, labelRenderer.domElement);
const cube_pos = new THREE.Vector3(1, 0, 2);
drawCube(cube_pos, scene);
window.addEventListener('resize', onWindowResize);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
labelRenderer.render( scene, camera );
}
<script src="https://cdn.jsdelivr.net/npm/three#0.122.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.122.0/examples/js/controls/OrbitControls.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.122.0/examples/js/renderers/CSS2DRenderer.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css">
The reason you're not seeing the icon is that you're importing your font-awesome CSS file as a <script>.
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css"></script>
But it's not a script, it's a stylesheet, and it needs to be imported as such:
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css">
Unable to Draw a curved polyline using Here Maps JS API.
Trying to add the logic based on my previous findings.
It throws an error "Uncaught TypeError: arc.GreatCircle is not a constructor"
Any Suggestions on how to fix this ?
My Earlier Querstion
Here is my working JSFiddle which is trying to draw a curve to multiple spots.
//Step 1: initialize communication with the platform
// In your own code, replace variable window.apikey with your own apikey
var platform = new H.service.Platform({
apikey: window.apikey
});
var defaultLayers = platform.createDefaultLayers();
//Step 2: initialize a map - this map is centered over Europe
var map = new H.Map(document.getElementById('map'),
defaultLayers.vector.normal.map,{
center: {lat:52, lng:5},
zoom: 5,
pixelRatio: window.devicePixelRatio || 1
});
// add a resize listener to make sure that the map occupies the whole container
window.addEventListener('resize', () => map.getViewPort().resize());
//Step 3: make the map interactive
// MapEvents enables the event system
// Behavior implements default interactions for pan/zoom (also on mobile touch environments)
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
// Create the default UI components
var ui = H.ui.UI.createDefault(map, defaultLayers);
window.addEventListener('resize', function() { map.getViewPort().resize(); });
var npoints = 100,
offset = 20;
// Now use the map as required...
//addPolylineToMap(map);
// Berlin -> Chicago0
add([52.51607,13.37699],[41.88425,-87.63245], { style: { strokeColor : "#00FF00", lineWidth : 5, lineDash: [3], lineHeadCap: "arrow-head", lineTailCap: "arrow-tail"} });
// Tokyo -> san Francisco
add([35.68019,139.81194],[37.77712,-122.41964], {style: { strokeColor: "rgba(0,0,255,0.7)", lineWidth: 15, lineDash: [1], lineHeadCap: "arrow-head", lineTailCap: "arrow-tail"} });
// Berlin -> Melbourne
add([52.51607,13.37699],[-37.81753,144.96715], { style: { strokeColor : "rgba(255,0,255,0.7)", lineWidth : 5, lineDash: [3], lineHeadCap: "arrow-head", lineTailCap: "arrow-tail"} });
// Berlin -> Paris -> Paris -> London
add([52.51607,13.37699],[48.85721, 2.34144], { style: { strokeColor : "rgba(0,255,0,0.7)", lineWidth : 5, lineDash: [3], lineHeadCap: "arrow-head", lineTailCap: "arrow-tail"} });
add([48.85721, 2.34144],[51.50643,-0.12721], { style: { strokeColor : "rgba(255,255,0,0.7)", lineWidth : 5, lineDash: [3], lineHeadCap: "arrow-head", lineTailCap: "arrow-tail"} });
function add(s,e,options) {
var arc = {};
arc.Coord = Coord;
arc.Arc = Arc;
arc.GreatCircle = GreatCircle;
var start_ll = new H.geo.Point(s[0],s[1]),
end_ll = new H.geo.Point(e[0],e[1]),
start_coord = {x: start_ll.lng, y:start_ll.lat},
end_coord = {x:end_ll.lng, y:end_ll.lat};
description = ''+s[0]+','+s[1]+'=>'+e[0]+','+e[1]+'',
gc0 = new arc.GreatCircle(start_coord,end_coord, {'name': 'line', 'color':'#ff7200','description':description}),
line0 = gc0.Arc(npoints,{offset:offset}),
strip = line0.strip();
map.addObject(new H.map.Polyline(strip, options));
}
var D2R = Math.PI / 180;
var R2D = 180 / Math.PI;
var Coord = function(lon, lat) {
this.lon = lon;
this.lat = lat;
this.x = D2R * lon;
this.y = D2R * lat;
};
Coord.prototype.view = function() {
return String(this.lon).slice(0, 4) + ',' + String(this.lat).slice(0, 4);
};
Coord.prototype.antipode = function() {
var anti_lat = -1 * this.lat;
var anti_lon = (this.lon < 0) ? 180 + this.lon : (180 - this.lon) * -1;
return new Coord(anti_lon, anti_lat);
};
var LineString = function() {
this.coords = [];
this.length = 0;
};
LineString.prototype.move_to = function(coord) {
this.length++;
this.coords.push(coord);
};
var Arc = function(properties) {
this.properties = properties || {};
this.geometries = [];
};
Arc.prototype.json = function() {
if (this.geometries.length <= 0) {
return { 'geometry': { 'type': 'LineString', 'coordinates': null }, 'type': 'Feature', 'properties': this.properties };
} else if (this.geometries.length == 1) {
return { 'geometry': { 'type': 'LineString', 'coordinates': this.geometries[0].coords }, 'type': 'Feature', 'properties': this.properties };
} else {
var multiline = [];
for (var i = 0; i < this.geometries.length; i++) {
multiline.push(this.geometries[i].coords);
}
return { 'geometry': { 'type': 'MultiLineString', 'coordinates': multiline }, 'type': 'Feature', 'properties': this.properties };
}
};
Arc.prototype.strip = function() {
var s = H.geo.Strip ? new H.geo.Strip() : new H.geo.LineString();
for (var i = 0; i < this.geometries.length; i++) {
if (this.geometries[i].coords.lenght !== 0) {
var coords = this.geometries[i].coords;
for (var j = 0; j < coords.length; j++) {
var p = new H.geo.Point(coords[j][1], coords[j][0]);
s.pushPoint(p);
}
}
}
return s;
}
var GreatCircle = function(start, end, properties) {
if (!start || start.x === undefined || start.y === undefined) {
throw new Error("GreatCircle constructor expects two args: start and end objects with x and y properties");
}
if (!end || end.x === undefined || end.y === undefined) {
throw new Error("GreatCircle constructor expects two args: start and end objects with x and y properties");
}
this.start = new Coord(start.x, start.y);
this.end = new Coord(end.x, end.y);
this.properties = properties || {};
var w = this.start.x - this.end.x;
var h = this.start.y - this.end.y;
var z = Math.pow(Math.sin(h / 2.0), 2) + Math.cos(this.start.y) * Math.cos(this.end.y) * Math.pow(Math.sin(w / 2.0), 2);
this.g = 2.0 * Math.asin(Math.sqrt(z));
if (this.g == Math.PI) {
throw new Error('it appears ' + start.view() + ' and ' + end.view() + " are 'antipodal', e.g diametrically opposite, thus there is no single route but rather infinite");
} else if (isNaN(this.g)) {
throw new Error('could not calculate great circle between ' + start + ' and ' + end);
}
};
#map {
width: 95%;
height: 450px;
background: grey;
}
<script src="https://heremaps.github.io/maps-api-for-javascript-examples/test-credentials.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Polyline on the Map</title>
<link rel="stylesheet" type="text/css" href="https://js.api.here.com/v3/3.1/mapsjs-ui.css" />
<link rel="stylesheet" type="text/css" href="demo.css" />
<link rel="stylesheet" type="text/css" href="styles.css" />
<link rel="stylesheet" type="text/css" href="../template.css" />
<script type="text/javascript" src='../test-credentials.js'></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-core.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-service.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"></script>
</head>
<body id="markers-on-the-map">
<div id="map"></div>
<script type="text/javascript" src='demo.js'></script>
</body>
</html>
this is simple: the var GreatCircle is not defined yet but program code invoke GreatCircle
We moved some parts of code through each together
but any way there is error GreatCircle doesn't have 'arc' property defined.
there is this module https://demo.support.here.com/javascripts/examples/v31/geodesic-polyline.js
but you needs Bézier curve: https://en.wikipedia.org/wiki/B%C3%A9zier_curve
I found some implementation on this https://habr.com/ru/post/163073/ - (but in russian) - there a curve consists from lines based on 100 points (step 0.01)
flow = getBezierCurve(new Array(arr[0], arr[1], arr[2], arr[3]), 0.01);
drawLines(ctx, flow, 10);
In JS API wasn't implemented functionality of like Bézier curve
but search in google on "bezier curve javascript example code" - if you get points of curve you can use in JS API map.screenToGeo every point and plot it on the map
I need to create a new choropleth version of this map whereby the polygons' colorFills respond to data in a column ("PERCENTAGE") from a table that I merged with the original fusion table. The polygons will be either green, yellow or red depending on the percentages.
I'm working from a wordpress plugin that was built by someone else for a project.
var map;
function initMap() {
var myOptions = {
zoom: 4,
center: new google.maps.LatLng( 51.41467424448992, 16.737563625000007 ),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// initialize the map
map = new google.maps.Map( document.getElementById( 'map-canvas' ),
myOptions );
// google maps styles go below here...
map.setOptions( { styles: styles } );
// Initialize JSONP request
var script = document.createElement( 'script' );
var url = ['https://www.googleapis.com/fusiontables/v2/query?'];
url.push( 'sql=' );
var query = 'SELECT name, iso_a2, kml_4326 FROM ' +
'1_XPSB5N6EOCr5i9etLrR0HA3717jfyk4iOamXWqu';
var encodedQuery = encodeURIComponent( query );
url.push( encodedQuery );
url.push( '&callback=drawMap' );
url.push( '&key=AIzaSyAm9yWCV7JPCTHCJut8whOjARd7pwROFDQ' );
script.src = url.join( '' );
var body = document.getElementsByTagName( 'body' )[0];
body.appendChild( script );
}
function drawMap( data ) {
//console.log(getCountry);
//console.log(data['rows']);
var rows = data['rows'];
for ( var i in rows ) {
if ( rows[i][0] != 'Antarctica' ) {
var newCoordinates = [];
var geometries = rows[i][2]['geometries'];
if ( geometries ) {
for ( var j in geometries ) {
newCoordinates.push( constructNewCoordinates( geometries[j] ) );
}
} else {
newCoordinates = constructNewCoordinates( rows[i][2]['geometry'] );
}
var fillColor = "#fff";
var strokeColor = "transparent";//#333 ()
if ( getCountry[rows[i][1]] ) {
fillColor = "#fbbd2b";
strokeColor = "#ff9900";
}
var country = new google.maps.Polygon( {
paths: newCoordinates,
strokeColor: strokeColor,
strokeOpacity: 1,
strokeWeight: 0.4,
fillColor: fillColor,
fillOpacity: 0.18,
name: getCountry[rows[i][1]],
nameCode: rows[i][1]
} );
if ( getCountry[rows[i][1]] ) {
google.maps.event.addListener( country, 'mouseover', function () {
this.setOptions( { fillOpacity: 0.4 } );
} );
google.maps.event.addListener( country, 'mouseout', function () {
this.setOptions( { fillOpacity: 0.18 } );
} );
google.maps.event.addListener( country, 'click', function () {
GetCounty( this.nameCode ); console.log(this.nameCode);
} );
}
google.maps.Polygon.prototype.my_getBounds = function () {
var bounds = new google.maps.LatLngBounds();
this.getPath().forEach( function ( element, index ) {
bounds.extend( element );
} );
return bounds;
};
var lat = country.my_getBounds().getCenter().lat();
var lng = country.my_getBounds().getCenter().lng();
country.setMap( map );
}
}
}
function constructNewCoordinates( polygon ) {
var newCoordinates = [];
var coordinates = polygon['coordinates'][0];
for ( var i in coordinates ) {
newCoordinates.push(
new google.maps.LatLng( coordinates[i][1], coordinates[i][0] ) );
}
return newCoordinates;
}
// Search form, contentpop code goes below here
I have tried adding the styles to the 'new google.maps.Polygon' variable (as below) but it didn't work so I'm wondering where I'm going wrong. Any suggestions appreciated.
{
where: 'PERCENTAGE < 33.3%',
polygonOptions: {
fillColor: '#0000FF'
}
Try 'PERCENTAGE < 0.33' instead. The column is formatted as a percentage, but the actual value is a plain number. You can see this if you add a filter on that column.
So, I'm still not sure why I couldn't get it working inside "var country new google.maps.Polygon" but managed it with "var layer = new google.maps.FusionTablesLayer"
var layer = new google.maps.FusionTablesLayer({
query: {
select: 'iso_a2',
from: '1_XPSB5N6EOCr5i9etLrR0HA3717jfyk4iOamXWqu'
},
styles: [{
where: 'PERCENTAGE < 33.3',
polygonOptions: {
fillColor: "#92bf24",
strokeColor: "#ff9900",
}
}]
});
layer.setMap(map);
There will be 4 different maps in the dropdown though, so I might see if I can find a more convenient way to style the polygons - maybe from the SQL table, which is uncharted territory for me.
I'm trying to implement measuring tools to calculate the area and perimeter of a polygon or the length of a polyline. I've adapted existing code which works with polygons (commented out in the code), but I don't get it to work with both polygons and polylines.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map_div {
height: 100%;
}
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.17&sensor=false&libraries=drawing"></script>
<script>
function initialize() {
map = new google.maps.Map(document.getElementById('map_div'), {
center: {lat: 49.820, lng: 6.100},
zoom: 8
});
// create a dialog box but dont bind it to anything yet
// myInfoWindow = new google.maps.InfoWindow();
// show drawing tools
DrawingTools();
}
function DrawingTools() {
myDrawingManager = new google.maps.drawing.DrawingManager({
drawingMode: null,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_LEFT,
drawingModes: [
google.maps.drawing.OverlayType.POLYGON,
google.maps.drawing.OverlayType.POLYLINE
]
},
polygonOptions: {
draggable: true,
editable: true,
fillColor: '#fb0a2a',
fillOpacity: 0.2,
strokeColor: '#fb0a2a',
zIndex: 2000
},
polylineOptions: {
draggable: true,
editable: true,
strokeColor: '#fb0a2a',
zIndex:2000
}
});
myDrawingManager.setMap(map);
// when polygon drawing is complete, an event is raised by the map
// this function will listen to the event and work appropriately
DrawingCompletionListener();
};
/* Code that already works for polygones
function DrawingCompletionListener() {
// capture the field, set selector back to hand, remove drawing
google.maps.event.addListener(
myDrawingManager,
'polygoncomplete',
function(polygon) {
myField = polygon;
ShowDrawingTools(false);
ObjectEditable(false);
FieldClickListener();
}
);
}
*/
// Code I tried to get work for both polygones AND polylines
function DrawingCompletionListener() {
// capture the field, set selector back to hand, remove drawing
google.maps.event.addListener(
myDrawingManager,
'overlaycomplete',
function(event) {
if (event.type == google.maps.drawing.OverlayType.POLYGON) {
function pg (polygon) {
myField = polygon;
ShowDrawingTools(false);
ObjectEditable(false);
FieldClickListener();
}}
else if (event.type == google.maps.drawing.OverlayType.POLYLINE) {
function pl (polyline) {
myField = polyline;
ShowDrawingTools(false);
ObjectEditable(false);
AddPropertyToField();
FieldClickListener();
}}
}
);
}
/**
* Show or hide drawing tools
*/
function ShowDrawingTools(val) {
myDrawingManager.setOptions({
drawingMode: null,
drawingControl: val
});
}
/**
* Allow or disallow polygon/polyline to be editable and draggable
*/
function ObjectEditable(val) {
myField.setOptions({
editable: val,
draggable: val
});
myInfoWindow.close();
return false;
}
/**
* Attach an event listener to the polygon/polyline. When a user clicks on the
* object, get a formatted message that contains links to re-edit the
* object, mark it as complete, or delete it. The message
* appears as a dialog box
*/
function FieldClickListener() {
google.maps.event.addListener(
myField,
'click',
function(event) {
var message = GetMessage(myField);
myInfoWindow.setOptions({ content: message });
myInfoWindow.setPosition(event.latLng);
myInfoWindow.open(map);
}
);
}
/**
* Delete the polygon and show the drawing tools so that new polygon can be
* created
*/
function DeleteField() {
myInfoWindow.close();
myField.setMap(null);
ShowDrawingTools(true);
}
/**
* Get coordinates of the polygon/polyline and display information that should
* appear in the polygons dialog box when it is clicked
*/
function GetMessage(polygon) {
var coordinates = polygon.getPath().getArray();
var message = '';
message += '<div>'
+ 'area : ~' + GetArea(polygon) + ' ar<br />'
+ 'perimeter : ~' + GetPerimeter(polygon) + ' m'
+ 'length : ~' + GetLength(polyline) + ' m'
+ '</div>';
message += '<hr><div class="btn-group"><button type="button" class="btn btn-primary btn-xs" onclick="PolygonEditable(true);">Edit</button>'
+ '<button type="button" class="btn btn-primary btn-xs" onclick="ObjectEditable(false);">OK</button>'
+ '<button type="button" class="btn btn-primary btn-xs" onclick="DeleteField(myField);">Löschen</button></div>';
return message;
}
/**
* Get area / perimeter of the drawn polygon
*/
function GetArea(poly) {
var result = parseFloat(google.maps.geometry.spherical.computeArea(poly.getPath()))/100;
return result.toFixed(2);
}
function GetPerimeter(poly) {
var perimeter = parseFloat(google.maps.geometry.spherical.computeLength(poly.getPath()));
return perimeter.toFixed(0);
}
function GetLenght(poly) {
var length = parseFloat(google.maps.geometry.spherical.computeLength(poly.getPath()));
return length.toFixed(0);
}
</script>
</head>
<body onload="initialize()">
<div id="map_div">
</div>
</body>
</html>
I've changed the 'DrawingCompletionListener()' function to work.
I still have a little problem. I want to display different informations depending on the type of object, that is drawn. I don't get the correct syntax in my GetMessage(obj)-function to check whether the obj is a polygon or a polyline?
Here the complete code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map_div {
height: 100%;
}
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.17&sensor=false&libraries=drawing"></script>
<script>
function initialize() {
map = new google.maps.Map(document.getElementById('map_div'), {
center: {lat: 49.820, lng: 6.100},
zoom: 8
});
// create a dialog box but dont bind it to anything yet
myInfoWindow = new google.maps.InfoWindow();
// show drawing tools
DrawingTools();
}
function DrawingTools() {
myDrawingManager = new google.maps.drawing.DrawingManager({
drawingMode: null,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_LEFT,
drawingModes: [
google.maps.drawing.OverlayType.POLYGON,
google.maps.drawing.OverlayType.POLYLINE
]
},
polygonOptions: {
draggable: true,
editable: true,
fillColor: '#fb0a2a',
fillOpacity: 0.2,
strokeColor: '#fb0a2a',
zIndex: 2000
},
polylineOptions: {
draggable: true,
editable: true,
strokeColor: '#fb0a2a',
zIndex:2000
}
});
myDrawingManager.setMap(map);
// when polygon drawing is complete, an event is raised by the map
// this function will listen to the event and work appropriately
DrawingCompletionListener();
};
// Draw polygones or polylines and add clicklistener to open infoWindow
function DrawingCompletionListener() {
// capture the field, set selector back to hand, remove drawing
google.maps.event.addListener(
myDrawingManager,
'overlaycomplete',
function(event) {
if (event.type == google.maps.drawing.OverlayType.POLYGON) {
myField = event.overlay;
ShowDrawingTools(false);
ObjectEditable(false);
FieldClickListener();
}
else if (event.type == google.maps.drawing.OverlayType.POLYLINE) {
myField = event.overlay;
ShowDrawingTools(false);
ObjectEditable(false);
FieldClickListener();
}
}
);
}
/**
* Show or hide drawing tools
*/
function ShowDrawingTools(val) {
myDrawingManager.setOptions({
drawingMode: null,
drawingControl: val
});
}
/**
* Allow or disallow polygon/polyline to be editable and draggable
*/
function ObjectEditable(val) {
myField.setOptions({
editable: val,
draggable: val
});
myInfoWindow.close();
return false;
}
/**
* Attach an event listener to the polygon/polyline. When a user clicks on the
* object, get a formatted message that contains links to re-edit the
* object, mark it as complete, or delete it. The message
* appears as a dialog box
*/
function FieldClickListener() {
google.maps.event.addListener(
myField,
'click',
function(event) {
var message = GetMessage(myField);
myInfoWindow.setOptions({ content: message });
myInfoWindow.setPosition(event.latLng);
myInfoWindow.open(map);
}
);
}
/**
* Delete the polygon / polyline and show the drawing tools again
*/
function DeleteField() {
myInfoWindow.close();
myField.setMap(null);
ShowDrawingTools(true);
}
/**
* Display information that should
* appear in the polygons / polylines dialog box when it is clicked
*/
function GetMessage(obj) {
var message = '';
// this is not yet working
if (obj.type == google.maps.drawing.OverlayType.POLYGON) {
message += '<div>'
+ 'area : ' + GetArea(obj) + ' ar<br />'
+ 'perimeter : ' + GetLength(obj) + ' m <br />'
+ '</div>';
}
else if (obj.type == google.maps.drawing.OverlayType.POLYLINE) {
message += '<div>'
+ 'length : ' + GetLength(obj) + ' m <br />'
+ '</div>';
}
message += '<hr><div class="btn-group"><button type="button" class="btn btn-primary btn-xs" onclick="ObjectEditable(true);">Edit</button>'
+ '<button type="button" class="btn btn-primary btn-xs" onclick="ObjectEditable(false);">OK</button>'
+ '<button type="button" class="btn btn-primary btn-xs" onclick="DeleteField(myField);">Delete</button></div>';
return message;
}
/**
* Get area / perimeter / lenght of the drawn polygon / polyline
*/
function GetArea(obj) {
var result = parseFloat(google.maps.geometry.spherical.computeArea(obj.getPath()))/100;
return result.toFixed(2);
}
function GetLength(obj) {
var length = parseFloat(google.maps.geometry.spherical.computeLength(obj.getPath()));
return length.toFixed(0);
}
</script>
</head>
<body onload="initialize()">
<div id="map_div">
</div>
</body>
</html>
I want a circle to act like a heart does, a pulsing animation. So the circle first scales to 75%, then to 100%. I want to make this an infinite loop.
Code:
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var StateModifier = require('famous/modifiers/StateModifier');
var Easing = require('famous/transitions/Easing');
var mainContext = Engine.createContext();
var surface = new Surface({
size: [180, 180],
properties: {
backgroundColor: 'grey',
borderRadius: '50%'
}
});
var stateModifier = new StateModifier();
stateModifier.setTransform(
Transform.scale(0.7, 0.7, 1),
{ duration : 1050 }
);
stateModifier.setTransform(
Transform.scale(1, 1, 1),
{ duration : 450 }
);
mainContext.add(stateModifier).add(surface);
Anyone knows how to implement this?
Use the callback and wrap the setTransform in a function to have each callback call each other when they finish.
Example running snippet
define('main', function(require, exports, module) {
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var StateModifier = require('famous/modifiers/StateModifier');
var Easing = require('famous/transitions/Easing');
var mainContext = Engine.createContext();
var surface = new Surface({
size: [180, 180],
properties: {
backgroundColor: 'grey',
borderRadius: '50%'
}
});
var stateModifier = new StateModifier();
function min() {
stateModifier.setTransform(
Transform.scale(0.7, 0.7, 1), {
duration: 1050
},
max
);
}
function max() {
stateModifier.setTransform(
Transform.scale(1, 1, 1), {
duration: 450
},
min
);
}
mainContext.add(stateModifier).add(surface);
surface.on('deploy', function() {
min();
});
});
require(['main']);
<script src="http://requirejs.org/docs/release/2.1.16/minified/require.js"></script>
<script src="http://code.famo.us/lib/requestAnimationFrame.js"></script>
<script src="http://code.famo.us/lib/classList.js"></script>
<script src="http://code.famo.us/lib/functionPrototypeBind.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.famo.us/famous/0.3.5/famous.css" />
<script src="http://code.famo.us/famous/0.3.5/famous.min.js"></script>