Hello I want to use larger zooming factors via the ZoomControl Buttons.
How is that possible in AmCharts (Maps) Version 4?
I could find an old documentation which describes my wanted feature:
https://docs.amcharts.com/javascriptmaps/ZoomControl (zoomFactor)
In the new docs I can only find it in "components".
The only way I think I could make it work is listening into the "hit" event on the zoomControl Button, then determine if it was a positive(zoomIn) or negative(zoomOut) event and zoom manually the Chart because the Chart extends the Component which contains the zoomFactor im looking for.
amCharts 4.0.14+: chart.zoomStep
With amCharts 4.0.14+ a MapChart.zoomStep has been implemented which is precisely what you're looking for. As of this writing (January 2, 2019), it is not yet documented except in the changelog.
All you would have to do is:
chart.zoomStep = 3;
Our Zooming to Countries Map demo's default zoomStep is 2. Here's a fork where it's 3:
https://codepen.io/team/amcharts/pen/d454553836da95fe2345a608e1a0efbd
amCharts <= 4.0.13: custom "zoom factor"
If you're referring to Component.zoomFactor, then all charts have this property. Even though it's called zoomFactor, it's not what you're thinking, also, it's read-only anyway.
Unfortunately what you describe as a "zooming factor" cannot be overridden, the buttons basically zoomIn() and zoomOut(), within those methods a zooming factor of 2 is hardcoded. Listening in on the "hit" event wouldn't work because you'd have competing zoom events. If you disabled the original "hit" event and made your own, there is still additional helper logic for keyboards for accessibility purposes, so your custom event and these helpers will have inconsistent zoom factors. So what can be done is to kill the default plusButton and minusButton and roll your own.
To disable them just set their .disabled property to true:
chart.zoomControl.plusButton.disabled = true;
chart.zoomControl.minusButton.disabled = true;
Then we'll make our own versions of the buttons also as children of the ZoomControl container and place them before/after its slider to simulate the original buttons:
var plusButton = chart.zoomControl.createChild(am4core.Button);
plusButton.shouldClone = false;
plusButton.label.text = "+";
plusButton.width = am4core.percent(100);
plusButton.padding(5, 5, 5, 5);
plusButton.marginBottom = 2;
plusButton.insertBefore(chart.zoomControl.slider);
var minusButton = chart.zoomControl.createChild(am4core.Button);
minusButton.shouldClone = false;
minusButton.label.text = "-";
minusButton.width = am4core.percent(100);
minusButton.padding(5, 5, 5, 5);
minusButton.marginTop = 1;
minusButton.insertAfter(chart.zoomControl.slider);
Then we'll provide "hit" events on the buttons that zoom in/out with our own zooming factor (customZoomFactor below):
var customZoomFactor = 3; // default: 2
plusButton.events.on("hit", function() {
chart.zoomToGeoPoint(
chart.zoomGeoPoint,
chart.zoomLevel * customZoomFactor,
false
);
});
minusButton.events.on("hit", function() {
chart.zoomToGeoPoint(
chart.zoomGeoPoint,
chart.zoomLevel / customZoomFactor,
false
);
});
Here's a fork of our Zooming to Countries Map demo that incorporates all of the above code:
https://codepen.io/team/amcharts/pen/f358095c9ea00d875049b67a7bd13df4
Related
I would like to have my element zoom-based. I don't need it visible when zooming out of 19, because my map doesn't look nice.
I tried to use the maxResolution method derived from the layers.js file, when it was found, as a whole map was generated by the QGIS2web plugin.
Unfortunately it wasn't working
I tried also the minZoom feature, but in vain.
All the reasonable examples I found here:
https://openlayers.org/en/latest/apidoc/module-ol_View.html
https://openlayers.org/en/latest/examples/layer-zoom-limits.html
https://github.com/Viglino/ol-ext/issues/51
Another thread says about changing the maxResolution value, but it didn't work either.
https://gis.stackexchange.com/questions/160725/vector-layer-visibility-using-min-maxresolution-is-not-working-in-openlayers-2
Finally, my code looks as follows:
var tekst2 = new ol.Overlay({
position: pos3,
minZoom: 19,
element: document.getElementsByClassName('tekscio')[1],
});
map.addOverlay(tekst2);
I see, that the minZoom refers mostly for the lower zoom limit of the map canvas.
But this configuration:
var tekst2 = new ol.Overlay({
position: pos3,
element: document.getElementsByClassName('tekscio')[1],
maxResolution:0.42006699228392946,
});
map.addOverlay(tekst2);
didn't work either.
I also found some methods here:
http://dev.openlayers.org/releases/OpenLayers-2.13.1/doc/apidocs/files/deprecated-js.html
http://dev.openlayers.org/docs/files/OpenLayers/Layer/FixedZoomLevels-js.html#OpenLayers.Layer.FixedZoomLevels.getOLZoomFromMapObjectZoom
but it looks like they have been deprecated.
What should I do in this code? Is there another thing to provide here, which I am missing?
I want to have this text based on the zoom level.
Just in case I am sending the JS fiddle with the javascript code here:
https://jsfiddle.net/uxkcyomf/
I would like to have my element zoom-based. I don't need it visible when zooming out of 19, because my map doesn't look nice.
You can simply show/hide an element depending on the current zoom level in a way similar to this (the zoom change handler was taken from https://gis.stackexchange.com/a/309404/70847):
var currZoom = map.getView().getZoom();
map.on("moveend", function(e) {
var newZoom = map.getView().getZoom();
if (currZoom != newZoom) {
if (newZoom > 19) {
document.getElementById("vienna").style.display = "none";
} else {
document.getElementById("vienna").style.display = "unset";
}
currZoom = newZoom;
}
});
So i have 3 different, which contains different 3d objects with special animations.
First is 3d objects rotating above the head and change the angle of orbit with our head shakes. The second one is falling 2d sprites all around character calling by eye closing. And the third one is simple facemesh with grid texture on it. Im draw special UI and code it, so in ArPlayer it works perfects, but when im try to upload it to facebook this UI not working and i have only mask number 1.
So im try to search the solution on Youtube and have only this, but this works only with texture changing i think. So my question is: Can i use instagram changing ui with my effects and if yes, how i can do this. Thaks a lot!
P.S: All images u can find.
Effects must not use custom buttons, keyboards, pickers or sliders - effects may use the native UI picker and slider only. (Spark AR Review Policies 2.6)
Using the Native UI picker, you can not only change textures, but also the visibility of objects.
Example:
Create a new project
Create several plane objects on the scene (for example 3 pieces) and name them obj0,
obj1, obj2 and make them invisible
In Capabilities add Native UI -> Picker
Add 3 textures to the project and name them icon_1, icon_2, icon_3 and check the "No compression" option for everyone
Add such a script
const NativeUI = require('NativeUI');
const Textures = require('Textures');
const Scene = require('Scene');
Promise.all([
Textures.findFirst('icon_1'),
Textures.findFirst('icon_2'),
Textures.findFirst('icon_3'),
Scene.root.findFirst('obj0'),
Scene.root.findFirst('obj1'),
Scene.root.findFirst('obj2')
]).then(onReady);
function onReady(assets) {
const texture0 = assets[0];
const texture1 = assets[1];
const texture2 = assets[2];
const objects = [assets[3],assets[4],assets[5]];
const picker = NativeUI.picker;
const index = 0;
const configuration = {
selectedIndex: index,
items: [
{image_texture: texture0},
{image_texture: texture1},
{image_texture: texture2}
]
};
picker.configure(configuration);
picker.visible = true;
picker.selectedIndex.monitor({fireOnInitialValue:true}).subscribe(function(index) {
objects[index.newValue].hidden = false;
if(index.oldValue != undefined)
{
objects[index.oldValue].hidden = true;
}
});
}
A similar official example is from developers, there they used Native UI picker (script) + patch to hide objects. Launch Spark AR Studio and create new project from template "3D Stickers" and watch how they did it. If you don’t have such a project template, update Spark AR Studio.
I have two boxes. One spawns on the ground and the other is dropped on top of it. Gravity is turned on. I am trying to get the collision event listener to fire on the bottom box which is resting on the ground. However, nothing is logged.
var c = new Physijs.BoxMesh( new THREE.CubeGeometry( 5, 5, 5 ), new THREE.MeshBasicMaterial({ color: 0x888888 }) );
c.__dirtyPosition = true;
c.position.set(10, 0,-5);
c.addEventListener('collision', function(object){
console.log("hello world"); // NOT FIRING
});
scene.add(c);
var p = c.clone();
p.__dirtyPosition = true;
p.position.y = 50;
scene.add(p);
I can't figure out what I'm doing wrong - could it be because of __dirtyPosition?
EDIT: I tested it without clone() and creating the second box anew, but it doesn't make a difference.
EDIT 2: It's worth mentioning that the simulation runs fine I just can't get the listener to work.
Relevant GitHub Issue
It looks like the clone method is part of THREEjs, not Physijs. So your code just clones the physical material, not the physical mesh. You're just going to have to create another BoxMesh using the same code you did for c.
Is it possible to hide all features on a layer when zooming occurs? I've tried to set both the visible and opacity properties on the layer itself to now show when zooming. Also i've tried to set style on each feature to 'none' but it dosen't seem to work. I've tried with these two alternatives:
1.
function hideGraphicsFeatures(hide) {
if(hide) {
graphicsLayer.setVisible(false);
} else {
graphicsLayer.setVisible(true);
}
map.render();
}
2.
function hideGraphicsFeatures(hide) {
var features = graphicsLayer.getFeatures();
if(hide) {
for (var i = features.length - 1; i >= 0; i--) {
features[i].style.display = 'none';
};
} else {
for (var i = features.length - 1; i >= 0; i--) {
features[i].style.display = ''; // show. Set to anything but 'none'
};
}
map.render();
}
I believe I know what you are looking for. I had to do something similar to improve the zoom/pan performance when tens of thousands of features on many layers were displayed on the map. For panning I set the layers' visibility to false when the first map 'pointerdrag' event is triggered and set them back to visible in the 'moveend' event (you may need some additional handling to avoid redundant actions and data reloads).
For zooming it is a bit trickier but fortunately you can override the ol.interaction.MouseWheelZoom handler by using a custom function:
ol.interaction.MouseWheelZoom.handleEvent = myFunction(evt){
// here you set the layers to invisible and set the new map zoom level
// based on the event's wheel value...
}
After that in the 'zoomend' event handler you make the layers visible. If you just use buttons to zoom in/out then it's easy to hide/show the layers.
It worked for me and it is a good workaround in some situations.
Try:
function zoomChanged() {
zoom = map.getZoom();
if (zoom >=15) {
graphicsLayer.setVisibility(true);
}
else if (zoom < 15) {
graphicsLayer.setVisibility(false);
}
}
And then call that function using:
map.events.register("zoomend", map, zoomChanged);
Where "map" is the variable of your map initialization. Combined, these toggle a layer's visibility on and off based on your zoom level. If that's not exactly what you're going for, you could use a different indicator in the if/else block. I think you were just missing the event handler.
maybe you can do this one.
But, sorry if this can't help you.
function showGraphic () {
$('#Graphic1').hide();
$('#Graphic2').show(2000);
$('#Graphic3').hide();
$('#Graphic4').hide();
}
I have most of a module written to handle multitouch pinch, pan and zoom on an HTML 5 canvas element. I will share it below. I've been developing in JavaScript for some time now, and this one continues to boggle me. If anybody has any insights, I will post the final version up on stack for everybody to share once it is confirmed working on my iPad.
Here is what I am doing:
touchmove events trigger the changing of variables. I use these variables to change the way in which my image is painted onto the canvas. I have eight variables, each corresponding to the options that can be put into the drawImage() function. These eight variables get updated through functions that increment/decrement their values and keep them within a certain range. The variables are closure variables, so they are global throughout my module. To prevent over-processing, I make a call to this drawImage() function once every 40ms while the user has their finger pressed to the screen using a setInterval().
Here is the problem:
touchmove events seem to be causing a race condition where my variables get updated by many different instances of that same event. I can somewhat confirm this through my console output, that tracks one variable that is bounded to never reach below 20. When I swipe in one direction quickly, that variable dips down far below 20. Then when I release my finger, swipe slowly, it returns to 20. Another thing that points me in this direction, when I look at these variables while stepping through my program, they differ from what my console.log() pumps out.
Note: The code successfully draws the image the first time, but not anytime thereafter. A basic rendition of my code is below... The full version is on GitHub inside the Scripts folder. It is a Sencha Touch v1.1 app at heart
function PinchPanZoomFile(config)
{
/*
* Closure variable declaration here...
* Canvas Declaration here...
*/
function handleTouchStart(e) {
whatDown.oneDown = (e.originalEvent.targetTouches.length == 1) ? true : false;
whatDown.twoDown = (e.originalEvent.targetTouches.length >= 2) ? true : false;
drawInterval = setInterval(draw, 100);
}
function handleTouchEnd(e) {
whatDown.oneDown = (e.originalEvent.targetTouches.length == 1) ? true : false;
whatDown.twoDown = (e.originalEvent.targetTouches.length >= 2) ? true : false;
clearInterval(drawInterval);
}
function handleTouchMove(e) {
if(whatDown.twoDown) {
/*
* Do Panning & Zooming
*/
changeWindowXBy(deltaDistance); //deltaDistance
changeWindowYBy(deltaDistance); //deltaDistance
changeCanvasXBy(deltaX); //Pan
changeCanvasYBy(deltaY); //Pan
changeWindowDimsBy(deltaDistance*-1,deltaDistance*-1); //(deltaDistance)*-1 -- get smaller when zooming in.
changeCanvasWindowDimsBy(deltaDistance,deltaDistance); //deltaDistance -- get bigger when zooming in
} else if(whatDown.oneDown) {
/*
* Do Panning
*/
changeWindowXBy(0);
changeWindowYBy(0);
changeCanvasXBy(deltaX);
changeCanvasYBy(deltaY);
changeWindowDimsBy(0,0);
changeCanvasWindowDimsBy(0,0);
}
}
function draw() {
//Draw Image Off Screen
var offScreenCtx = offScreenCanvas[0].getContext('2d');
offScreenCtx.save();
offScreenCtx.clearRect(0, 0, canvasWidth, canvasHeight);
offScreenCtx.restore();
offScreenCtx.drawImage(base64Image,
parseInt(windowX),
parseInt(windowY),
parseInt(windowWidth),
parseInt(windowHeight),
parseInt(canvasX),
parseInt(canvasY),
parseInt(canvasWindowWidth),
parseInt(canvasWindowHeight)
);
//Draw Image On Screen
var offScreenImageData = offScreenCtx.getImageData(0, 0, canvasWidth, canvasHeight);
var onScreenCtx = canvas[0].getContext('2d');
onScreenCtx.putImageData(offScreenImageData, 0, 0);
}
}
I strongly recommend using Sencha Touch 2.0.1, as it supports a lot of the touch events you need. See http://dev.sencha.com/deploy/touch/examples/production/kitchensink/#demo/touchevents for examples.