HTML5/Cesium - making divs float over cesium map - html

I am using cesium : http://cesiumjs.org/
and I wanted to make some divs float over a cesium map, but I can't get it to work.
I tried the following container/tag method at jsfiddle.net/j08691/dChUR/5/ - substituing the image by a cesium map div - but it doesn't seem to work - the "tag" div isn't shown.
Any help?

You need to add position: absolute; and either top or bottom to your CSS, because the widget also uses absolute positioning. Adding this creates a new stacking context, which overrides z-index.
Here's a working example, hit "Run Code Snippet" at the bottom of this:
Cesium.Camera.DEFAULT_VIEW_FACTOR = 0;
var viewer = new Cesium.Viewer('cesiumContainer', {
timeline: false,
animation: false,
navigationHelpButton: false
});
var skyAtmosphere = viewer.scene.skyAtmosphere;
var skyCheckbox = document.getElementById('skyCheckbox');
skyCheckbox.addEventListener('change', function() {
viewer.scene.skyAtmosphere = skyCheckbox.checked ? skyAtmosphere : undefined;
}, false);
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
font-family: sans-serif; color: #edffff;
}
#controlPanel {
position: absolute;
top: 5px;
left: 5px;
background: rgba(42, 42, 42, 0.8);
padding: 5px 8px;
border-radius: 5px;
}
label {
cursor: pointer;
}
label:hover span {
text-decoration: underline;
}
<link href="http://cesiumjs.org/releases/1.15/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"/>
<script src="http://cesiumjs.org/releases/1.15/Build/Cesium/Cesium.js">
</script>
<div id="cesiumContainer"></div>
<div id="controlPanel">
This is a floating control panel<br/>
with a translucent background color.
<p>
<label>
<input id="skyCheckbox" type="checkbox" checked />
<span>Enable atmospheric effect</span>
</label><br/>
<button class="cesium-button">Button 1</button>
<button class="cesium-button">Button 2</button>
</p>
</div>

To add to emackey's answer, what I had to do in addition to adding position: absolute to my css was to add a top:150px or bottom:150px. Basically anything that will specify a position relative to the parent container.
Even though using the absolute position it is most likely being pushed down by the cesium widget since it takes up 100% height.

Related

How to flow the text anywhere in html

I want the text to be in the top of the arrow as of the figure shown below:
The html entity of the arrow is ⟶
can you please help me?
This is what I tried, but I want as of figure, arrow is also short as of this ⟶ entity.
.text {
position: relative;
bottom: -10px;
}
<div class="text">MnO<sub>2</sub></div>
<div class="arrow">⟶</div>
Look into MathJax mhchem package. It can let you writing chemical equations easily.
window.MathJax = {
TeX: {
extensions: ["mhchem.js"]
},
tex2jax: {
inlineMath: [
['$', '$'],
["\\(", "\\)"]
]
}
};
.MathJax_CHTML {
font-size: 30px !important;
}
<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
<p> $\xrightarrow{\text{$\ce{MnO2}$}}$</p>
<br />
<p> $\ce{A ->[catalyst] B}$</p>
You could adjust the font size of the arrow and maybe slightly scale the width of the arrow-character by e. g. giving it's parent div something like
display:inline-block;
-webkit-transform:scale(3.0,1.0);
-moz-transform:scale(3.0, 1.0);
-ms-transform:scale(3.0, 1.0);
-o-transform:scale(3.0, 1.0);
transform:scale(3.0,1.0);
Will probably distort your arrowhead to ugly. If you want that exact ratio from text to arrow, you would have to use an appropriate image for the arrow.
Here , this will work for you.
<style>
.text {
position: relative;
bottom: -10px;
left: 12px
}
.arrow {
transform: scale(4, 2);
transform-origin: left;
}
</style>
<body>
<div class="text">MnO<sub>2</sub></div>
<div class="arrow">⟶</div>
</body>

Embed Mapbox Swiping Maps on HTML

