I want to have a line that points to some specific points of a 3d Model with a 2DCanvas, but this line should continue pointing to the same point of the model even after moving/rotating it, so the line has to be redrawn, and the initial position re-calculated.
This is a codepen : https://codepen.io/anon/pen/vWKQrO where you can see my intention.
<script src="https://aframe.io/releases/0.5.0/aframe.min.js"></script>
<script src="https://unpkg.com/aframe-html-shader#0.2.0/dist/aframe-html-shader.min.js"></script>
</head>
<script src="https://unpkg.com/aframe-line-component/dist/aframe-line-component.min.js"></script>
</head>
<script type="text/javascript">
AFRAME.registerComponent('drag-rotate-component',{
schema : { speed : {default:1}},
init : function(){
this.ifMouseDown = false;
this.x_cord = 0;
this.y_cord = 0;
document.addEventListener('mousedown',this.OnDocumentMouseDown.bind(this));
document.addEventListener('mouseup',this.OnDocumentMouseUp.bind(this));
document.addEventListener('mousemove',this.OnDocumentMouseMove.bind(this));
},
OnDocumentMouseDown : function(event){
this.ifMouseDown = true;
this.x_cord = event.clientX;
this.y_cord = event.clientY;
},
OnDocumentMouseUp : function(){
this.ifMouseDown = false;
},
OnDocumentMouseMove : function(event)
{
if(this.ifMouseDown)
{
var temp_x = event.clientX-this.x_cord;
var temp_y = event.clientY-this.y_cord;
if(Math.abs(temp_y)<Math.abs(temp_x))
{
this.el.object3D.rotateY(temp_x*this.data.speed/1000);
}
else
{
this.el.object3D.rotateX(temp_y*this.data.speed/1000);
}
this.x_cord = event.clientX;
this.y_cord = event.clientY;
}
}
});
</script>
<a-scene vr-mode-ui="enabled: true">
<a-assets>
<a-asset-item id="brainstem" src="https://cdn.aframe.io/test-models/models/brainstem/BrainStem.gltf"></a-asset-item>
</a-assets>
<a-entity gltf-model="#brainstem" position="0 0 -5" scale="3 3 3" drag-rotate-component >
</a-entity>
<a-entity line geometry="primitive: plane" material="shader: html; target: #boxHTML" position="3 5 -5"></a-entity>
<a-entity position="0 -0.5 2">
<a-camera look-controls="enabled:false"></a-camera>
</a-entity>
<!--<a-obj-model scale="0.01 0.01 0.01" src="#crate-obj" mtl="#crate-mtl"></a-obj-model>-->
<a-entity line="start: 3 5 -5; end: 0.5 2 -5; color: #000000"></a-entity>
<a-sky color="#FAFAFA"></a-sky>
<!-- HTML to render as a material. -->
<div style="width: 100%; height: 100%; position: fixed; left: 0; top: 0; z-index: -1; overflow: hidden">
<div id="boxHTML" style="background-image: url(bad.png); color: white; width: 240px; height: 250px; font-size: 64px; font-family: monospace; text-align: center">
<p style="background: rgb(30, 30, 30); position: absolute; top: 25px; width: 250px">Hello</p>
</div>
</div>
</a-scene>
How could i re-draw the line after rotating?
Thanks!
Answer : Done here : https://codepen.io/spaboy/pen/OOWvKP
You can update the line with .setAttribute('line', {start: newStart, end: newEnd}). Just change the newEnd to point to the new spot. You need to do some transform/math to determine what that new spot is after the model has rotated.
Perhaps I would add an THREE.Object3D to the object (.setObject3D('point', yourObject3D)). Then set the object 3d's position to the point that you want to point at. Then when the model rotates, it's an easy way to get the new point in world space using el.object3D.updateMatrixWorld(); yourObject3D.getWorldPosition();. Use that new world position as the new end point.
Related
index.html:
<script src="app.js"></script>
<div ng-app="app" ng-controller="app" ng-style="{ color: thecolor }">
foo
</div>
app.js:
angular.module("app", [])
.controller("app", function() {
$scope.thecolor = "red";
});
Fiddle.
Expected: "foo" is rendered red. Observed: "foo" is rendered black (the default).
So basically I'm trying to set the style of an element from variables in the scope. I've seen this working in Angular 1.0.2, but I need it to work in 1.4.8.
EDIT: Once I've updated the controller to include the $scope dependency, I still can't get certain things to work, such as positioning within a parent element.
index.html:
<link rel="stylesheet" href="app.css">
<script src="app.js"></script>
<div ng-app="app" ng-controller="app">
<div ng-style="{ left: x, top: y }">
foo
</div>
</div>
app.js:
angular.module("app", [])
.controller("app", ["$scope", function($scope) {
$scope.x = 100;
$scope.y = 100;
}]);
app.css:
body {
margin: 0px;
}
div {
position: relative;
width: 100vw;
height: 100vh;
}
div div {
position: absolute;
}
Expected: "foo" is rendered 100px down and to the right. Observed: no displacement.
Fiddle.
Controller in your code doesnt have $scope as Dependency Injection (DI), based on your updated question modifying the answer as below
controller
angular.module("app", [])
.controller("app", ['$scope',function($scope) {
$scope.thecolor = "red";
$scope.x = 100;
$scope.y = 100;
}]);
view
<div ng-style="{ left: x + 'px', top: y + 'px' }">foo</div>
updated fiddle
You have to specify the unit for the CSS values - you can do it in the view:
<div ng-style="{ left: x + 'px', top: y + 'px' }">
You missed $scope injection in controller.
angular.module("app", [])
.controller("Ctrl", function($scope) {
$scope.thecolor = "red";
});
Here is a working demo:
http://jsbin.com/jomacoj/edit?html,js,console,output
Just a bit of trivia: I have started using backbone just a month back and svg about a week back. Basically am still learning.
I mainly have a cube. On load the front face has a circle divided into sectors. Each sector is clickable. On clicking each sector the cube flips 90 degrees right and that particular sector is zoomed and displayed there.
Now there is a slider on the zoomed sector ranging from 0-10. This I have created again using svg circles on a line equidistantly. The problem is that the circles must be clickable so that the value on which it is clicked should be captured.
But once the cube flips none of the events are firing. I have been struggling with this for 3 days now but no luck. Any help from anybody please.
I understand that the delegateEvents() method needs to be called somewhere, but where am not able to make out. Or is it the css transforms that are disabling the events, I don't understand???
Below is my code:
The js file
var CircleView = Backbone.View.extend({
model: this.model,
xmlns: "http://www.w3.org/2000/svg",
events: {
'click path': 'handleClick',
},
handleClick: function(ev) {
var id = $(ev.currentTarget).attr('id');
var el = this.$el;
model = this.model;
var xAngle = 0, yAngle = -90;
// Cube flips here
(document.getElementById('cube')).style.webkitTransform = "rotateX(" + xAngle + "deg) rotateY(" + yAngle + "deg)";
// view to display the zoomed sector
var secView = new SectorView({el: $('#circleEdit2'), model: model, value: value, id: id});
secView.render();
},
render: function(model) {
// Code to draw svg circle with 12 clickable sectors goes here
// On clicking any sector cube flips and zoomed sector is displayed there
// This is working perfectly
el.html($("#face1").html());
return el;
}
})
var SectorView = Backbone.View.extend({
model: this.model,
id: 0,
value: 0,
xmlns: "http://www.w3.org/2000/svg",
events: {
'click circle': 'handleDots'
},
handleDots: function(ev) {
var id = $(ev.currentTarget).attr('id');
var numID = parseInt(id);
alert("Click Event Called");
},
render: function() {
var id = this.id;
var el = this.$el;
model = this.model;
// Code to draw zoomed Sector ranging from 0-10 goes here
// method to draw slider using svg circles on a line equidistantly
// On clicking each circle value should be captured
// Here click event is not firing but all graphics are displayed correctly
this.drawSlider(el, id, winWidth/2, oRadius, value, (winWidth/3 - oRadius/4.7));
$("#face2").html(this.$el);
$("#radios").css("top", winWidth/3.5);
$("#radios").css("left", left);
this.delegateEvents();
}
})
The HTML:
<html>
<head>
<link rel="stylesheet" href="circleEditTool.css">
<script src="jquery-ui-1.10.2\jquery-1.9.1.js"></script>
<script src="underscore.js"></script>
<script src="backbone.js"></script>
<script src="jquery-ui-1.10.2\ui\jquery-ui.js"></script>
<script src="jquery-ui-1.10.2\ui\jquery.ui.core.js"></script>
<script src="jquery-ui-1.10.2\ui\jquery.ui.widget.js"></script>
<script src="jquery-ui-1.10.2\ui\jquery.ui.mouse.js"></script>
<script src="jquery-ui-1.10.2\ui\jquery.ui.slider.js"></script>
</head>
<body>
<div id="cube">
<div class="face one" id="face1">
<svg id="circleEdit1"> </svg>
</div>
<div class="face two" id="face2">
<svg id="circleEdit2"> </svg>
<div id="radios">
<input name='typeOfArea' type='radio' value="Strength" checked>Strength</input>
<input name='typeOfArea' type='radio' value="OK">OK</input>
<input name='typeOfArea' type='radio' value="Weakness">Weakness</input>
</div>
</div>
</div>
</br></br>
<script src="circleEditTool2.js"> </script>
</body>
</html>
The css:
#experiment {
-webkit-perspective: 1200px;
-webkit-perspective-origin: 50% 300px;
}
#cube {
position: center;
margin: auto;
height: 600px;
width: 600px;
-webkit-transition: -webkit-transform 2s linear;
-webkit-transform-style: preserve-3d;
border: 1px solid #ccc;
background: rgba(255, 255, 255, 1);
}
.face {
position: absolute;
height: 600px;
width: 600px;
background-color: rgba(200, 200, 200, 0.7);
-webkit-backface-visibility: hidden;
background-color: #F2F2F2;
}
#cube .one {
-webkit-transform: translateZ(200px);
opacity: 1;
box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.5);
}
#cube .two {
-webkit-transform: rotateY(90deg) translateZ(350px);
opacity: 1;
box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.5);
}
this is my code. presently the map is normal.i want to apply this in a website with dark theme color and so I want this map in grey shade can any one help please?
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<style type="text/css">
body { font: normal 10pt Helvetica, Arial; }
#map { width: 350px; height: 300px; border: 0px; padding: 0px; }
</style>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="http://code.google.com/apis/gears
/gears_init.js"></script>
</head>
<body>
<div id="map" style="height: 500px; width: 500px;">
<script type="text/javascript">
var mapOpts = { mapTypeId: google.maps.MapTypeId.TERRAIN, zoom: 2, center:
new google.maps.LatLng(20, 0) };
var map = new google.maps.Map(document.getElementById("map"), mapOpts);
var infoWindow = new google.maps.InfoWindow();
var markerBounds = new google.maps.LatLngBounds();
var markerArray = [];
function makeMarker(options) {
var pushPin = new google.maps.Marker({ map: map });
pushPin.setOptions(options);
google.maps.event.addListener(pushPin, "click",
function () { infoWindow.setOptions(options);
infoWindow.open(map, pushPin); });
markerBounds.extend(options.position);
markerArray.push(pushPin);
return pushPin; } google.maps.event.addListener(map, "click",
function () { infoWindow.close(); });
makeMarker({ title: "Test1", position: new google.maps.LatLng(10, 10),
content: "Content1", icon: '' });
makeMarker({ title: "Test2", position: new google.maps.LatLng(20, 20),
content: "Content2", icon: '' });
makeMarker({ title: "Test3", position: new google.maps.LatLng(30, 30),
content: "Content3", icon: '' });
</script>
</div>
</html>
Hi, this is my code. presently the map is normal.i want to apply this in a website with dark theme color and so I want this map in grey shade can any one help please?
you can view this at: http://jsfiddle.net/1nqrwvgk/
You can use CSS filters:
#map
{
filter: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><filter id="g"><feColorMatrix type="matrix" values="0.3 0.3 0.3 0 0 0.3 0.3 0.3 0 0 0.3 0.3 0.3 0 0 0 0 0 1 0"/></filter></svg>#g');
-webkit-filter: grayscale(100%);
filter: grayscale(100%);
filter: progid:DXImageTransform.Microsoft.BasicImage(grayScale=1);
}
http://jsfiddle.net/1nqrwvgk/1/
This will make your map grayscale in all major browsers.
I've been working with Google Maps for a while in my local development environment (I'm working on http://127.0.0.1:5000), but lately I'm getting this error:
Google has disabled use of the Maps API for this application. See the Terms of Service for more information: http://www.google.com/intl/en-US_US/help/terms_maps.html.
In my Google API Console I have created an Browser Key, and I've tried the following domains:
http://127.0.0.1/*
http://localhost/*
http://127.0.0.1:5000/*
http://0.0.0.0:5000/*
http://*:*/*
Obviously, not being about to see the map is making local development quite tricky. But I cannot figure out how to get around this. Can anyone point me at the correct configuration/approach to resolve this?
The documentation doesn't seem to talk about this sort of thing, which isn't helpful.
I got the same trouble, and the issue is to remove the key param in the adress as suggested by Mano Marks.
Just change
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&signed_in=true&callback=initMap"
async defer></script>
to
<script src="https://maps.googleapis.com/maps/api/js?signed_in=true&callback=initMap"
async defer></script>
Below is a full working code (HTML + JS)
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Reverse Geocoding</title>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
#floating-panel {
position: absolute;
top: 10px;
left: 25%;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
text-align: center;
font-family: 'Roboto','sans-serif';
line-height: 30px;
padding-left: 10px;
}
</style>
<style>
#floating-panel {
position: absolute;
top: 5px;
left: 50%;
margin-left: -180px;
width: 350px;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
}
#latlng {
width: 225px;
}
</style>
</head>
<body>
<div id="floating-panel">
<input id="latlng" type="text" value="40.714224,-73.961452">
<input id="submit" type="button" value="Reverse Geocode">
</div>
<div id="map"></div>
<script>
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 8,
center: {lat: 40.731, lng: -73.997}
});
var geocoder = new google.maps.Geocoder;
var infowindow = new google.maps.InfoWindow;
document.getElementById('submit').addEventListener('click', function() {
geocodeLatLng(geocoder, map, infowindow);
});
}
function geocodeLatLng(geocoder, map, infowindow) {
var input = document.getElementById('latlng').value;
var latlngStr = input.split(',', 2);
var latlng = {lat: parseFloat(latlngStr[0]), lng: parseFloat(latlngStr[1])};
geocoder.geocode({'location': latlng}, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
if (results[1]) {
map.setZoom(11);
var marker = new google.maps.Marker({
position: latlng,
map: map
});
infowindow.setContent(results[1].formatted_address);
infowindow.open(map, marker);
} else {
window.alert('No results found');
}
} else {
window.alert('Geocoder failed due to: ' + status);
}
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?signed_in=true&callback=initMap"
async defer></script>
</body>
</html>
I want to highlight a area like on the image below which is taken from Google Maps. Is this possible to accomplish with the current version of their API (v3)? If yes, how?
Thanks in advance.
You need to know the vertices of the area and create a polygon based on them.
But dashed strokes currently are not supported by polygons, if you require to have a dashed stroke you must create a sequence of polylines with different stroke-colors based on the vertices.
A built-in method to highlight an area currently doesn't exist.
You can automatically highlight an area with Google Maps Javascript API, here is an example:
<!DOCTYPE html>
<html>
<head>
<title>Place ID Finder</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
#map {
height: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#ggg
{
position: absolute;
left:20%;
top:5%;
}
.controls {
background-color: #fff;
border-radius: 2px;
border: 1px solid transparent;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
box-sizing: border-box;
font-family: Roboto;
font-size: 15px;
font-weight: 300;
height: 29px;
margin-left: 17px;
margin-top: 10px;
outline: none;
padding: 0 11px 0 13px;
text-overflow: ellipsis;
width: 400px;
}
.controls:focus {
border-color: #4d90fe;
}
.title {
font-weight: bold;
}
#infowindow-content {
display: none;
}
#map #infowindow-content {
display: inline;
}
</style>
</head>
<body>
<div style="display: none">
<input id="pac-input" class="controls" type="text" placeholder="Enter a location">
</div>
<div id="map"></div>
<div id="infowindow-content">
<span id="place-name" class="title"></span><br>
<strong>Place ID:</strong> <span id="place-id"></span><br>
<span id="place-address"></span>
</div>
<script>
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 37.9989746, lng: 23.6413698},
zoom: 11
});
var input = document.getElementById('pac-input');
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.bindTo('bounds', map);
autocomplete.setFields(
['place_id', 'geometry', 'name', 'formatted_address']);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
var infowindow = new google.maps.InfoWindow();
var infowindowContent = document.getElementById('infowindow-content');
infowindow.setContent(infowindowContent);
var marker = new google.maps.Marker({map: map});
marker.addListener('click', function() {
infowindow.open(map, marker);
});
autocomplete.addListener('place_changed', function() {
infowindow.close();
var place = autocomplete.getPlace();
if (!place.geometry) {
return;
}
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17);
}
marker.setPlace({
placeId: place.place_id,
location: place.geometry.location,
});
marker.setVisible(true);
infowindowContent.children['place-name'].textContent = place.name;
infowindowContent.children['place-id'].textContent = place.place_id;
infowindowContent.children['place-address'].textContent = place.formatted_address;
infowindow.open(map, marker);
var frame = document.getElementById("map");
frame.innerHTML = '<iframe width="100%" height="100%" frameborder="0" style="border:0" src="https://www.google.com/maps/embed/v1/place?q=place_id:'.concat(place.place_id).concat('&key=XXXXXXX" allowfullscreen></iframe>');
frame.innerHTML += '<p id="ggg"><button type="button" onclick="location.reload()">Try again!</button></p>';
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=XXXXXXXXX&libraries=places&callback=initMap" async defer></script>
</body>
</html>
You will need to replace API KEY with your API KEY. Try e.g."Nea Smyrni 171 21, Greece" in the input and then select the first drop down option and notice that it automatically highlights the area!