OpenLayers draw line string with line width in meters - openlayers-3

Want to draw Line string with line width measured in meters
Tried styles but they are fixed width(in pixels) and don't change line thickness while zooming
Thanks in advance

If anybody is interested:
function() {
return [
new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(0,0,0,1)',
width: 50 / ol.map.getView().getResolution()
})
})
]
}
You can provide a function which returns a ol.style.Style instead of using a ol.style.Style directly (e.g. with setStyle).
This function is called within every single render process and you can change the width of a ol.style.Stroke dynamically.
In the case above a line is drawn, where the width should represent 50 meters in the real world if you use the Web Mercator projection (EPSG:3857).

Try use Polygon, or after drawend change Line to Polygon.

Related

What is the best way to drag a transformer by dragging from empty areas in Konvajs?

I'm currently following this guide to select shapes in the stage and put them inside a Transformer.
If possible, I'd like to drag an entire Transformer with all of its content without touching any of the shapes inside.
For example, I have two lines that are far from each other. Both of them are nodes inside a Transformer and can be dragged as long as I click one of those 2 lines. However, if I tried to drag from any of the empty area inside the Transformer nothing would happen (or the transformer would reset, depending on the code).
I'm thinking of adding a transparent Rect (this Rect will always have the same size as the Transformer) to the Transformer and then add any other shape that I want inside the Transformer. Since both the Rect and the Transformer have the same size, I could easily drag the entire Transformer from any "empty area" where my other shapes are not located.
I'm not sure if this is the correct/efficient way to do it. How should I tackle this issue to obtain the best outcome?
There is an experimental property shouldOverdrawWholeArea for Konva.Transformer. It is not in the docs yet.
If you set it to true the whole transformer area will be available for drag.
But if you have a transformer on top of other shapes, then shapes will be not listening for regular events (such as click, touchstart etc). Because the transformer rectangle will overdraw hit area of attached shapes. Even will start working as soon, as you remove such a transformer from them.
const stage = new Konva.Stage({
container: 'container',
width: window.innerWidth - 20,
height: window.innerHeight - 20
});
const layer = new Konva.Layer();
stage.add(layer);
const shape1 = new Konva.Circle({
x: 70,
y: 70,
radius: 50,
fill: 'green'
});
layer.add(shape1);
const shape2 = shape1.clone({
x: 190,
y: 90
})
layer.add(shape2);
const tr = new Konva.Transformer({
nodes: [shape1, shape2],
shouldOverdrawWholeArea: true
});
layer.add(tr);
layer.draw();
<script src="https://unpkg.com/konva#7.0.3/konva.min.js"></script>
<div id="container"></div>

Konvajs custom shapes and transformers

What I am trying to achieve is showing the transformer around the custom shape itself. I took the code directly from the API docs for creating the custom shape and adding the transformer. The transformer works great for rectangles, circles, etc but for custom shapes, it doesn't seem to appear properly.
Here is a link to a demo app with the issue with custom shapes and transformer:
https://jsfiddle.net/5zpua740/
var stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
});
var layer = new Konva.Layer();
/*
* create a triangle shape by defining a
* drawing function which draws a triangle
*/
var triangle = new Konva.Shape({
sceneFunc: function (context) {
context.beginPath();
context.moveTo(120, 150);
context.lineTo(320, 180);
context.quadraticCurveTo(250, 200, 360, 270);
context.closePath();
// Konva specific method
context.fillStrokeShape(this);
},
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 4,
draggable: true
});
// add the triangle shape to the layer
layer.add(triangle);
// add the layer to the stage
stage.add(layer);
stage.on('click', function (e) {
// if click on empty area - remove all transformers
if (e.target === stage) {
stage.find('Transformer').destroy();
layer.draw();
return;
}
// remove old transformers
// TODO: we can skip it if current rect is already selected
stage.find('Transformer').destroy();
// create new transformer
var tr = new Konva.Transformer();
layer.add(tr);
tr.attachTo(e.target);
layer.draw();
})
In this sample, you can see that if you click on the object, the transformer appears in the corner. You can still use it to manipulate the object but it's not around the object itself.
Any help appreciated! Thanks in advance.
Konva can't detect bounding box of a custom shape. But we can simply help it. We just need to define a method getSelfRect.
The method should return bounding box of a shape without transforming applied (like the shape has no rotation, no scaling and placed in x =0, y=0).
We can do this by just looking at sceneFunc:
triangle.getSelfRect = function() {
return {
// sceneFunc started from moving to 120, 150 point
// so it is our top left point
x: 120,
y: 150,
// the bottom right point finished with quadraticCurveTo
// I will use the coordinates to calculate size of the shape
width: 360 - 120,
height: 270 - 150
};
}
Demo: http://jsbin.com/lazuhowezi/2/edit?js,output

where can i find a thorough description of implementing custom ol.style.Style in openlayers 3?