I am trying to embed a sliding map onto an HTML page. Right now the map would float on top of other elements. What should I do to make the map appear inside one of the containers?
I try to delete the line .map{position: absolute} but then the map stops showing up at all. I have also tried to make sure other CSS files linked in the HTML is not overriding the map's style.
<style>
body {font-family: "Lato", sans-serif}
.mySlides {display: none}
.map {
/*position: absolute;
top: 500px;
bottom: 0;*/
width: 80%;
}
body {
overflow: hidden;
}
body * {
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
</style>
<body>
<div class="w3-container w3-content w3-center w3-padding-64" style="max-width:800px" id="band">
<h2 class="w3-wide">Guangzhou</h2>
<p class="w3-opacity"><i></i></p>
<hr>
<div id='slidemap-cont'>
<div id='before' class='map'></div>
<div id='after' class='map'></div>
</div>
</div>
<script>
mapboxgl.accessToken = 'MY_ACCESS_TOKEN';
var beforeMap = new mapboxgl.Map({
container: 'before',
style: 'mapbox://styles/estella213439/cju7drf1x1zr41flvd51t9adb',
center: [113.33833,23.08506],
zoom: 12
});
var afterMap = new mapboxgl.Map({
container: 'after',
style: 'mapbox://styles/estella213439/cju7af6q42ia21fqbv7ffas1g',
center: [113.33833,23.08506],
zoom: 12
});
var map = new mapboxgl.Compare(beforeMap, afterMap, {
// Set this to enable comparing two maps by mouse movement:
// mousemove: true
});
</script>
</body>
If you need them to both be position: absolute;, then you need to specify the top for your second element to be the same as the height of the first one
.map {
position: absolute;
width: 80%;
height: 50%;
}
#before {
top: 0;
}
#after {
top: 50%; // Must match height of before element
padding-top:5px; //So you can see where one map stops and the other begins.
}
Here's a JSFiddle with your example to demonstrate.

Vue.js: do not show element until it is in correct position

I am learning Vue and really enjoying it. I have a tab that I want fixed to the bottom of the browser window when the page loads. When a user clicks the tab, it will slide up to show some content.
Everything is working great. I am able to have the tab stick to the bottom of the page - and click events are working great as well.
The problem I am having is that I need to calculate the height of tab (and div) to set the CSS property correctly. When the page loads, you can see the tab slide down into place. I would like to hide the tab until everything has been calculated and it's in the correct place.
Here is what I'm using:
app.js
new Vue({
el: '#info',
delimiters: ['${', '}'],
data: {
active: false,
inactive: true,
styles: {
'bottom': 0
},
},
methods() {
toggle: function (event) {
event.preventDefault();
this.active = !this.active;
this.inactive = !this.inactive;
}
},
mounted() {
let tabHeight = this.$refs.infoTab.clientHeight;
let boxHeight = this.$refs.infoBox.clientHeight; // 473px
this.styles.bottom = -boxHeight + 'px';
}
});
HTML
<div class="info not-active" id="info" #click="toggle" ref="infoTab"
v-cloak
v-bind:class="{ active: active }"
v-bind:style="styles">
<!-- content -->
</div>
style.css
[v-cloak] {
display: none;
}
/* more classes */
.info {
width: 100%;
position: fixed;
&.inactive {
bottom: -100%;
}
&.active {
bottom: 0 !important;
}
}
I know I am close, I just don't want users to see the tab slide into place. It should just be there. I tried using the created hook, but clientHeight is not available.
Any suggestions are greatly appreciated!
I think you can solve this just using CSS, no need to use any of Vue's lifecycle hooks, I made a pen with a vanilla JS example:
let infoNode = document.getElementById('info');
infoNode.addEventListener('click', () => {
if (infoNode.style.top) {
// clear inline top style
infoNode.style.top = '';
} else {
// set top to client height + 2 * border thickness
infoNode.style.top = `calc(100% - ${infoNode.clientHeight}px - 4px)`;
}
});
#info {
font-size: 16px;
width: 200px;
border: 2px solid hsl(0, 0%, 80%);
padding: 8px;
border-radius: 4px;
cursor: pointer;
position: fixed;
/* 100% height of the viewport subtracting:
tab height: padding, margin, & font size */
top: calc(100% - (8px + 8px + 24px));
/* we center the tab horizontally here using
50% the width of the viewport - 50% the fixed
width of the tab */
left: calc(50% - 200px/2);
transition: top 0.5s;
}
.title {
font-size: 24px;
font-weight: 500;
margin-bottom: 8px;
display: block;
}
p {
margin: 0;
}
<div id="info">
<span class="title">Click on Me</span>
<p>
This is the content of the tab, isn't it great? I think so too, and it can be of any arbitrary length!
</p>
</div>
Basically the trick is to use calc with top instead of -100% with bottom for your positioning, then your tab is initially rendered in the correct position and you don't have to worry it being out of place when a visitor first loads your page.

Adding mini cesium container on Main cesium Container

