I have tried to get it to display but it just shows me the html formatting not the map. In the script part when a simple map display code is entered it displays the map but when any other function is added it stops functioning. I haven't been able to recreate what is available on this page: https://openlayers.org/en/latest/examples/draw-and-modify-features.html
Please help
The sample map code that displays correctly:
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([37.41, 8.82]),
zoom: 4
})
});
The code that doesn't work
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.4.3/css/ol.css" type="text/css">
<title>Draw and Modify Features</title>
<!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
<script src="https://unpkg.com/elm-pep"></script>
<style>
.map {
width: 100%;
height: 400px;
}
</style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.4.3/build/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<form class="form-inline">
<label>Geometry type </label>
<select id="type">
<option value="Point">Point</option>
<option value="LineString">LineString</option>
<option value="Polygon">Polygon</option>
<option value="Circle">Circle</option>
</select>
</form>
<script type="text/javascript">
var raster = new TileLayer({
source: new OSM(),
});
var source = new VectorSource();
var vector = new VectorLayer({
source: source,
style: new Style({
fill: new Fill({
color: 'rgba(255, 255, 255, 0.2)',
}),
stroke: new Stroke({
color: '#ffcc33',
width: 2,
}),
image: new CircleStyle({
radius: 7,
fill: new Fill({
color: '#ffcc33',
}),
}),
}),
});
var map = new Map({
layers: [raster, vector],
target: 'map',
view: new View({
center: [-11000000, 4600000],
zoom: 4,
}),
});
var modify = new Modify({ source: source });
map.addInteraction(modify);
var draw, snap; // global so we can remove them later
var typeSelect = document.getElementById('type');
function addInteractions() {
draw = new Draw({
source: source,
type: typeSelect.value,
});
map.addInteraction(draw);
snap = new Snap({ source: source });
map.addInteraction(snap);
}
/**
* Handle change event.
*/
typeSelect.onchange = function () {
map.removeInteraction(draw);
map.removeInteraction(snap);
addInteractions();
};
addInteractions();
</script>
</body>
</html>
In your case you need to use syntax as Mike pointed out.
Example: instead of this
var raster = new TileLayer({
source: new OSM(),
});
you should use full build syntax
var raster = new ol.layer.Tile({
source: new ol.source.OSM(),
});
Or just copy past Mike's solution above
this line:
var raster = new TileLayer({
source: new OSM(),
});
and that should do the trick
A quick way to make module syntax code work with the full build to define the equivalent variable names at the start of your code
var TileLayer = ol.layer.Tile;
var OSM = ol.source.OSM;
var VectorSource = ol.source.Vector;
var VectorLayer = ol.layer.Vector;
var Style = ol.style.Style;
var Fill = ol.style.Fill;
var Stroke = ol.style.Stroke;
var CircleStyle = ol.style.Circle;
var Map = ol.Map;
var View = ol.View;
var Modify = ol.interaction.Modify;
var Draw = ol.interaction.Draw;
var Snap = ol.interaction.Snap;
With this example :
https://openlayers.org/en/latest/examples/draw-and-modify-features.html
I try to create a polygon but I want it to disappear when the polygon is complete.
Can someone help me ?
Thanks :)
Just remove the source when creating the interaction:
draw = new Draw({
type: 'Polygon'
});
When no destination source for the drawn features is set, the polygon will just disappear when completed (otherwise it is added to the source).
Listen to drawend event to get the polygon.
If I understand you correctly, you want to remove the draw interaction after the user geometry draw is complete. Like #Anatoly mention in the comments you can use the drawend event to remove the interactions.
Take a look at the example I made for you,
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.3.1/css/ol.css" type="text/css">
<style>
.map {
height: 400px;
width: 100%;
}
</style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.3.1/build/ol.js"></script>
<title>End Draw Interaction After Draw</title>
</head>
<body>
<div>
<button id="startDraw">Start Draw</button>
<button id="endDraw">End Draw</button>
</div>
<div id="map" class="map"></div>
<script type="text/javascript">
// vector layer
var source = new ol.source.Vector();
var vector = new ol.layer.Vector({
source: source,
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)'
}),
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
})
})
});
// map
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vector
],
view: new ol.View({
center: ol.proj.fromLonLat([37.41, 8.82]),
zoom: 4
})
});
// buttons
var startDrawBtn = document.getElementById('startDraw');
var endDrawBtn = document.getElementById('endDraw');
endDrawBtn.disabled = true;
// interaction
var draw = new ol.interaction.Draw({
source: source,
type: 'Polygon'
});
var snap = new ol.interaction.Snap({source: source});
function endInteractions() {
map.removeInteraction(draw);
map.removeInteraction(snap);
startDrawBtn.disabled = false;
endDrawBtn.disabled = true;
}
function startInteractions() {
startDrawBtn.disabled = true;
endDrawBtn.disabled = false;
map.addInteraction(draw);
map.addInteraction(snap);
draw.on('drawend', evt => {
// console.log(evt.feature);
endInteractions();
});
}
startDrawBtn.addEventListener('click', startInteractions);
endDrawBtn.addEventListener('click', endInteractions);
</script>
</body>
</html>
Suppose you have a 2d array like the ones often used to organise tile maps, 1 represents solid tiles.
var map = [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,1,1,1,1,1,1,0,0,0,0,0],
[0,0,0,0,1,1,1,1,1,1,0,0,0,0,0],
[0,0,0,0,1,1,1,1,1,1,0,0,0,0,0],
[0,0,0,0,1,1,1,1,1,1,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
];
Instead of square tiles, I want to convert this shape in to points of a polygon. Each 1 in the array would have a set width and height like a tile map, but I only want the corner points necessary to recreate the shape as a solid polygon. I also want diagonal slopes instead of a step-like effect when the 1's are diagonal like in the array. I've played around and searched for an answer but I can't figure out the best way to do this, any ideas?
Thanks.
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.1.min.js"></script>
<script defer="defer">
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var poly = new Kinetic.Line({
points: [73, 192, 73, 160, 340, 23, 500, 109, 499, 139, 342, 93],
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 5,
closed: true
});
// add the shape to the layer
layer.add(poly);
// add the layer to the stage
stage.add(layer);
</script>
</body>
</html>
You could put those points you want in the points array ,and use kinetic js for ur project.
Link : http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-polygon-tutorial/
I am attempting to use kinetic.js with an existing canvas. The problem is that the kinetic.js API requires that you specify the id of the container element and then kinetic.js creates a Kinetic.Stage (which creates and uses its own canvas).
For instance:
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 239,
y: 75,
width: 100,
height: 50,
fill: 'green',
stroke: 'black',
strokeWidth: 4
});
// add the shape to the layer
layer.add(rect);
// add the layer to the stage
stage.add(layer);
</script>
I want to be able to use an existing canvas element with kinetic.js instead of it creating its own. Is this possible?
A similar question has been asked before, however it doesn't seem to provide a correct answer.
Any ideas? Thanks!
An html canvas is just a bunch of pixels.
You can convert those pixels into an image and then use that image as the source for a Kinetic.Image.
// create an image from the existing canvas
var canvas2Image=new Image();
canvas2Image.onload=function(){
// create a Kinetic.Image using that image
var kImage=new Kinetic.Image({
x:0,
y:0,
width:canvas2Image.width,
height:canvas2Image.height,
image:canvas2Image
});
}
canvas2Image.src=canvas.toDataURL();
I want to draw multiple figures on a canvas on different button clicks.
HTML
<body>
<div id="container">
</div>
<div id="option">
<button value="rect" onclick="rect();">rect</button>
<button value="circle" onclick="circle();">circle</button>
</div>
</body>
Javascript:
var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 500
});
var layer = new Kinetic.Layer();
function rect(){
var redLine = new Kinetic.Line({
points: [100, 5, 100, 300, 450,300],
stroke: 'black',
strokeWidth: 3,
lineCap: 'square',
lineJoin: 'mitter'
});
// add the shape to the layer
layer.add(redLine);
// add the layer to the stage
stage.add(layer);
}
function circle(){
var wedge = new Kinetic.Wedge({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
angleDeg: 60,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
rotationDeg: -120
});
// add the shape to the layer
layer.add(wedge);
// add the layer to the stage
stage.add(layer);
}
But it gives error as layer and stage are not defined. How do I solve it ?
The reasons that stage and layer would not be defined are that either they are outside of scope, or your code is breaking before they are instantiated in the first place.
First, make sure that your stage and layer are outside of any functions; global scope.
Second, your functions 'circle()' and 'rect()' are being called with the button click, which I suspect is breaking your code. You want to remove this onclick handler from inline:
<button value="circle" onclick="circle();">circle</button>
and assign onclick using javascript, after you have created your stage. You can assign handlers easily using jQuery. So your code should look something like:
HTML
<button value="rect" id='rect'>rect</button> //assign an id to your button
JS
var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 500
});
var layer = new Kinetic.Layer();
$('#yourButtonId').click(function(){ // button id here would be '#rect' if you use the id above
rect();
});