I've read through the source, and looked at the examples but haven't found the answer yet.
I need to style the image that appears on the modify overlay beneath the mouse cursor.
i'm using a custom style function to add midpoints and custom endpoints to the layer used by ol.interaction.Modify. ol.interaction.Modify is applying styling to a point near the mouse cursor to indicate that the feature can be modified. This is great except the cursor styling falls beneath the custom endpoints. i can't find a way to alter the z-index.
so, i'm answering my question for myself. i guess that's what makes the internet wonderful. i'm not a dog.
// we'd normally pass feature & resolution parameters to the function, but we're going to
// make this dynamic, so we'll return a style function for later use which will take those params.
DynamicStyleFunction = ( function( /* no feat/res yet!*/ ) {
/**
you really only get style are rendered upon simple geometries, not features. features are made of different geometry types, and styleFunctions are passed a feature that has its geometries rendered. in terms of styling vector geometries, you have only a few options. side note: if there's some feature you expect to see on the the map and it's not showing up, you probably haven't properly styled it. Or, maybe it hasn't been put it in a collection that is included in the source layer... which is a hiccup for a different day.
*/
// for any geometry that you want to be rendered, you'll want a style.
var styles = {};
var s = styles;
/**
an ol.layer.Vector or FeatureOverlay, renders those features in its source by applying Styles made of Strokes, Fills, and Images (made of strokes and fills) on top of the simple geometries which make up the features
Stroke styles get applied to ol.geom.GeometryType.LINE_STRING
MULTI_LINE_STRING can get different styling if you want
*/
var strokeLinesWhite = new ol.style.Stroke({
color: [255, 255, 255, 1], // white
width: 5,
})
var whiteLineStyle new ol.style.Style({
stroke: strokeLinesWhite
})
styles[ol.geom.GeometryType.LINE_STRING] = whiteLineStyle
/**
Polygon styles get applied to ol.geom.GeometryType.POLYGON
Polygons are gonna get filled. They also have Lines... so they can take stroke
*/
var fillPolygonBlue = new ol.style.Style({
fill: new ol.style.Fill({
color: [0, 153, 255, 1], // blue
})
})
var whiteOutlinedBluePolygon = new ol.style.Style({
stroke: strokeLinesWhite,
fill: fillPolygonBlue,
})
styles[ol.geom.GeometryType.POLYGON] = fillPolygonBlue
/**
Circle styles get applied to ol.geom.GeometryType.POINT
They're made with a radius and a fill, and the edge gets stroked...
*/
var smallRedCircleStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: '#FF0000', // red... but i had to look it up
})
})
})
var whiteBigCircleWithBlueBorderStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
fill: new ol.style.Fill({
color: '#FFFFFF' // i guessed it
})
}),
stroke: new.ol.style.Stroke({
color: '#0000FF', // blue
width: 5
})
})
// render all points as small red circles
styles[ol.geom.GeometryType.POINT] = smallRedCircleStyle
// if you pass an array as the style argument, every rendering of the feature will apply every defined style style rendered with the geometry as the argument. that can be a whole lot of rendering in a FeatureOverlay...
smallRedCircleStyle.setZIndex(Infinity)
whiteBigCircleWithBlueBorderStyle.setZIndex(Infinity -1) // that prob wouldn't work, but i hope it's instructive that you can tinker with styles
// so...
var bullseyePointStyle = [ smallRedCircleStyle, whiteBigCircleWithBlueBorderStyle ];
return function dynamicStyleFunction (feature, resolution){
// this is the actual function getting invoked on each function call
// do whatever you want with the feature/resolution.
if (Array.indexOf(feature.getKeys('thisIsOurBullseyeNode') > -1) {
return bullseyePointStyle
} else if (feature.getGeometryName('whiteBlueBox')){
return whiteOutlinedBluePolygon
} else {
return styles[feature.getGeometryName()]
}
}
})()
ol.interaction.Modify, ol.interaction.Select and ol.interaction.Draw take a style argument to change the look of the sketching features.

Highcharts - programmatically draw a line or graphic between two related points

I often have charts that require a design element like a curly brace to call attention to call attention to a range or comparison in a graph, such as the y-difference in two points at the end of a graph.
My first take is that this would be a job for Highcharts Renderer API. Load the graph, and run a callback that adds an image (or line, shape, whatever) via chart.renderer.image(...) or similar.
That's the approach I have started down, but I'm just missing how to get the coordinates for chart data points within the callback. Here's a working codepen of the code below. What doesn't work is that there's no logic to give it proper placement on the canvas (suppose I want the bracket to go from the final top point to the final bottom point)
$('#container').highcharts({
data: { table: document.getElementById('datatable') },
chart: { type: 'line' },
title: { text: 'Data extracted from a HTML table in the page'
}
}, function(chart){
var img = 'http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Curly_bracket_right.svg/30px-Curly_bracket_right.svg.png';
// How can I populate these values?
var x = 0; // should programmatically get x-position of last point
var y = 0; // should programmatically get y-position of last point
var h = 100; // should programmatically get distance between y-position of top and bottom points
var w = 50;
chart.renderer.image( img, x, y, w, h ).add();
});
Is there a straightforward way to populate those values? Or is there a better way to do this entirely?
to get the position you want you can use few methods provided by highcharts in their API.
methods like toPixels(), toValue() will help you to alter your required position as per the chart demogrphics.
please refer their api
toPixels() : http://api.highcharts.com/highcharts#Axis.toPixels()
toValue() : http://api.highcharts.com/highcharts#Axis.toValue()
hope using this will solve your requirement of positioning

Draw rectangle in the selection, Highcharts

I want to draw rectangle or square in selection area to show the selected xAxis min, max and yAxis min max in highchart.
Thanks in Advance
Explaining #igor-shastin's example...
Set zoomType to "xy"
Add a rect to the chart with 0 dimensions and hang onto the reference
In the selection event:
Grab the event.xAxis[0].min and .max; same for .yAxis
Update the rect coordinates so it renders where the selection was made
Return false and/or call event.preventDefault() to prevent actually zooming

Resources