Converting a 2d array to polygon points - javascript
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/
Related
Blending mode between konvajs and openlayers
I try to use blending mode between konvajs (https://konvajs.org/) and openlayers (https://openlayers.org/) I have a map created with openlayers, then I use Overlay (https://openlayers.org/en/latest/examples/overlay.html) of openlayers to add canvas konvajs on over the map. I've try: property globalCompositeOperation of konvajs, but it works only with items in konvajs css mix-blend-mode, but it all items in konvajs were stuck with the same mode, I want each items have different mode. Is there any way to achieve this? Here example code I tried with No.1 above: https://codesandbox.io/s/cool-monad-ow21j?file=/main.js
To help investigate how OpenLayer and Konvajs canvas might interact I created the below snippet. This draws an Openlayer map element then adds a Konvajs canvas element. Both are positioned absolute so that they overlap. I threw in some simple rectangles with varying opacity to illustrate the possibility in case that was all you really require. The image below shows the F12 inspector view of the elements. As we can see, label a points out that the OpenLayers element employs a dedicated canvas. Similarly, label b shows the Konvajs canvas. The conclusion is that these elements are indeed separate HTML5 canvas elements. Therefore the question switches to 'is it possible to use blend mode across canvasses?'. Fortunately this has been asked before. So, in answer to your question, 'Is there any way to achieve this [blend between OpenLayer and Konvajs] ?' the answer seems to be a definite maybe. However, looking at the potential approaches it would seem that you might lose some of the mouse/touch functionality of both of the canvas layers. // Create the map element 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([-1.1656, 51.0856]), zoom: 15 }) }); // Create the Konva element var stage = new Konva.Stage({container: 'container1', width: 600, height: 400}); var layer1 = new Konva.Layer(); stage.add(layer1); var rect = new Konva.Rect({x: 100, y: 25, width: 100, height: 50, fill: 'magenta', stroke: 'black', draggable: true }); layer1.add(rect); rect = new Konva.Rect({x: 200, y: 75, width: 100, height: 50, fill: 'magenta', stroke: 'black', draggable: true, opacity: 0.5 }); layer1.add(rect); rect = new Konva.Rect({x: 300, y: 125, width: 100, height: 50, fill: 'magenta', stroke: 'black', draggable: true, opacity: 0.25 }); layer1.add(rect); stage.draw(); .map { height: 400px; width: 100%; } <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.4.3/build/ol.js"></script> <script src="https://cdn.rawgit.com/konvajs/konva/1.6.5/konva.min.js"></script> <div id="map" class="map" style="left: 0; top: 0; width: 600px; height: 400px; background-color: transparent; position: absolute;"></div> <div id='container1' style="left: 0; top: 0; width: 600px; height: 400px; background-color: transparent; position: absolute;"></div>
Change position of leaflet label
I'd like to add labels to my leaflet-markers, and then position them above and horizontally centered for the marker icon. With the labelAnchor option in the Leaflet.label plugin I can manually adjust every label so that I get what I want, and for now I've added a fixed width to my labels so that I know the text will be centered. But there must be a better way to achieve this? http://jsfiddle.net/NYGvibeke/frUf4/3/ <style type="text/css"> .labeltext { width: 120px; text-align: center; border:none; } </style> <script type="text/javascript"> var myIcon = L.icon({ iconUrl: 'http://icons.iconarchive.com/icons/visualpharm/icons8-metro- style/512/Maps-and-Geolocation-Marker-icon.png', iconSize: [18, 30], iconAnchor: [10, 30], labelAnchor: [-80, -40] }); var layer = new L.StamenTileLayer("toner-lite", {maxZoom: 10}); var map = new L.Map("map", { center: new L.LatLng(30, 100), zoom: 4, maxZoom: 12, minZoom: 2 }); map.addLayer(layer); var marker1 = L.marker([25, 100], {icon: myIcon}).bindLabel('This is a label text', { noHide: true, className: 'labeltext'}).addTo(map); </script>
Change .labeltext { width: 120px} to .labeltext { width: auto} The auto value will dynamically size the width of the label. UPDATE Actually, that's only part of it. Here's the rest in a jsfiddle. Basically, you need to dynamically assign the position based on the number of characters. It takes a little bit of calibration (depending on font typeface/size), but here's what I came up with for labelAnchor: [-label[0].length*2.5-20, -40]
Selecting Kineticjs path by id
I am trying to create an interactive map and have been exploring with some of the prebuilt templates. In this each country is created and highlights when the mouse is over them. My question is how would I go about making it highlight another country such a Brazil when any country has a mouseover. Thus how do I go about selecting another object when a country is highlighted. <body> <div id="container"></div> <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.4.min.js"></script> <script src="http://riskmap.filkor.org/paths.js"></script> <script src="http://riskmap.filkor.org/gameData.js"></script> <script defer="defer"> var stage = new Kinetic.Stage({ container: 'container', width: 1920, height: 1080 }); var mapLayer = new Kinetic.Layer({ y: 20, scale: 1 }); var topLayer = new Kinetic.Layer({ y: 20, scale: 1 }); /* * loop through country data */ for(id in TerritoryNames) { var path = new Kinetic.Path({ data: TerritoryPathData[id].path, fill: '#eee', stroke: '#555', strokeWidth: 1, id: id }); path.on('mouseover', function() { this.setFill('#111'); this.moveTo(topLayer); topLayer.drawScene(); }); path.on('mouseout', function() { this.setFill('#eee'); this.moveTo(mapLayer); topLayer.draw(); }); mapLayer.add(path); } stage.add(mapLayer); stage.add(topLayer); </script>
At any time, you can get a reference to a country through its id using stage.find: var Brazil = stage.find("#Brazil")[0]; Then use that reference to highlight Brazil.
Make kineticjs use existing canvas
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();
Draw Multiple figures in a stage using Kineticjs?
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(); });