Is it possible to add a mini cesium container on top of Main cesium container as follows .
Both containers should render different information. How this can be achieved in cesium?
Yes, this is possible, but beware that it is a full separate instance of Cesium. This means it takes its own texture memory, GL context, etc. Click "Run code snippet" at the bottom of this for an example.
var mainViewer = new Cesium.Viewer('mainCesiumContainer', {
navigationHelpButton: false, animation: false, timeline: false
});
var insetViewer = new Cesium.Viewer('insetCesiumContainer', {
navigationHelpButton: false, animation: false, timeline: false,
geocoder: false, baseLayerPicker: false, sceneModePicker: false
});
// Make the inset window display in 2D, to show it's different.
insetViewer.scene.morphTo2D(0);
html, body, #mainCesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
font-family: sans-serif;
}
#insetCesiumContainer {
position: absolute;
bottom: 1%;
right: 2%;
width: 40%;
height: 60%;
border: 1px solid #fff;
box-shadow: 0 0 4px #fff;
}
<link href="http://cesiumjs.org/releases/1.16/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"/>
<script src="http://cesiumjs.org/releases/1.16/Build/Cesium/Cesium.js">
</script>
<div id="mainCesiumContainer"></div>
<div id="insetCesiumContainer"></div>

Setting limit for mootools makeResizable dynamically?

I'm trying to set the upper limit values of a resizable image to keep it within the containing div. I'm using mootools to make the image both moveable and resizable (implementing Drag.Move and makeResizable to do so.)
My temporary solution is to use overflow:hidden; so the resized image does not overtake the rest of the page when it is sized beyond the container, but I'd like to be able to have a way so the image can not be resized outside of its container.
I know that since limit is set on 'domready', if I try to set it to a variable that changes value as the image is resized (ie: onDrag), the limit parameter won't be updated on the fly. I'm wondering if anyone has any insight into how I can achieve a similar effect to the Drag.Move container parameter, as makeResizable doesn't seem to have the same parameter.
HTML:
<div id="pImageArea">
<div id="pLogo" class="displayNone">
<div id="moveHandleName">
<img src="uploadedlogo.jpg" id="imgName" />
</div>
<div id="resizeHandleName"></div>
</div>
</div>
CSS:
#imageArea {
float: left;
width: 630px;
height: 400px;
border: 1px solid #333;
position: relative;
overflow: hidden;
}
#imgContainer {
width: 50px;
height: 50px;
border: 1px dashed #333;
position: absolute;
}
#imgName {
width: 100%;
}
#moveHandleName {
width: 100%;
height: 100%;
}
#resizeHandleName {
width: 8px;
height: 8px;
border: 1px solid #000;
position: absolute;
left: 100%;
top: 100%;
margin: -5px 0 0 -5px;
background-color: #fff;
z-index: 100;
}
JS:
window.addEvent('domready', function(){
var xLim = 50;
var yLim = 50;
// Make image moveable
new Drag.Move($('imgContainer'), {
container: $('imageArea'),
handle: $('imgHandleName')
});
// Make image resizable
$('imgContainer').makeResizable({
handle:$('handleName'),
limit: {x: [50, xLim], y: [50, yLim]},
onDrag: function(el) {
// Set imgContainer height
el.setStyle('height', $('imgName').getSize().y + 'px');
// Set upper limits
xLim = $('imageArea').getSize().x - el.getSize().x;
yLim = $('imageArea').getSize().y - el.getSize().y;
},
});
});
Thanks in advance,
Matt
I 'solved' it like this in my own code (modified to use your element and values):
$('imgContainer').retrieve('resizer').setOptions({
limit: {
x: [50, xLim],
y: [50, yLim]
}
});
The move limit should be properly enforced once you specify the 'container' option and your container has a set width and height. When you resize, my draggable does not need to have limits (re)set. (Using Moo 1.4 by the way.)
However, resizing does cause problems in conjunction with move and limits. The key is that the 'limit' option is only set when initializing makeResizable(). The only way to update it is by setting it with the code shown above. But you have to update it right after you dropped the draggable, because that's the only event that affects the limit. So:
// Make image moveable
new Drag.Move($('imgContainer'), {
container: $('imageArea'),
handle: $('imgHandleName'),
onDrop: function() {
$('imgContainer').retrieve('resizer').setOptions({
limit: {
x: [50, $('imageArea').getSize().x - parseInt($('imageArea]).getStyle('left'))],
y: [50, $('imageArea').getSize().y - parseInt($('imageArea]).getStyle('top'))]
}
});
});
As you can see, I've also used getStyle() instead of getPosition() because getPosition() returns a value relative to the window, while Moo sets the draggable top and left relative to the droparea.