When adding a stroke to a Konva polygon (Line with closed: = true), half the width of the stroke is added to the size of the polygon.
Example: https://codesandbox.io/s/loving-kirch-8692q
This is a problem, when there are two touching polygons, since the two strokes overlap.
Is there a way to prevent this?
That is how strokes work in 2d canvas API. The workaround is to make a polygon smaller by half of the stroke size:
const strokeWidth = 5;
const halfStroke = strokeWidth / 2;
const poly1 = new Konva.Line({
points: [
10 + halfStroke,
10 + halfStroke,
10 + halfStroke,
50 - halfStroke,
50 - halfStroke,
50 - halfStroke,
50 - halfStroke,
10 + halfStroke
],
fill: "#00D2FF",
stroke: "black",
strokeWidth: 5,
closed: true
});
Demo: https://codesandbox.io/s/konva-stroke-9okr6
I found a solution using globalCompositeOperation. An example can be found here.
Related
I am using Konva.js to render some colourful boxes.
I have a Stage with some set size and regions within that Stage, bound by points (e.g. rectangles, but they can be any polygons).
I then need to add some number of smaller rects inside this area such that they look nice and are uniformly distributed.
E.g.
// these numbers are an example only, irrelevant
let width = 500 * 1.936402653140851;
let height = 500;
// setup stage, boilerplate
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
// region layer - boundaries
var regionLayer = new Konva.Layer({
scale: {x: width/4963, y: height/2563} // these numbers are an example only, irrelevant
});
stage.add(regionLayer);
// for this example, a single region, L-shaped on it's side
let box = new Konva.Line({
name: 'region-1',
points: [1067, 681,
3337, 681,
3337, 987,
3037, 987,
3037, 787,
1067, 787],
closed: true,
fill: 'blue',
opacity: 0.5
});
regionLayer.add(box);
regionLayer.draw();
// layer to draw rects in
let rectsLayer = new Konva.Layer({
scale: {x: width/4963, y: height/2563} // these numbers are an example only, irrelevant
});
for (let i = 0; i < 90; i++) { // e.g. some number up to X
let rect = new Konva.Rect({
width: 20,
height: 20,
fill: 'red',
x: 1067 + 40 * (i + 1),
y: 681 + 20
});
rectsLayer.add(rect);
}
stage.add(rectsLayer);
rectsLayer.draw();
The result of the above is something like this
What I'd like to have, is those boxes filling free area within the boundaries of my polygon only.
I read a whole heap about Delauney triangulation, Voronoi diagrams and sequencing for normal distribution to make it happen, but sadly I came up with zilch on practical approach of doing this.
https://jsfiddle.net/x4aksz1y/2/
In this example, I tried to move the points by points.graphic.translate(0, -25), but it can't help to move point's label and SVGs. You can see the details in the example.
events: {
load() {
var chart = this,
series = chart.series[0];
series.points.forEach(function(point) {
point.graphic.translate(0, -25);
});
}
}
You need to move each element separately.
Label:
point.dataLabel.text.translate(0, -25)
And custom image just after rendering it:
points.forEach(function(point) {
point.customImg = chartt.renderer.image(
'https://www.highcharts.com/images/employees2014/Torstein.jpg',
point.plotX + chartt.plotLeft + point.shapeArgs.width / 2 - width / 2,
point.plotY + chartt.plotTop - height / 2,
width,
height
)
.attr({
zIndex: 5
})
.add();
point.customImg.translate(0, -25)
});
Demo: https://jsfiddle.net/BlackLabel/05hmufxa/
I want to put some images as SVG on each point in Gantt chart, I've tried something like below:
function (chartt) { // on complete
chartt.renderer.image('imageURL.png',100,100,30,30)
.add();
}
But after running this code, the image will be shown on the corner of the page. I want to draw images on each point in the chart and set their position related to its point.
Live Demo: https://jsfiddle.net/meysamm22/x41wdu5z/
You need to use the right x and y attributes, calculate them based on plotX and plotY point's properties:
function(chartt) { // on complete
var points = chartt.series[0].points,
width = 30,
height = 30;
points.forEach(function(point) {
chartt.renderer.image(
'https://www.highcharts.com/images/employees2014/Torstein.jpg',
point.plotX + chartt.plotLeft + point.shapeArgs.width / 2 - width / 2,
point.plotY + chartt.plotTop - height / 2,
width,
height
)
.attr({
zIndex: 5
})
.add();
});
});
Live demo: https://jsfiddle.net/BlackLabel/r4ph3ykz/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#image
I need to make rounded-perpendicular lines with react-konva, is it achievable using existing APIs? If yes, how?
I used bezier API for Line class, it works great. Somehow now I need to revamp the bezier curve to be rounded-perpendicular lines.
Sth like this:
There are many ways you can implement it. You can use tension to create curved lines or use lineCap property.
But to have more control it is better to create a custom shape.
const RADIUS = 20;
const Line = ({ points }) => {
return (
<Shape
points={points}
sceneFunc={(context, shape) => {
const width = points[1].x - points[0].x;
const height = points[1].y - points[0].y;
const dir = Math.sign(height);
const radius = Math.min(RADIUS, Math.abs(height / 2), Math.abs(width / 2));
context.beginPath();
context.moveTo(points[0].x, points[0].y);
context.lineTo(points[0].x + width / 2 - RADIUS, points[0].y);
context.quadraticCurveTo(
points[0].x + width / 2,
points[0].y,
points[0].x + width / 2,
points[0].y + dir * radius
);
context.lineTo(points[0].x + width / 2, points[1].y - dir * radius);
context.quadraticCurveTo(
points[0].x + width / 2,
points[1].y,
points[0].x + width / 2 + radius,
points[1].y
);
context.lineTo(points[1].x, points[1].y);
context.fillStrokeShape(shape);
}}
stroke="black"
strokeWidth={2}
/>
);
};
Demo: https://codesandbox.io/s/757nw05p6
I'm working with Highcharts spider web chart at the moment and wanted to see if I can do the following
How do I zoom polar charts? (or is it possible?)
How do I put background-color in each of the segment?
How do I zoom polar charts? (or is it possible?)
If you want a zoom like zoomType then no. zoomType is disabled for polar charts by highcharts-more.js. From source:
// Disable certain features on angular and polar axes
chart.inverted = false;
chartOptions.chart.zoomType = null;
How do I put background-color in each of the segment?
You can use math and Chart.renderer to create and fill paths to color the background of the segments. For example you might do it like this:
var colors = [ "pink", "yellow", "blue", "red", "green", "cyan", "teal", "indigo" ];
var parts = 6;
for(var i = 0; i < parts; i++) {
centerX = chart.plotLeft + chart.yAxis[0].center[0];
centerY = chart.plotTop + chart.yAxis[0].center[1];
axisLength = chart.yAxis[0].height;
angleOffset = -Math.PI/2;
angleSegment = Math.PI/(parts/2);
firstPointX = centerX + (axisLength * Math.cos(angleOffset + (angleSegment * i)));
firstPointY = centerY + (axisLength * Math.sin(angleOffset + (angleSegment * i)));
secondPointX = centerX + (axisLength * Math.cos(angleOffset + (angleSegment * (i+1))));
secondPointY = centerY + (axisLength * Math.sin(angleOffset + (angleSegment * (i+1))));
chart.renderer.path([
'M', centerX, centerY,
'L', firstPointX, firstPointY,
'L', secondPointX, secondPointY,
'Z'
]).attr({
fill: colors[i % colors.length],
'stroke-width': 1,
'opacity': 1
}).add();
}
As seen in this JSFiddle demonstration. You just have to match number of categories with the parts variable.