access svg element in a arearange HighCharts chart - svg

The last line of the following code (brutally copied from a HighCharts demo chart page) changes the opacity of a arearange series:
var chart=Highcharts.chart('container', {
series: [{
name: 'Temperature',
data: averages,
zIndex: 1,
marker: {
fillColor: 'white',
lineWidth: 2,
lineColor: Highcharts.getOptions().colors[0]
}
}, {
name: 'Range',
data: ranges,
type: 'arearange',
lineWidth: 0,
linkedTo: ':previous',
color: Highcharts.getOptions().colors[0],
fillOpacity: 0.3,
zIndex: 0,
marker: {
enabled: false
}
}]
});
chart.series[1].update({fillOpacity:0.7},true);
JSFiddle here.
(the opacity could be set directly inside the chart object, but I need to modify it after the chart creation, the code is a toy example to simulate my needs)
My real chart has several arearange series, and updating them is heavy. Is there a way to modify such property avoiding the .update method? that it, is there a way to directly access the svg element corresponding to the arearange series?
I've tried to check the series .graph property, as previously suggested in an answer to a similar question, but in this case arearange series has no .graph property.

It can be done exactly the same as in the answer mentioned in your question but instead of modifying the graph you have to modify the area property.
Code:
chart.series[1].area.attr({
fill: 'rgba(124,181,236,0.7)'
});
Demo:
https://jsfiddle.net/BlackLabel/abohcq4x/

Related

A graph with multiple scales/Y-axes

I have a line graph that I would like to have two different Y-axes (this is usually accomplished by having one set of labels on the left, and one on the right). So I can have two different types of related data on the same graph, but with different scales. Is this possible with RGraph?
<canvas id="cvs" width="750" height="250" style="border: 1px solid #ccc">[No canvas support]</canvas>
<script>
data = [4,8,6,8,6,3,5];
data2 = [15,18,14,24,35,22,31];
new RGraph.Line({
id: 'cvs',
data: data,
options: {
spline: true,
marginInner: 10,
xaxis: false,
yaxis: false,
colors:['blue']
}
}).draw();
new RGraph.Line({
id: 'cvs',
data: data2,
options: {
spline: true,
marginInner: 10,
xaxis: false,
yaxis: false,
backgroundGrid: false,
yaxisPosition: 'right'
}
}).draw();
</script>
Richard (the developer) helped me out. To achieve this, you combine two graphs, giving each graph the same ID target. The second graph will be written over the first. Which means, if everything lines up, there will be (what looks like) a single graph, just be sure everything lines up between the two (margins, labels, etc.).
The code is the example Richard gave me.

noUiSlider - Place Both Tooltips above Slider?

Is it possible to specify the position of the tooltips that noUiSlider draws? It appears that by default it places the first one over the slider, and the second below. I understand the usability goal here, but I'd like to put both above or below.
Example (with tooltips above and below): http://jsfiddle.net/leongersen/z83oz9np/2/
noUiSlider.create(div, {
start: [0, 50], // 2 handles
range: {
'min': 0,
'max': 50
},
tooltips: true // 2 tooltips but how to position?
});
I don't believe there is an option to specify the position of the labels. In the css version you're using there's
.noUi-horizontal .noUi-handle-upper .noUi-tooltip {
bottom:-32px
}
Which you can override to be the same as the other label:
.noUi-horizontal .noUi-handle-upper .noUi-tooltip {
top: -32px;
bottom: initial;
}
See your updated fiddle: http://jsfiddle.net/z83oz9np/20/
Think that's the best thing to do here. In the latest version on github I've noted this styling is missing, so take this into account if you ever update it.
You can overwrite the attribute "bottom" from the css class ".noUi-horizontal .noUi-tooltip"
for example to do the tooltip go below the slider:
.noUi-horizontal .noUi-tooltip {bottom: -130%;}
For others that find themselves here, this will give you more consistent positioning than negative pixel positioning:
.noUi-vertical .noUi-handle-upper .noUi-tooltip {
right: unset;
left: 120%;
}
This removes the right: 120%; from the tooltip and repositions it with respect to the left, like the bottom tooltip.
for me none of this solution worked so I ended up with my own:
.noUi-horizontal .noUi-tooltip
{
left: unset !important;
}
.noUi-target
{
direction: unset !important;
}
done.

How to add an image to an element as a decorator?

