I need some help for the handles in the navigator of highstock.
My set options do not work in my example:
http://jsfiddle.net/q1xpn6hL/
Please take a look at line 5 to 9:
borderColor: '#666',
width: 10,
height: 35,
borderRadius: 2,
borderWidth: 0.5
thanks a lot!
Those options are not supported. You would have to extend Highcharts to enable them. It is possible to override function that handles creating of handles.
Example: http://jsfiddle.net/v4vhy01j/
(function (H) {
H.wrap(H.Scroller.prototype, 'drawHandle', function (proceed, x, index) {
var scroller = this,
chart = scroller.chart,
renderer = chart.renderer,
elementsToDestroy = scroller.elementsToDestroy,
handles = scroller.handles,
handlesOptions = scroller.navigatorOptions.handles,
borderWidth = H.pick(handlesOptions.borderWidth, 1),
borderRadius = H.pick(handlesOptions.borderRadius, 0),
width = H.pick(handlesOptions.width, 9),
height = H.pick(handlesOptions.height, 16),
attr = {
fill: handlesOptions.backgroundColor,
stroke: handlesOptions.borderColor,
'stroke-width': borderWidth
},
tempElem;
// create the elements
if (!scroller.rendered) {
// the group
handles[index] = renderer.g('navigator-handle-' + ['left', 'right'][index])
.css({
cursor: 'ew-resize'
})
.attr({
zIndex: 4 - index
}) // zIndex = 3 for right handle, 4 for left
.add();
// the rectangle
tempElem = renderer.rect(-5, 9 - height/2, width, height, borderRadius)
.attr(attr)
.add(handles[index]);
elementsToDestroy.push(tempElem);
// the rifles
tempElem = renderer.path([
'M', -1.5, 13 - height/2,
'L', -1.5, 5 + height/2,
'M',
0.5, 13 - height/2,
'L',
0.5, 5 + height/2]).attr(attr)
.add(handles[index]);
elementsToDestroy.push(tempElem);
}
// Place it
handles[index][chart.isResizing ? 'animate' : 'attr']({
translateX: scroller.scrollerLeft + scroller.scrollbarHeight + parseInt(x, 10),
translateY: scroller.top + scroller.height / 2 - 8
});
});
}(Highcharts));
The Highstock navigator does not support all those options. Here's what the documentation says:
handles: Object
Options for the handles for dragging the zoomed area. Available options are backgroundColor (defaults to #ebe7e8) and borderColor (defaults to #b2b1b6).
Related
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'm trying to add text (TextPath) inside an Arc shape, that is following the curve of en Arc. Making a curved TextPath is easy, however I'm failing to put it on top on Arc shape.
If I set x and y of both objects to for.ex. 100 and 100, they end up in illogical locations, so I'm obviously failing to understand something here. What I'm trying to achieve is shown in attached screenshot - could someone make demo of putting a TextPath on top of en Arc ? Thanks.
what I'm trying to achieve
I slightly modified your demo to remove hardcoded values as much as possible.
You just need to correctly generate an SVG path. You can use some answers from here: How to calculate the SVG Path for an arc (of a circle)
Also, you can use Konva.Path shape to debug the generated path.
function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;
return {
x: centerX + (radius * Math.cos(angleInRadians)),
y: centerY + (radius * Math.sin(angleInRadians))
};
}
function describeArc(x, y, radius, startAngle, endAngle){
var endAngleOriginal = endAngle;
if(endAngleOriginal - startAngle === 360){
endAngle = 359;
}
var start = polarToCartesian(x, y, radius, endAngle);
var end = polarToCartesian(x, y, radius, startAngle);
var arcSweep = endAngle - startAngle <= 180 ? "0" : "1";
if(endAngleOriginal - startAngle === 360){
var d = [
"M", start.x, start.y,
"A", radius, radius, 0, arcSweep, 0, end.x, end.y, "z"
].join(" ");
}
else{
var d = [
"M", start.x, start.y,
"A", radius, radius, 0, arcSweep, 0, end.x, end.y
].join(" ");
}
return d;
}
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Konva.Layer();
stage.add(layer);
var arc = new Konva.Arc({
x: 250,
y: 250,
innerRadius: 100,
outerRadius: 170,
angle: 260,
rotation: 0,
draggable: true,
fill: 'yellow',
stroke: 'black',
strokeWidth: 4,
offset: 0,
});
layer.add(arc);
var tr1 = new Konva.Transformer({
node: arc,
resizeEnabled: false
});
layer.add(tr1);
var txt = new Konva.TextPath({
x: arc.x(),
y: arc.y(),
draggable: true,
fill: '#333',
fontSize: 22,
fontFamily: 'Arial',
text: "Hello world !",
align: 'center',
data: describeArc(0, 0, (arc.innerRadius() + arc.outerRadius()) / 2, 90, 90 + arc.getAttr("angle")),
});
layer.add(txt);
var tr2 = new Konva.Transformer({
node: txt,
resizeEnabled: false,
});
layer.add(tr2);
const path = new Konva.Path({
x: txt.x(),
y: txt.y(),
data: txt.data(),
stroke: 'red'
});
layer.add(path);
layer.draw();
Demo: https://jsbin.com/muwobaxipe/3/edit?js,output
I have an app where I am panning and zooming multiple layers.
However, when I set the position of the layers they are being updated to the wrong values.
For instance, after calling:
layer.position({
x: 12,
y: 233,
});
I would expect
layer.getClientRect();
to return
{
x: 12,
y: 233,
}
Instead it returns
{
x: -22,
y: 220,
}
Is there any known reason this is happening?
I realised I wasn't taking into account all the offsets. The x position of a circle is set from the centre while getClientRect() returns the width and height including negatives. So getClientRect() on a circle with a radius of 50 and x of 0 will actually return {x: -25, y: -25, width: 50, height: 50}.
Seems to work for me as advertised in this cut down test. Did you move the stage or something ?
In the snippet below I draw a layer with 4 'corner' rects, display its value from grtClientRect() in 'Layer pos #1' which gives (0, 0), then move the stage to 12, 233 and display its value from grtClientRect() in 'Layer pos #2' which shows (12, 233). I move the layer back up to (12, 23) just for fun thereafter.
var stage = new Konva.Stage({
container: 'container',
width: 1600,
height: 400
});
// add a layer
var layer = new Konva.Layer();
stage.add(layer);
// add 4 corner rects - code I happened to have to hand
var rectCorner = [];
for (i=0;i<4;i=i+1){
rectCorner[i] = new Konva.Rect({
x: 0,
y: 0,
width: 50,
height: 50,
fill: 'red',
opacity: 0.5,
strokeWidth: 0})
layer.add(rectCorner[i]);
}
// put the rects in the corners to give a known layer space
rectCorner[1].position({x:500, y: 0});
rectCorner[2].position({x:500, y: 150});
rectCorner[3].position({x:0, y: 150});
layer.draw();
// get the client rect now
var p = layer.getClientRect();
$('#info1').html('Layer pos #1=' + p.x + ', ' + p.y);
// move the layer...
layer.position({
x: 12,
y: 233,
});
// get the client rect now
var p = layer.getClientRect();
$('#info2').html('Layer pos #2=' + p.x + ', ' + p.y);
// move the layer back to the top...
layer.position({
x: 12,
y: 23,
});
stage.draw();
p
{
padding: 4px;
}
#container
{
background-color: silver;
overflow: hidden;
}
<div id='info1'></div>
<div id='info2'></div>
<div id="container"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/konvajs/konva/1.7.6/konva.min.js"></script>
<script type="text/javascript" src="test.js"></script>
How would you achieve this (jsFiddle link)
dynamically for the Highcharts "Activity Gauge", so obviously it works there but I had to manually determine the correct x & y coordinates for the labels.
This result is similar to using the "inside" property for column charts, but seems nothing is built-in like that for this chart type (that I've run across at least). One could come close by passing in the same y values as for each series as tick marks on the y-axis (see snippet below) and getting rid of all markings except the number, but then I can't stagger those to be positioned correctly within each series, and for the dataLabel x & y approach I don't know the equation to be able to position the labels based on the series y values dynamically with a callback.
yAxis: {
labels: {
enabled: true,
x: 10, y: -15,
format: '{value} %',
style: {
fontSize: 16,
color: 'black'
}
},
min: 0,
max: 100,
gridLineColor: 'transparent',
lineColor: 'transparent',
minorTickLength: 0,
//tickInterval: 67,
tickPositions: [50, 65, 80], //TRIED TO USE Y-AXIS LABELS BUT COULDN'T STAGGER THEM
tickColor: '#000000',
tickPosition: 'inside',
//tickLength: 50,
tickWidth: 0
},
Any help would be much appreciated, thanks in advance.
Solved via Highcharts support forum:
fiddle
, just call the following function on chart load and redraw events:
function redrawConnectors() {
var chart = this,
cX, cY,
shapeArgs, ang, posX, posY, bBox;
Highcharts.each(chart.series, function(series, j) {
Highcharts.each(series.points, function(point, i) {
if (point.dataLabel) {
bBox = point.dataLabel.getBBox();
shapeArgs = point.shapeArgs;
cX = shapeArgs.x,
cY = shapeArgs.y,
ang = shapeArgs.end;
posX = cX + shapeArgs.r * Math.cos(ang);
posY = cY + shapeArgs.r * Math.sin(ang);
point.dataLabel.attr({
x: posX - bBox.width / 2,
y: posY - bBox.height / 2
});
}
});
});
}
Is there any way to increase the height of the handles in the highstock navigator component? Right now, the only options available are to change the color and the border-color. How about the height and width of the handles?
http://api.highcharts.com/highstock#navigator.handles
Thanks,
Vikas.
You can wrap drawHandles function and modify it to have increased height.
var height = 20;
(function (H) {
H.wrap(H.Scroller.prototype, 'drawHandle', function (proceed, x, index) {
var scroller = this,
chart = scroller.chart,
renderer = chart.renderer,
elementsToDestroy = scroller.elementsToDestroy,
handles = scroller.handles,
handlesOptions = scroller.navigatorOptions.handles,
attr = {
fill: handlesOptions.backgroundColor,
stroke: handlesOptions.borderColor,
'stroke-width': 1
},
tempElem;
// create the elements
if (!scroller.rendered) {
// the group
handles[index] = renderer.g('navigator-handle-' + ['left', 'right'][index])
.css({
cursor: 'e-resize'
})
.attr({
zIndex: 4 - index
}) // zIndex = 3 for right handle, 4 for left
.add();
// the rectangle
tempElem = renderer.rect(-4.5, 0, 9, height, 0, 1)
.attr(attr)
.add(handles[index]);
elementsToDestroy.push(tempElem);
// the rifles
tempElem = renderer.path([
'M', -1.5, 4,
'L', -1.5, 12,
'M',
0.5, 4,
'L',
0.5, 12]).attr(attr)
.add(handles[index]);
elementsToDestroy.push(tempElem);
}
// Place it
handles[index][chart.isResizing ? 'animate' : 'attr']({
translateX: scroller.scrollerLeft + scroller.scrollbarHeight + parseInt(x, 10),
translateY: scroller.top + scroller.height / 2 - 8
});
});
}(Highcharts));
http://jsfiddle.net/za68w54r/
There is an option for increasing the height of the navigator too..
Check this fiddle:
http://jsfiddle.net/gh/get/jquery/1.7.2/highslide-software/highcharts.com/tree/master/samples/stock/navigator/height/
Code:
navigator: {
height: 100
},