Three.js is an awesome library. Its well documented and its working great.
I am trying to render a plane along with trackball control inside a div. The div resizes as the window or the browser is resized. Following is the issue i am facing
When the browser finishes loading, the plane is displayed in the browser, However, it is not refreshing or responding to the trackball control. But when i minimize the browser or switch tabs the scene becomes active and it works as designed. I am sure the trackball and the scene is working upon load as i am able to see the changes when i refresh it by minimizing the browser or switching tabs. I believe it has to do with rendering or refreshing on load.
Similarly, when i resize the browser the div changes its size but the scene goes back to the frozen state. Once again, if i minimize or switch tabs the scene is resized and works as intended.
I am not able to figure out where the issue is.
Thanks a lot
Sam
<!DOCTYPE html>
<html
lang="en">
<head>
<title>three.js
canvas
-
geometry
-
cube
</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 {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
#Cont3D {
min-width: 200px;
min-height: 400px;
float: none;
margin-left: 20%;
margin-right: 20%;
border-width: thick;
border-style: solid;
margin-top: 100px;
}
</style>
</head>
<body>
<script
src="build/three.js"></script>
<script
src="js/loaders/STLLoader.js"></script>
<script
src="js/renderers/SoftwareRenderer.js"></script>
<script
src="js/controls/TrackballControls_Persp.js"></script>
<script
src="js/modifiers/SubdivisionModifier.js"></script>
<script
src="js/controls/OrbitControls.js"></script>
<script
src="js/libs/stats.min.js"></script>
<script
src="js/Detector.js"></script>
<script>
function startmusic() {
var container, stats;
var camera, scene, renderer;
var plane;
var targetRotationX = 0;
var targetRotationOnMouseDownX = 0;
var mouseX = 0;
var mouseXOnMouseDown = 0;
var targetRotationY = 0;
var targetRotationOnMouseDownY = 0;
var mouseY = 0;
var mouseYOnMouseDown = 0;
var Width, Height;
init();
animate();
function init() {
container = document.getElementById("Cont3D");
var info = document.createElement('div');
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = 'Drag to spin the cube';
container.appendChild(info);
Width = container.clientWidth;
Height = container.clientHeight;
camera = new THREE.PerspectiveCamera(50, Width / Height, 1, 2000);
camera.position.y = 150;
camera.position.z = 500;
scene = new THREE.Scene();
// Plane
var geometry = new THREE.PlaneGeometry(200, 200);
geometry.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
var material = new THREE.MeshBasicMaterial({
color: 0xe0e0e0
});
plane = new THREE.Mesh(geometry, material);
scene.add(plane);
//LIGHTS
hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6);
hemiLight.color.setHSL(0.6, 1, 0.6);
hemiLight.groundColor.setHSL(0.095, 1, 0.75);
hemiLight.position.set(0, 500, 0);
scene.add(hemiLight);
scene.fog = new THREE.Fog(0xffffff, 3000, 10000);
scene.fog.color.setHSL(0.6, 0.87, 0.96);
spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(0, 1800, 0);
spotLight.target.position.set(0, 0, 0);
spotLight.castShadow = true;
scene.add(spotLight);
// RENDERER
// directional lighting
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position = camera.position; // .set(1, 1, 1).normalize();
scene.add(directionalLight);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(scene.fog.color, 1);
document.getElementById("logBox").innerHTML = container.style.width + "," + Width;
renderer.setSize(Width, Height);
container.appendChild(renderer.domElement);
controls = new THREE.TrackballControls(camera, renderer.domElement)
controls.rotateSpeed = .8;
controls.zoomSpeed = .7;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = false;
controls.dynamicDampingFactor = 0.6;
controls.maxDistance = 1000;
controls.minDistance = 150;
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild(stats.domElement);
controls.addEventListener('change', render);
container.addEventListener('resize', onWindowResize, false);
}
function onWindowResize(event) {
Width = container.clientWidth;
Height = container.clientHeight;
document.getElementById("logBox").innerHTML = Width + "," + Height;
camera.aspect = Width / Height;
camera.updateProjectionMatrix();
renderer.setSize(Width, Height);
controls.handleResize();
renderer.render(scene, camera);
}
function animate() {
requestAnimationFrame(animate);
render();
controls.update();
stats.update();
}
function render() {
renderer.render(scene, camera);
}
window.onresize = onWindowResize;
}
window.onload = startmusic;
</script>
<div
id="logBox"
style="position: absolute; top: 50px; width: 100%; text-align: center;">Blue</div>
<div
id="Cont3D">
</div>
</body>
</html>
function onWindowResize(event) {
Width = container.clientWidth;
Height = container.clientHeight;
document.getElementById("logBox").innerHTML = Width + "," + Height;
renderer.setSize(width, height);
camera.aspect = Width / Height;
camera.updateProjectionMatrix();
controls.handleResize();
}
You don't need
renderer.render(scene, camera);
In your resize handler.
Related
Using the canvas, the image changes when scrolling.
I wrote the code for animation.
If css gives you the same value as positio:absolute top:4000px,
Even if I scroll, the animation doesn't work.
It works if you lower the top value. I have to operate at the top 4000px position.
I'm curious about the solution
var canvas = document.getElementById('macbook');
var ctx = canvas.getContext('2d');
var scrollYPos = 1000;
var img = new Image();
img.src = "img/AirPods Max/large0.jpg";
window.addEventListener('scroll', function(e) {
scrollYPos = Math.round (window.scrollY/5);
console.log(scrollYPos);
if (scrollYPos> 52) {
scrollYPos = 52;
}
player(scrollYPos);
});
function player(num) {
img.src = `img/AirPods Max/large${num}.jpg`;
}
img.addEventListener('load', function(e) {
ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(img, 0,0);
})
canvas {
position: absolute;
top: 4000px;
}
<div id="img-sequence">
<canvas width="1004" height="1214" id="macbook"></canvas>
</div>
How do you change the markers with custom markers active in the map in the directions panel and change the color aswell from the body? Any help much appreciated.
The screenshot:
http://i.stack.imgur.com/wYFoc.png
Just to keep alive #MrUpsidown comment and code alive:
Short answer: you can't. Longer answer: don't use the directions
panel. Create your own, with the information you need (from the
directions service response) and add your custom markers.
Nov 24 at 16:32
Fiddle
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var routeBounds = false;
var overlayWidth = 200; // Width of the overlay DIV
var leftMargin = 30; // Grace margin to avoid too close fits on the edge of the overlay
var rightMargin = 80; // Grace margin to avoid too close fits on the right and leave space for the controls
overlayWidth += leftMargin;
var start = new google.maps.LatLng(3.148173, 101.7148792);
var end = new google.maps.LatLng(3.1347725, 101.6893408);
function initialize() {
var btn1 = document.getElementById('calcRoute');
btn1.addEventListener('click', calcRoute);
var btn2 = document.getElementById('offsetMap');
btn2.addEventListener('click', offsetMap);
var btn3 = document.getElementById('fitAndOffsetMap');
btn3.addEventListener('click', fitAndOffsetMap);
var btn4 = document.getElementById('fitMap');
btn4.addEventListener('click', fitMap);
directionsDisplay = new google.maps.DirectionsRenderer({
draggable: true
});
var mapOptions = {
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: start,
panControlOptions: {
position: google.maps.ControlPosition.TOP_RIGHT
},
zoomControlOptions: {
position: google.maps.ControlPosition.TOP_RIGHT
}
};
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
directionsDisplay.setMap(map);
}
function offsetMap() {
if (routeBounds !== false) {
// Clear listener defined in directions results
google.maps.event.clearListeners(map, 'idle');
// Top right corner
var topRightCorner = new google.maps.LatLng(map.getBounds().getNorthEast().lat(), map.getBounds().getNorthEast().lng());
// Top right point
var topRightPoint = fromLatLngToPoint(topRightCorner).x;
// Get pixel position of leftmost and rightmost points
var leftCoords = routeBounds.getSouthWest();
var leftMost = fromLatLngToPoint(leftCoords).x;
var rightMost = fromLatLngToPoint(routeBounds.getNorthEast()).x;
// Calculate left and right offsets
var leftOffset = (overlayWidth - leftMost);
var rightOffset = ((topRightPoint - rightMargin) - rightMost);
// Only if left offset is needed
if (leftOffset >= 0) {
if (leftOffset < rightOffset) {
var mapOffset = Math.round((rightOffset - leftOffset) / 2);
// Pan the map by the offset calculated on the x axis
map.panBy(-mapOffset, 0);
// Get the new left point after pan
var newLeftPoint = fromLatLngToPoint(leftCoords).x;
if (newLeftPoint <= overlayWidth) {
// Leftmost point is still under the overlay
// Offset map again
offsetMap();
}
} else {
// Cannot offset map at this zoom level otherwise both leftmost and rightmost points will not fit
// Zoom out and offset map again
map.setZoom(map.getZoom() - 1);
offsetMap();
}
}
}
}
function fromLatLngToPoint(latLng) {
var scale = Math.pow(2, map.getZoom());
var nw = new google.maps.LatLng(map.getBounds().getNorthEast().lat(), map.getBounds().getSouthWest().lng());
var worldCoordinateNW = map.getProjection().fromLatLngToPoint(nw);
var worldCoordinate = map.getProjection().fromLatLngToPoint(latLng);
return new google.maps.Point(Math.floor((worldCoordinate.x - worldCoordinateNW.x) * scale), Math.floor((worldCoordinate.y - worldCoordinateNW.y) * scale));
}
function calcRoute() {
var request = {
origin: start,
destination: end,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function (response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
// Define route bounds for use in offsetMap function
routeBounds = response.routes[0].bounds;
// Write directions steps
writeDirectionsSteps(response.routes[0].legs[0].steps);
// Wait for map to be idle before calling offsetMap function
google.maps.event.addListener(map, 'idle', function () {
// Offset map
offsetMap();
});
// Listen for directions changes to update bounds and reapply offset
google.maps.event.addListener(directionsDisplay, 'directions_changed', function () {
// Get the updated route directions response
var updatedResponse = directionsDisplay.getDirections();
// Update route bounds
routeBounds = updatedResponse.routes[0].bounds;
// Fit updated bounds
map.fitBounds(routeBounds);
// Write directions steps
writeDirectionsSteps(updatedResponse.routes[0].legs[0].steps);
// Offset map
offsetMap();
});
}
});
}
function writeDirectionsSteps(steps) {
var overlayContent = document.getElementById("overlayContent");
overlayContent.innerHTML = '';
for (var i = 0; i < steps.length; i++) {
overlayContent.innerHTML += '<p>' + steps[i].instructions + '</p><small>' + steps[i].distance.text + '</small>';
}
}
function fitMap() {
if (routeBounds !== false) {
map.fitBounds(routeBounds);
}
}
function fitAndOffsetMap() {
if (routeBounds !== false) {
map.fitBounds(routeBounds);
offsetMap();
}
}
initialize();
body {
margin:0;
padding:0;
font-family: Arial;
}
#map-canvas {
height:450px;
width:950px;
}
#overlay {
position: absolute;
width: 200px;
height: 450px;
background: black;
opacity: .8;
top: 0;
left: 0;
overflow: auto;
}
#overlayContent {
color: white;
padding: 10px 20px;
}
#overlayContent p {
font-size: 12px;
margin: 6px 0;
}
#overlayContent small {
display: block;
text-align: right;
font-style: italic;
}
small {
font-size: 9px;
}
i {
color: lightblue;
}
h1 {
font-size: 20px;
}
h5 {
font-size: 12px;
}
button {
margin: 20px 0 0 20px;
}
<div id="map-canvas"></div>
<div id="overlay">
<div id="overlayContent">
<h1>DIV OVERLAY</h1>
<h5>Routes should not be drawn below this element.</h5>
<h5>Click the <i>Calc route</i> button to draw the directions route.</h5>
<h5><i>Map offset</i> will be applied automatically.</h5>
<h5><i>Drag the route</i> to see how it is applied.</h5>
<h5>Click the <i>Offset map</i> button to reapply the offset.</h5>
<h5>Click the <i>Fit only</i> button to only fit route bounds.</h5>
<h5>Click the <i>Fit and offset map</i> button to fit to route bounds and reapply offset.</h5>
</div>
</div>
<button id="calcRoute">Calc route</button>
<button id="offsetMap">Offset map</button>
<button id="fitMap">Fit only</button>
<button id="fitAndOffsetMap">Fit and offset map</button>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry" type="text/javascript"></script>
I can't seem to scale a canvas that's populated by an image within a fixed container in IE9. anyone know a work around? I recall reading some other thread about how IE treats a canvas as a block element
<style type="text/css">
#container { max-width: 25%; max-height: 25%; }
canvas { max-width: 90%; max-height: 90%; }
</style>
<script type="text/javascript">
var img = new Image();
img.src = 'http://l.yimg.com/dh/ap/default/121214/babydeer340.jpg';
img.onload = function () {
$('canvas').each(function () {
var ctx = this.getContext("2d");
ctx.drawImage(img, 0, 0);
});
};
</script>
<div id="container">
<canvas id='fit-to-specified-width-height-with-aspect-ratio'></canvas>
</div>
<canvas id='normal'></canvas>
http://jsfiddle.net/VAXrL/535/
I too wish this behavior was consistent in all browsers but it looks like IE9 and a couple others treat canvas like a block level element and so you would need to style both width and height.
The canvas element will have to rely on hard pixels in its size since it is rasterized. One approach would be to calculate and set these pixels based on the original size of the image and a desired scale.
I forked your JSFiddle: http://jsfiddle.net/cbosco/ttU5L/3/
var img = new Image();
var SCALE = 0.25;
img.onload = function () {
$('canvas').each(function () {
var w = img.width;
var h = img.height;
w *= SCALE;
h *= SCALE;
this.width = w;
this.height = h;
var ctx = this.getContext("2d");
ctx.scale(SCALE, SCALE);
ctx.drawImage(img, 0, 0);
});
};
// good idea to set src attribute AFTER the onload handler is attached
img.src = 'http://l.yimg.com/dh/ap/default/121214/babydeer340.jpg';
I'm trying to replicate something similar to the following map, where the polygonal area is transparent and the surrounding area is semi-transparent:
Can anyone help with this?
Here's the original:
https://energyeasy.ue.com.au/outages/powerOutages
Using some CSS and a large 512 x 512px png I have managed to emulate what I wanted to achieve.
I'm sure there would be more accurate methods but this has worked for me.
http://www.syn-rg.com.au/Development/United-Energy/mg_map/MG_Area_map_02.html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0; }
#map_canvas {
background-color: #EAEAEA;
border: 1px solid #CCCCCC;
height: 400px;
margin-bottom: 10px;
margin-left: auto;
margin-right: auto;
width: 532px;
}
#map_canvas div div div div div img{ border:1000px solid black;margin:-1000px -1000px;}
/*#map_canvas div div div div div div div{ background: none repeat scroll 0px 0px rgba(0, 0, 0, 0.5);}*/
</style>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=AIzaSyA7UaoyrY4KyoW1iEU0KFo0ZOxH5w30oZ8&sensor=true"></script>
<script type="text/javascript">
var overlay;
USGSOverlay.prototype = new google.maps.OverlayView();
function initialize() {
var myLatLng = new google.maps.LatLng(-37.815676, 145.449005);
var myOptions = {
zoom: 9,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var swBound = new google.maps.LatLng(-38.269876, 144.842405); // Latitude, Longitude = 182.749 or 107.183 or 108.4443 or 107.77615
var neBound = new google.maps.LatLng(-37.161476, 146.249005); // -0.5542, +0.7033 = 256px
//var swBound = new google.maps.LatLng(-37.783, 144.966);
//var neBound = new google.maps.LatLng(-37.225, 145.66930);
//var swBound = new google.maps.LatLng(62.281819, -150.287132);
//var neBound = new google.maps.LatLng(62.400471, -150.005608);
var bounds = new google.maps.LatLngBounds(swBound, neBound);
// Photograph courtesy of the U.S. Geological Survey
var srcImage = 'images/mg_map_full.png';
overlay = new USGSOverlay(bounds, srcImage, map);
}
function USGSOverlay(bounds, image, map) {
// Now initialize all properties.
this.bounds_ = bounds;
this.image_ = image;
this.map_ = map;
// We define a property to hold the image's div. We'll
// actually create this div upon receipt of the onAdd()
// method so we'll leave it null for now.
this.div_ = null;
// Explicitly call setMap on this overlay
this.setMap(map);
}
USGSOverlay.prototype.onAdd = function () {
// Note: an overlay's receipt of onAdd() indicates that
// the map's panes are now available for attaching
// the overlay to the map via the DOM.
// Create the DIV and set some basic attributes.
var div = document.createElement('div');
div.style.borderStyle = "none";
div.style.borderWidth = "0";
div.style.borderColor = "red";
div.style.position = "absolute";
div.style.opacity = "0.3";
// Create an IMG element and attach it to the DIV.
var img = document.createElement("img");
img.src = this.image_;
img.style.width = "100%";
img.style.height = "100%";
img.style.position = 'absolute';
div.appendChild(img);
// Set the overlay's div_ property to this DIV
this.div_ = div;
// We add an overlay to a map via one of the map's panes.
// We'll add this overlay to the overlayImage pane.
var panes = this.getPanes();
panes.overlayImage.appendChild(div);
}
USGSOverlay.prototype.draw = function () {
// Size and position the overlay. We use a southwest and northeast
// position of the overlay to peg it to the correct position and size.
// We need to retrieve the projection from this overlay to do this.
var overlayProjection = this.getProjection();
// Retrieve the southwest and northeast coordinates of this overlay
// in latlngs and convert them to pixels coordinates.
// We'll use these coordinates to resize the DIV.
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
// Resize the image's DIV to fit the indicated dimensions.
var div = this.div_;
div.style.left = sw.x + 'px';
div.style.top = ne.y + 'px';
div.style.width = (ne.x - sw.x) + 'px';
div.style.height = (sw.y - ne.y) + 'px';
}
USGSOverlay.prototype.onRemove = function () {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="position: relative; background-color: rgb(229, 227, 223); overflow: hidden;"></div>
</body>
</html>
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Best way to center a <div> on a page vertically and horizontally?
I have a canvas element, and I'd like it to be right in the very center of a page, both vertical and horizontal.
I'm a programmer, and I don't much about CSS. Can anybody help me with centering my canvas both vertically and horizontally?
Here's my current CSS code:
/* Set up canvas style */
#canvas {
font-family: 'pixel';
margin-left: auto;
margin-right: auto;
display: block;
border: 1px solid black;
cursor: none;
outline: none;
}
It's already being centered horizontally, but not vertically, thank you in advance!
this should do the trick:
#canvas {
position: absolute;
top: 50%; left: 50%;
width: 200px;
height: 200px;
margin: -100px 0 0 -100px;
}
The margin top and left has to be negative half the height and width of the element.
The same principal applies if you don't know the width and height and need to calculate it with javascript. Just get the width/height, divide those by half and set the values as a margin in the same way as the example above.
Hope that helps :)
I don't know if this would help, but I wrote this jQuery plugin that might help. I also know this script needs adjustments. It'd adjust the page when needed.
(function($){
$.fn.verticalCenter = function(){
var element = this;
$(element).ready(function(){
changeCss();
$(window).bind("resize", function(){
changeCss();
});
function changeCss(){
var elementHeight = element.height();
var windowHeight = $(window).height();
if(windowHeight > elementHeight)
{
$(element).css({
"position" : 'absolute',
"top" : (windowHeight/2 - elementHeight/2) + "px",
"left" : 0 + "px",
'width' : '100%'
});
}
};
});
};
})(jQuery);
$("#canvas").verticalCenter();
Refined Code + Demo
Please, view this demo in "Full page" mode.
(function($) {
$.fn.verticalCenter = function(watcher) {
var $el = this;
var $watcher = $(watcher);
$el.ready(function() {
_changeCss($el, $watcher);
$watcher.bind("resize", function() {
_changeCss($el, $watcher);
});
});
};
function _changeCss($self, $container) {
var w = $self.width();
var h = $self.height();
var dw = $container.width();
var dh = $container.height();
if (dh > h) {
$self.css({
position: 'absolute',
top: (dh / 2 - h / 2) + 'px',
left: (dw / 2 - w / 2) + 'px',
width: w
});
}
}
})(jQuery);
$("#canvas").verticalCenter(window);
$(function() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
drawSmile(ctx, 0.9, 'yellow', 'black', 0.75);
});
function drawSmile(ctx, scale, color1, color2, smilePercent) {
var x = 0, y = 0;
var radius = canvas.width / 2 * scale;
var eyeRadius = radius * 0.12;
var eyeXOffset = radius * 0.4;
var eyeYOffset = radius * 0.33;
ctx.save();
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.beginPath(); // Draw the face
ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = color1;
ctx.fill();
ctx.lineWidth = radius * 0.05;
ctx.strokeStyle = color2;
ctx.stroke();
ctx.beginPath(); // Draw the eyes
ctx.arc(x - eyeXOffset, y - eyeYOffset, eyeRadius, 0, 2 * Math.PI, false);
ctx.arc(x + eyeXOffset, y - eyeYOffset, eyeRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = color2;
ctx.fill();
ctx.beginPath(); // Draw the mouth
ctx.arc(0, 0, radius * 0.67, Math.PI * (1 - smilePercent), Math.PI * smilePercent, false);
ctx.stroke();
ctx.restore();
}
#canvas {
border: 3px dashed #AAA;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<canvas id="canvas" width="256" height="256"></canvas>