Imagine I have Rect element and I wish to decorate it with a small (say 16x16) PNG image in the upper left. I am unable to determine how to achieve that task. I have studied the docs but have (so far) been unable to find a sample or reference on how to achieve that task. Does anyone have a recipe or a sample pointer that they would be willing to share to help me achieve my goal?
Better is to create your own custom shape that has a rectangle, image and text. This gives you much more flexibility and you don't have to have two elements in order to express one shape. Your shape decorated with a little image in the top left corner may look like:
joint.shapes.basic.DecoratedRect = joint.shapes.basic.Generic.extend({
markup: '<g class="rotatable"><g class="scalable"><rect/></g><image/><text/></g>',
defaults: joint.util.deepSupplement({
type: 'basic.DecoratedRect',
size: { width: 100, height: 60 },
attrs: {
'rect': { fill: '#FFFFFF', stroke: 'black', width: 100, height: 60 },
'text': { 'font-size': 14, text: '', 'ref-x': .5, 'ref-y': .5, ref: 'rect', 'y-alignment': 'middle', 'x-alignment': 'middle', fill: 'black' },
'image': { 'ref-x': 2, 'ref-y': 2, ref: 'rect', width: 16, height: 16 }
}
}, joint.shapes.basic.Generic.prototype.defaults)
});
And you can use it like this in your diagrams:
var decoratedRect = new joint.shapes.basic.DecoratedRect({
position: { x: 150, y: 80 },
size: { width: 100, height: 60 },
attrs: {
text: { text: 'My Element' },
image: { 'xlink:href': 'http://placehold.it/16x16' }
}
});
graph.addCell(decoratedRect);
Note how is the shape specified, the important bits are the markup, type and the attrs object that references the SVG elements in the markup by normal CSS selectors (here just tag selectors but you can use classes if you want). For the image tag, we take advantage of the JointJS special attributes for relative positioning (ref, ref-x and ref-y). With these attributes, we position the image relatively to the top left corner of the rect element and we offset it by 2px from the top edge (ref-y) and 2px from the left edge (ref-x).
One note: It is important that the type attribute ('basic.DecoratedRect') matches the namespace the shape is defined in (joint.shapes.basic.DecoratedRect). This is because when JointJS re-constructs graphs from JSON, it looks at the type attribute and makes a simple lookup to the joint.shapes namespace to see if there is a shape defined for this type.
We can create an element type for an image using the following recipe:
var image = new joint.shapes.basic.Image({
position : {
x : 100,
y : 100
},
size : {
width : 16,
height : 16
},
attrs : {
image : {
"xlink:href" : "images/myImage.png",
width : 16,
height : 16
}
}
});
graph.addCell(image);
This will position the image at x=100,y=100. It is important to make the size width/height match the attrs/image width/height and be the width/height of the image itself.
Although this doesn't decorate a previous element, it can be positioned over a previous element achieving the desired effect.

SVG text scales inproperly

I use Ext.daw.* to draw svg text. The root element has size 200x300.
If some element has larger size than size of root element then everything scales properly except the text: text appears to have larger size.
Check out this demo. How to make text scale properly?
Ext.create('Ext.draw.Component', {
renderTo: Ext.getBody(),
width: 200,
height: 300,
items: [{
type: 'path',
path: 'M0 0 V200',
'stroke-width': 3,
stroke: 'green'
},{
type: 'path',
// if I set path to 'M200 0 V700' then text goes crazy
path: 'M200 0 V200',
'stroke-width': 3,
stroke: 'green'
},{
type: 'text',
x: 0,
y: 50,
// text is located accurately between two lines
// but when one of the lines exceeds size of the canvas
// text's size changes
text: 'wwwwwwwwwwwwwwwwwww',
font: "18px monospace"
}]
});
Text is subject to hinting and kerning that happen differently at different point sizes and so does not normally scale uniformly. There is a hint available to indicate you would like this overridden:
text-rendering="geometricPrecision"
Changing your code to
},{
type: 'text',
x: 0,
y: 50,
text: 'wwwwwwwwwwwwwwwwwww',
'text-rendering': 'geometricPrecision',
font: "17px monospace"
}]
Should make it work more like you want it too, although it will display less clearly at small point sizes.

Can't get an svg to animate

I imported an SVG from InkScape using the ReadySetRaphael tool. I wanted to animate the svg, and ease it in. So just for test purposes, i tried to transform it using the animate method.
I keep getting an error to say my object doesnt have a method of "animate". I've checked other SO answers which suggest i have to clone the object and set the final path, but not sure if that does, or how it applies to me?
Here's my js code so far.
//code created using readysetraphael. Original svg made in inkscape.
var rsr = Raphael('rsr', '744.09448', '1052.3622');
var layer1 = rsr.set();
var path2993 = rsr.path("m 344.93716,348.36218 c 0,0 34.17415,-33.06016 -1.26571,-83.92195 -35.43985,-50.86178 39.23699,-38.14634 6.32855,-91.55121 -32.90844,-53.40487 -50.62837,-36.8748 -50.62837,-36.8748 -9.49282,-0.63577 -8.85996,-0.63577 -8.85996,-0.63577");
path2993.attr({
id: 'path2993',
parent: 'layer1',
fill: 'none',
stroke: '#cf0000',
"stroke-width": '2.92',
"stroke-linecap": 'butt',
"stroke-linejoin": 'miter',
"stroke-miterlimit": '4',
"stroke-opacity": '1',
"stroke-dasharray": 'none',
"marker-start": 'none',
"marker-mid": 'none',
"marker-end": 'url(#TriangleInL)'
}).data('id', 'path2993');
layer1.attr({
'id': 'layer1',
'name': 'layer1'
});
var rsrGroups = [layer1];
//Animate svg
rsr.animate({
transform: 's2'
}, 2000);
Your code pulls an animation call over the paper object. As animate() is a member of Element, the call fails.
I assume you're trying to animate a specific shape, e.g. path2993. Simply call it on the relevant element instead:
path2993.animate({transform: 's2'}, 2000);

Resources