I currently have an Openlayers 3 integration with many updating features, these make the scrolling stutter, especially when the 'kinetic' movement (flick scroll) is used. Is there a way to turn that smooth scrolling with inertia off so the user has to drag to move the map?
Removing the animation on zoom would help too.
I've been looking in the ol.animation area for these - is that the right place?
The kinetic can be turned off in the ol.interaction.DragPan interaction. Removing the animation while zooming can be done by passing duration: 0 to the ol.interaction.MouseWheelZoom.
See a live example here: http://jsfiddle.net/9v6fd6as/1/
Here's the example source code:
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
interactions: ol.interaction.defaults({
dragPan: false,
mouseWheelZoom: false
}).extend([
new ol.interaction.DragPan({kinetic: false}),
new ol.interaction.MouseWheelZoom({duration: 0})
]),
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
Above answer from Alexandre Dube is correct for older versions of openlayers.
If you're using OpenLayers 6+ with TypeScript, this is how you can disable animated panning:
import Interaction from "ol/interaction/Interaction";
import DragPan from "ol/interaction/DragPan";
import {defaults as defaultInteractions} from 'ol/interaction.js';
import {Kinetic} from "ol";
// ...
ngOnInit() {
this.map = new Map({
//...
interactions: defaultInteractions({
dragPan: false
}).extend([new DragPan({kinetic: new Kinetic(0, 0, 0)})]),
//...
});
}
Related
Mapbox GL JS allows you define custom layers that can use tools like Three.js to achieve effects that are impossible using the built-in layer types such as fill-extrusion.
Custom and built-in layer types can be mixed and matched. Here's a red cube rendered with Three.js in front of a 50% transparent green fill-extrusion layer:
This looks fine until I spin around and look at the red Three.js cube behind the green fill-extrusion layer:
While the red Three.js cube is rendered behnd the green fill-extrusion layer, there's a strange visual effect where you can't see the cube behind the transparent fill-extrusions. Instead, you see straight through it to the background map.
Is it possible get custom layers working as you'd expect with transparent fill-extrusion layers? Here's a codepen for this example using some of the code from this question.
const x = -74.0445;
const y = 40.6892;
const map = new mapboxgl.Map({ /* ... */ });
map.on('load', () => {
map.addSource('boxes', { type: 'geojson', data: { /* ... */ }})
map.addLayer({
id: 'boxes',
type: 'fill-extrusion',
source: 'boxes',
paint: {
'fill-extrusion-color': 'green',
'fill-extrusion-base': ['get', 'min_height'],
'fill-extrusion-height': ['get', 'height'],
'fill-extrusion-vertical-gradient': false,
'fill-extrusion-opacity': 0.5,
}
});
});
class BoxCustomLayer { /* ... see codepen link ... */ }
let boxLayer = new BoxCustomLayer('box')
map.on('load', () => {
map.addLayer(boxLayer);
});
I'm trying to make a scene where there's a "hole in the wall".
This requires a plane with square removed, and then a material applied to the plane with the following properties:
Invisible to the camera
Hides any other objects from being rendered that are behind it
There's an example of this with three.js here, but how can I do it with the a-frame material syntax?
The "Mask".
Looking at the box-hole example, to create the illusion, Lee creates two boxes.
1) The box which is "in the hole"
2) A slightly bigger invisible box without a top - to cloak the first one. The top is removed to work as a "hole" through which you can see the first box
How it can be done in THREE.js
The cloaking is done by preventing the second box from rendering any color. From Lee's example:
let material = new THREE.MeshBasicMaterial({
colorWrite: false;
})
The docs state, that the flag can be used to create invisible objects hiding others.
How it can be done in a-frame
I'm afraid you can't simply make the "cloak" material in a-frame. The colorWrite property is not exposed in the material component.
What i think the simplest way would be - is creating a cloak component, which will create the second box in THREE.js:
AFRAME.registerComponent('cloak', {
init: function() {
let geometry = new THREE.BoxGeometry(1, 1, 1)
geometry.faces.splice(4, 2) // cut out the top faces
let material = new THREE.MeshBasicMaterial({
colorWrite: false
})
let mesh = new THREE.Mesh(geometry, material)
mesh.scale.set(1.1, 1.1, 1.1)
this.el.object3D.add(mesh)
}
})
and use it like this:
<a-box material="src: myPic.png; side: back;" cloak>
Check it out in this codepen. With a HIRO marker, you should get a hole like this:
Using models, or other objects as "cloaks"
Here we need to apply the colorWrite=false magic to each node/child of the model.
init: function() {
// make sure the model is loaded first
this.el.addEventListener('model-loaded', e=>{
let mesh = this.el.getObject3D('mesh') // grab the mesh
if (mesh === undefined) return; // return if no mesh :(
mesh.traverse(function(node) { // traverse through and apply settings
if (node.isMesh && node.material) { // make sure the element can be a cloak
node.material.colorWrite = false
node.material.needsUpdate = true;
}
});
})
}
Also make sure the cloak is rendered before the elements that needs cloaking:
<a-marker>
<a-entity gltf-model="#wall-with-a-hole" cloak-component></a-entity>
<!-- the other stuff that needs to be cloaked-->
</a-marker
I used a useful bug in older OL5, now it was fixed and I seaching again for a solution since weeks...
My wish with the ZoomSlider is to stay at the step between the integer zooming levels. When I click on the Slider it moves e.g. from 16 to 17. My Polygon in the View may a little bit bigger than I need. Then I move the Sliderbutton a little bit and the View ist perfect - but as I leave the mousebutton the Sliderbutton jumps to the nearest level...
The bug in the past, there I could leave the Sliderbutton to left or right and the perfect View stood at the step between the levels (but the view did't refresh in this state, but most time this view was ok for me; I printed this view).
Now sadly this bug is fixed... - so I search a possibility to reach the steps between the levels again.
I tried with combinations (surely wrong) of constainResolution false/true, pinchZoom false/true, zoomDelta or delta values between 0.5 and 2 ... nothing helps and after searching in API, google, .. and trying a lot, I'm very confused now.
I don't understand the meaning of "pinch" (normally I speak German; in the dictionary there are so much meanings for this word...) - because I don't see any change, neither I set pinchZoom to true nor set to false...
Is there any solution for "hold view between the Zoom Level"?
I cannot find any earlier version of OpenLayers where ZoomSlider works as you described.
One workaround would be to set the view zoom factor very small to create many more zoom levels and set the delta options on the zoom button control and interactions correspondingly large so they continue to work at normal zoom levels.
e.g. to divide each normal zoom level into 100 zoom levels:
var zoomFactorDelta = 100;
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
controls: ol.control.defaults({
zoomOptions: { delta: zoomFactorDelta }
}).extend([
new ol.control.ZoomSlider()
]),
interactions: ol.interaction.defaults({
zoomDelta: zoomFactorDelta
}),
keyboardEventTarget: document,
view: new ol.View({
center: ol.proj.fromLonLat( [8, 50] ),
zoomFactor: Math.pow(2,1/zoomFactorDelta),
zoom: 10 * zoomFactorDelta,
maxZoom: 20 * zoomFactorDelta
})
});
However, while the zoomDelta setting works as expected for keyboard and double click zooms, it doesn't have any effect on mousewheel zoom (despite the documentation description "Zoom level delta when using keyboard or mousewheel zoom"), making mousewheel zoom 100 times slower than before. An alternative which keeps mousewheel zoom working at normal speed is to redefine the view's constrainResolution function to multiply the default delta parameter:
var zoomFactorDelta = 100;
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
controls: ol.control.defaults().extend([
new ol.control.ZoomSlider()
]),
keyboardEventTarget: document,
view: new ol.View({
center: ol.proj.fromLonLat( [8, 50] ),
zoomFactor: Math.pow(2,1/zoomFactorDelta),
zoom: 10 * zoomFactorDelta,
maxZoom: 20 * zoomFactorDelta
})
});
var view = map.getView();
var defaultConstrainResolution = view.constrainResolution.bind(view);
view.constrainResolution = function(resolution, delta, direction) {
return defaultConstrainResolution(resolution, delta*zoomFactorDelta, direction)
};
This workaround using only an override of the constrainResolution function also works, but it might have side effects elsewhere:
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
controls: ol.control.defaults().extend([
new ol.control.ZoomSlider()
]),
keyboardEventTarget: document,
view: new ol.View({
center: ol.proj.fromLonLat( [8, 50] ),
zoom: 10
})
});
var view = map.getView();
var defaultConstrainResolution = view.constrainResolution.bind(view);
view.constrainResolution = function(resolution, delta, direction) {
return Math.abs(delta) > 0 ? defaultConstrainResolution(resolution, delta, direction)
: resolution;
};
I am trying to create a web app using React VR and run it using Samsung Gear VR.
I could not see the default white dot (VR pointer) while in VR mode in my scene. Consequently methods such as "onInput" and "onClick" are not working. The same methods work quite fine if I view the same scene outside VR mode - even using the browser provided in Gear VR.
Am I missing something? How do I access those methods while in VR mode in Gear VR?
Example code that works fine in normal web browser (including the one in Gear VR), but not when I am in VR.
<Text
style={{
// backgroundColor: '#777879',
fontSize: 0.2,
transform: [{translate: [0, 0, -5]}],
color: this.state.textColor
}}
onEnter={() => this.setState({textColor: 'gold'})}
onExit={() => this.setState({textColor: 'white'})}>
This text will turn gold when you look at it.
</Text>
You need to add a raycaster:
To do so, you need to do the following:
In your project, go to <project root>/vr/client.js.
Just before the init method, add a SimpleRaycaster constant.
const SimpleRaycaster = {
getType: () => "simple",
getRayOrigin: () => [0, 0, 0],
getRayDirection: () => [0, 0, -1],
drawsCursor: () => true
};
function init(bundle, parent, options) {
//...
Then, in the init method, set cursorVisibility: visible and add the raycaster to the array of raycasters:
function init(bundle, parent, options) {
const vr = new VRInstance(bundle, 'Example', parent, {
raycasters: [
SimpleRaycaster // Add SimpleRaycaster to the options
],
cursorVisibility: "visible", // Add cursorVisibility
enableHotReload: true,
...options,
});
vr.render = function() {
// Any custom behavior you want to perform on each frame goes here
};
// Begin the animation loop
vr.start();
return vr;
}
window.ReactVR = {init};
That's it. Now you should have a white dot in the middle of your view.
I'm having trouble trying to add a polygon to the map by clicking something outside of the map area, e.g. a text link on the same page as the map.
I can add the polygon by clicking on the map via the addListener method but the same code with addDomListener doesn't work. Was wondering if anyone knows how to do this correctly?
My code that is not working (i get the alert test so the listener is working but the polygon is not added to the map):
google.maps.event.addDomListener(document.getElementById('thediv'), 'click',function (event){
drawPolygon();
alert("test");
});
The code that is working but not what I want (polygon is drawn and alert test is received):
google.maps.event.addListener(map, 'click',function (event){
drawPolygon();
alert("test");
});
and the drawPolygon code which works:
function drawPolygon(){
var bermudaTriangle;
var triangleCoords = [
new google.maps.LatLng(25.774252, -80.190262),
new google.maps.LatLng(18.466465, -66.118292),
new google.maps.LatLng(32.321384, -64.75737),
new google.maps.LatLng(25.774252, -80.190262)
];
bermudaTriangle = new google.maps.Polygon({
paths: triangleCoords,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35
});
bermudaTriangle.setMap(map);
}