i have added the draw interaction to draw free hand polygon by default freehandCondition is SHIFT key but how can we draw if the map is opened in Mobile and Tablets.
drawOptions.type = 'Polygon';
this.draw = new ol.interaction.Draw(drawOptions);
this.draw.on('drawend', lang.hitch(this, "drawEnd"));
How can we draw? is their any other condition i can give?
There are several ways to suspend drag pan and enable free-hand drawing in OL3. Here is one way to set the freeHandCondition (where the variable shapeGeom is Point, LineString or Polygon):
function drawInteraction() {
if (shapeGeom == 'Point') {
draw = new ol.interaction.Draw({
features: drawfeature,
type: shapeGeom,
})
} else {
draw = new ol.interaction.Draw({
features: drawfeature,
type: shapeGeom,
freehandCondition: ol.events.condition.always,
condition: ol.events.condition.never,
})
}
map.addInteraction(draw);
}
When you start the draw action, suspend DragPan.
map.getInteractions().forEach(function(interaction) {
if (interaction instanceof ol.interaction.DragPan) {
interaction.setActive(false);
}
}, this);
Then, restore DragPan when the feature has been drawn.
draw.on('drawend', function(event){
map.addInteraction(new ol.interaction.DragPan)});
OL3's API docs have information for both the freeHandCondition and DragPan elements with these links.
Related
I am trying to add a draw interaction to my map. The user should click a button, add one point and then add attribute information about the point. I'm still stuck in the drawing part: After I draw a point in the map, the cursor position remains the same and mouse movements change the map in the background (like when panning). When I click again this stops. No idea why it's doing this. In the console in Chrome I get an error in the draw.js file from openlayers (this.source_.addFeature is not a function).
Grateful for any help!
Here's my code:
function addFeature() {
var btn_cancel = document.getElementById('buttonCancel');
btn_cancel.style.display = 'block';
var btn_add = document.getElementById('buttonAdd');
btn_add.classList.add("button_clicked");
var draw;
function addInteraction() {
draw = new ol.interaction.Draw({
source: lunchvec,
type: "Point",
});
map.addInteraction(draw);
draw.on('drawend', function(evt) {
console.log(evt.feature.getGeometry().getCoordinates());
map.removeInteraction(draw);
});
};
addInteraction();
}
I want leaflet to work offline, without title, to show only a grid as titles. To have all the features of Leaflet, add plugins to draw a line, pin a marker, draw a polygon, zoom in / zoom out on shapes etc.
Is there a simple way to show just a simple grid?
Here's a custom GridLayer (that's already been implemented by the Leaflet authors). All you have to do is copy L.GridLayer.DebugCoords where you would normally load a tile layer.
var map = L.map('map', {
center: [0, 0],
zoom: 0
});
L.GridLayer.DebugCoords = L.GridLayer.extend({
createTile: function (coords, done) {
var tile = document.createElement('div');
//this adds tile coordinates; you may or may not want this
tile.innerHTML = [coords.x, coords.y, coords.z].join(', ');
tile.style.outline = '1px solid red';
/* // you don't need this artificial timeout for your application
setTimeout(function () {
done(null, tile); // Syntax is 'done(error, tile)'
}, 500 + Math.random() * 1500);
*/
return tile;
}
});
L.gridLayer.debugCoords = function(opts) {
return new L.GridLayer.DebugCoords(opts);
};
map.addLayer( L.gridLayer.debugCoords() );
Stand-alone, working example: http://leafletjs.com/examples/extending/gridcoords.html
Code taken from: http://leafletjs.com/examples/extending/extending-2-layers.html
I want to finish drawing when releasing mouse button and not on double click. How can I achieve that?
Right now I use this code to activate freehand drawing on Openlayers drawing feature by default:
draw = new ol.interaction.Draw({
source: drawLayerSource,
type: 'LineString',
condition: ol.events.condition.singleClick,
freehandCondition: ol.events.condition.noModifierKeys
});
map.addInteraction(draw);
But I don't know how to avoid double click to finish the line string and use mouse release instead.
UPDATE - https://jsfiddle.net/jonataswalker/frwfuzzn/
To enable both freehand and straight lines, I'm calculating the elapsed time between the drawing start and pointerup with this function:
var isStraightLine = function(){
var now = new Date();
// `start_time` was set at the drawing beginning
var diff = now - start_time;
// strip the ms
diff /= 1000;
already_checked = true;
// an average time I found here
// not sure if this is completely reliable
return diff < 0.07;
};
If I find this is a freehand drawing finish with draw.finishDrawing(). Better check the code for the sake of understanding.
I could but only if you stay with freehandCondition default condition - ol.events.condition.shiftKeyOnly.
Listen to pointerup on ol.Map and if you are drawing, finish with ol.interaction.Draw#finishDrawing.
var start_drawing = false;
var draw = new ol.interaction.Draw({
source: vectorSource,
type: 'LineString',
condition: ol.events.condition.singleClick
});
map.addInteraction(draw);
draw.on('drawstart', function(evt){
start_drawing = true;
});
draw.on('drawend', function(evt){
start_drawing = false;
});
map.on('pointerup', function(evt){
if(start_drawing) {
draw.finishDrawing();
}
});
http://jsfiddle.net/jonataswalker/ewv0mo3c/
I'm building a drawing board app in JavaScript using the Kinetic.js library. I'm having an issue with performance in the code I implemented for freehand drawing. Basically, I create an invisible rectangle that is the size of the stage, then attach event handlers to it to determine where to place the drawn line. Each time the mouse moves with the left-click button held down, I add the mouse coordinated to an array and use the points in that array to map my line. There is about a one second delay between the mouse movement and the line actually being rendered. I'm not sure if this delay is caused by an error in my own code or limitations in the Kinetic library. Here is the code:
Whiteboard.prototype.initializeDrawings = function() {
// Create an invisible shape that will act as an event listener
var background = new Kinetic.Rect({
x: 0,
y: 0,
width: this.stage.getWidth(),
height: this.stage.getHeight(),
});
this.mouseDrag = false;
// Attach handlers
background.on('mousedown touchstart', function(e) {
this.mouseDrag = true;
this.currentLine = [];
});
// Save a copy of whiteboard instance
var wb = this;
background.on('mousemove touchmove', function(e) {
if(this.mouseDrag === true) {
this.currentLine.push([e.clientX, e.clientY]);
wb.userDrawings.clear();
wb.userDrawings.add(new Kinetic.Line({
points: this.currentLine,
stroke: 'red',
strokeWidth: 4,
lineCap: 'round',
lineJoin: 'round'
}));
wb.stage.add(wb.userDrawings);
}
});
background.on('mouseup touchstop', function(e) {
this.mouseDrag = false;
});
this.stage.add(new Kinetic.Layer().add(background));
};
Overall, the code works, but because of the requirements for this application, I need to significantly minimize the delay between moving the mouse and rendering the path.
You don't want to be creating a new Kinetic.Line with every mousemove...
To gain better performance:
Instead of creating a new Kinetic.Line with every mousemove, create a single new Line in the mousedown handler and add points to that existing line in mousemove.
// a var which will eventually hold a Kinetic.Line (in your class or in global scope)
var myExistingLine;
// in mousedown
myExistingLine=new Kinetic.Line({ ...
// in mousemove
currentLine.push([mouseX,mouseY]);
myExistingLine.setPoints(currentLine);
myExistingLine.draw(); // or layer.drawScene();
To squeeze maximum performance:
Create a Kinetic.Shape which gives you access to a wrapped canvas context. Let the user draw their polyline on that context. After the user has created their polyline you can put those points in a new Kinetic.Line to get the benefits of a "managed" polyline--and remove the Kinetic.Shape.
So i'm making this application with leafet.js.
This application requires that i have to manually draw grids onto the screen,
that i've taken care in a draw_grid() function that draws a bunch of polygons to the screen.
i have this function that i'm calling to trigger the change of the leaflet map.
zoom - the zoom integer and size is a dict like {x:1,y:1} that controls the size of the tiles drawn onto the map. (they need to change as the units the tiles are being drawn under are lat,long points on the map.
function changeZoom(zoom,size){
map.setZoom(zoom);
setSize(size);
setTimeout(drawGrid,500)s;
}
the reason i have to use the setTimeout is because the leaflet ignores any drawing commands onto the map (which i'm doing as a layer) until the map has finished animating.
how to do this asynchronously instead?
You can use the map.zoomend event, described in the API here
map.on('zoomend', function() {
drawGrid();
});
Once the map finishes the zooming animation, it will then call the drawGrid function.
In newer version of Leaflet, "zoomed" is no longer an event. There are now "zoomstart" and "zoomend" events:
map.on("zoomstart", function (e) { console.log("ZOOMSTART", e); });
map.on("zoomend", function (e) { console.log("ZOOMEND", e); });
This is best way to managed leflet Zoom control clicked
/*Zoom Control Click Managed*/
var bZoomControlClick = false;
mymap.on('zoomend',function(e){
var currZoom = mymap.getZoom();
if(bZoomControlClick){
console.log("Clicked "+currZoom);
}
bZoomControlClick = false;
});
var element = document.querySelector('a.leaflet-control-zoom-in');
L.DomEvent.addListener(element, 'click', function (e) {
bZoomControlClick = true;
$(mymap).trigger("zoomend");
});
var element1 = document.querySelector('a.leaflet-control-zoom-out');
L.DomEvent.addListener(element1, 'click', function (e) {
bZoomControlClick = true;
$(mymap).trigger("zoomend");
});