I am trying to create a map of a small area. On this map I have 2 buttons, one is for zooming in and the other is for out. I have created 2 buttons and 1 loader, then connected these together to make it work. My code for buttons and loader:
Loader.qml
Loader {
id: mapLoader
source: "map.qml"
function reload () {
source = ""
source = "map.qml"
console.log("Map Updated")
}
}
Buttons.qml
// This button zooms in 1 unit
// get_Zoomlevel() works on C++; therefore, it isn'T affected from qml reloads.
Button {
...
onClicked: {
map.setZoomLevel(map.get_ZoomLevel() + 1)
mapLoader.reload()
}
...
}
After all, it works as expected, I can zoom in and out easily. However, since the loader loads all the map components from scratch it takes a little longer for a normal and smooth user experience. Therefore, I am looking for a better way of loading or any other advice. Thanks in advance.
I have found the answer and I want to share for the future.
I thought that zoomLevel property of QML Map was only for reading, but I noticed I can also write; therefore, when I noticed it just becomes easy.
I created a variable,
property int zoomLv = 15 // default zoom level
and whenever I zoomed in/ out using buttons I just edited this variable instead of reloading the full map Item.
onClicked: {
zoomLv += 1
}
Related
I am using Bootstrap 5.1.3 (in Rails). Our application consists of dynamically loaded data, that is not always the fastest to load (some complicated SQL queries / huge amounts of data to make calculations with).
We use tooltips on different elements to show extra information / indicate (click)actions. Tooltips are added like this.
On the element that should get the tooltip:
data-bs-toggle="tooltip" data-bs-placement="top" title={question.questionDescription}
In that Bootstrap file:
componentDidUpdate(previousProps, previousState)
{
// Enable all tooltips.
TooltipHelper.enableTooltips([].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')));
}
And then TooltipHelper:
static enableTooltips(targets)
{
var enabledTooltips = targets.map(function (target) {
return new bootstrap.Tooltip(target, { trigger: 'hover' });
});
}
The tooltips work, but don't always go away. My guess is that when a tooltip is shown (because hovering over something) and then that element (or a parent of that element) gets changed, for example the content of it, the tooltip stays there. No matter if I click somewhere of hover over other elements.
I've tried adding a delay within the enableTooltips()-function. This seems to work, but the needed delay is too big. Also, it still breaks when elements are dynamically added and content is loaded, when the page isn't reloaded.
My hacky solution:
static enableTooltips(targets)
{
setTimeout(function() {
var enabledTooltips = targets.map(function (target) {
return new bootstrap.Tooltip(target, { trigger: 'hover' });
});
}, 5000);
}
Anyone know of a solution? Thanks
I'm working with a provider and factory set up in angular, and in the factory is where I do all the heavy lifting of generating the templates, creating the instances, and doing all of the animations. The provider creates a very nifty slider menu from the left.
Problem
What's happening though, is that after the first instance of the slider menu, menu options start to double themselves. So I'll have the original 5, then 10, then 20, then 40... I have found a solution where we start with a null instance, and check if that instance is null, if it is null render the menu. So that forces it to only continuously render the initial 5, but then if we dynamically change the menu we won't ever see those changes and that is not what we want.
Fiddle
https://jsfiddle.net/Mr_Pikachu/chdbxt1h/351/
Broken Code
This is the chunk of code that I am most focused on, as it is the bit that is causing us the issue.
backdropScope.close = function(){
$animate.leave(menu).then(function(){
backdrop.remove();
//menuOpts.scope.$destroy();
// menu_rendered = null;
menu.remove();
});
}
// menustack object
$menuStack = {
'open': function(menuOpts){
menuOpts.scope.main = menuOpts.menu.main;
if(!menu_rendered) {
menu_rendered = menu_template(menuOpts.scope);
}
if(!backdropRendered) {
backdropRendered = backdropTemplate(backdropScope);
}
menuOpts.scope.$apply(function(){
$animate.enter(backdropRendered, body).then(function(){
$animate.enter(menu_rendered, body);
});
});
}
};
List of Attempted Fixes
setting menu_rendered = null in the $animate.leave() will work on the first instance, and re-render the menu properly, but then the backdrop instance won't recognize a click event
Using menuOpts.scope.$destory(), but it did absolutely nothing
Using the current solution of menu_rendered check. It is not optimal and looking for a solution that allows the use of dynamic content.
Updated Fiddle: https://jsfiddle.net/chdbxt1h/355/
I moved the angular.element calls into the body of the $menuStack.open method. The menu content does not get duplicated in repeated exposures. Presumably, this is because the DOM Node is created anew on each open, and garbage collected cleanly on leave and/or remove.
Both the background (menu-overlay) and menu are re-created on each open, so this should honor changes in the source menu data, though possibly not while the menu is open.
I am creating an amMap through amCharts http://docs.amcharts.com/3/javascriptmaps/AmMap and it comes with its own home button which you can click and reverts to the map default.
I would like to do this externally through my own button, but can't quite find the methods that amCharts uses to achieve this.
A few methods I've used are:
chart.zoomTo(), chart.zoomToLongLat(), chart.zoomToXY() using the correct values of when the chart is initialized. This works fine when the chart is not resized ever, but when the chart is resized (not re-initialized), those values become undependable, yet the home button is still able to bring me back to the default zoom.
What method does this home button use? Or I can use to replicate what the home button does?
You need to call zoomToLongLat and pass in your map object's initialZoomLevel, initialZoomLongitude and initialZoomLatitude. From the demo on AmChart's knowledge base for its custom external home button:
function centerMap() {
map.zoomToLongLat(map.initialZoomLevel, map.initialZoomLongitude, map.initialZoomLatitude);
}
You can resize the frame on the codepen demo to see that it resets itself correctly each time.
Yes.. it very simple,
I did it this way:
map.addListener("rendered", function(event) {
var map = event.chart;
map.initialZoomLevel = map.zoomLevel();
map.initialZoomLatitude = map.zoomLatitude();
map.initialZoomLongitude = map.zoomLongitude();
});
function centerMap() {
map.zoomToLongLat(map.initialZoomLevel, map.initialZoomLongitude, map.initialZoomLatitude);
}
<div onclick="centerMap();" class="icon-home"></div>
Using OpenLayers, I have a OpenLayers.Control.SelectFeature installed on a layer, with the hover option set to true. When creating the layer I call
<layer>.events.register("featureselected",...)
and
<layer>.events.register("featureunselected",...)
to register functions that create and destroy a popup. This all works fine. Now I want to add a small delay before the popup is created in order to avoid the popup flickering that currently occurs when moving the mouse across multiple features. However, I can't seem to figure out how to do this. I did find the OpenLayers.Handler.Hover handler, which has a delay option, but I don't know how to combine that with the SelectFeature control (if I even can).
I think this post has some valuable info, which I'm about to verify. Some answers down, someone talks about the flickering.
edit: In case you are making your own labels, I noticed the effect is less when you raise the labelOutlineWidth . It seems that only the letters of the label count as 'hover' and not the whole PointRadius radius. When you make the label outline too big, the label looks like a fly that hit a windscreen though (not a square but it follows the label contours, the letters more specifically).
update: apparently this is why when you hover a text label , check this out: pointer events properties. set this attribute (pointerEvents: ) in your OpenLayers.Style and try value 'all' and the others. It sure makes a difference for me.
I bind my feature selections a little different, here's a quick (untested) example that should get you what you need.
var timer,
delay = 500, //delay in ms
hover = new OpenLayers.Control.SelectFeature( <layer> , {
hover: true,
onSelect: function (feature) {
// setup a timer to run select function
timer = window.setTimeout(function () {
// your select code
}, delay);
},
onUnselect: function () {
// first cancel the pending timer (no side effects)
window.clearTimeout(timer);
// your unselect code
}
});
<map>.addControl(hover);
hover.activate();
How can I easily customize OpenLayers map controls? Or at least, how can I minimize the controls' height?
Thank you.
PS. Is there any CSS override?
You can sub-class any of the openLayers controls. I just made a 'zoom-slider' by sub-classing PanZoomBar (panZoomBar.js), overriding the draw() method and commenting out all the button elements, just leaving the zoom slider.. like this:
function zoomSlider(options) {
this.control = new OpenLayers.Control.PanZoomBar(options);
OpenLayers.Util.extend(this.control,{
draw: function(px) {
// initialize our internal div
OpenLayers.Control.prototype.draw.apply(this, arguments);
px = this.position.clone();
// place the controls
this.buttons = [];
var sz = new OpenLayers.Size(18,18);
var centered = new OpenLayers.Pixel(px.x+sz.w/2, px.y);
this._addButton("zoomin", "zoom-plus-mini.png", centered.add(0, 5), sz);
centered = this._addZoomBar(centered.add(0, sz.h + 5));
this._addButton("zoomout", "zoom-minus-mini.png", centered, sz);
return this.div;
}
});
return this.control;
}
var panel = new OpenLayers.Control.Panel();
panel.addControls([
new zoomSlider({zoomStopHeight:11}),
new OpenLayers.Control.LayerSwitcher({'ascending':false}),
]);
map.addControl(panel);
There is a CSS file that comes with can controls all of the CSS commands for within openlayers generally .olZoombar { here}
It is probably the easiest way to edit those sorts of things otherwise you can edit the actual .js file for the control.
If you are talking about the PanZoomBar or ZoomBar, as has been mentioned, you need to edit the zoomStopHeight. However, You do not need to edit OpenLayers.js.
new OpenLayers.Control.PanZoomBar({zoomStopHeight: 7})
You could consider trying PanZoom, which has no bar.
To minimize the ZoomBar search for zoomStopHeight in OpenLayers.js and edit it as you wish.
Further reference: Link.
Take a look here - http://geojavaflex.blogspot.com/
I am in the process of showing how to do an involved customization of the LayerSwitcher. This might give you ideas on how to do what you are after.
There is a map on the page that shows how the control works, and subsequent posts will discuss the code in detail.
If you are just interested in code see the source of the page and look for the link to CustomLayerSwitcher.js for the customized version of the switcher.