Highcharts multiple fill colors - javascript

I'm trying figuring out how to put every other with a brigther fill color for the same serie.
Please have a look at my reference, this is what I want to accomplish.
http://imgur.com/sYW8guR
FYI: Heres a simple area chart to save you time
http://jsfiddle.net/kylander/33cutjqn/

I don't see a way to do this without either using multiple series, or writing your own complex rendering script.
Another alternative for using 2 series that works a little different than the one proposed by Sebastian:
1) User the alternateGridColor
2) set the fillColor of your series with an appropriate opacity for the alternate grid color to have the desired effect
3) use a 2nd series, which can be automatically created, to stack on top of the main data series, filled with white to cover the alternating color in the 'open' space.
Example:
http://jsfiddle.net/jlbriggs/mg4vs1dm/
Honestly, I would personally simply opt to use the alternateGridColor option as is, however.

The simples way is using two series. http://jsfiddle.net/sbochan/gba46s7L/
series: [{
name: 'USA',
data: [1,2,3,2]
}, {
name: 'USSR/Russia',
data: [null,2,3]
}]

After playing a little bit with svg i found another solution to this.
Instead of defining color you may write
color: "url(#SomePattern)"
Define the pattern in separate svg like this
<div id="defs" style="width:0px;height:0px;">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="SomePattern"
width="50" height="50"
patternUnits="userSpaceOnUse">
<rect width='50' height='50' fill='#BDDEE8'/>
<rect x='25' width='25' height='50' fill='#D4E4E9'/>
</pattern>
</defs>
</svg>
</div>
and then insert with something like
$(".highcharts-container defs").append($("#pattern-container defs").html());
Here's a demo: http://jsfiddle.net/DrathVedro/33cutjqn/2/
However, it's just a texture and it's not bound to points like in your demo.

Try
xAxis.alternateGridColor
Docs:
http://api.highcharts.com/highcharts#xAxis.alternateGridColor

Related

SVG fill="url(#foo)" disappears when SVGs are loaded dynamically

I am loading different SVGs dynamically within a web application built in AngularJS, I am also altering the opacity of layers within the SVGs. These SVGs have some paths with the fill pattern property as such
<defs>
<pattern id="glass-floral" patternUnits="userSpaceOnUse" width="184" height="272">
<image xlink:href="../img/glass-floral.png" x="0" y="0" width="184" height="272"/>
</pattern>
</defs>
<rect x="98.3" y="85.5" fill="url(#glass-floral)" width="365" height="318.8"/>
This all works great at first- however under some conditions these # fills simply disappear:
-
Condition 1:
If I were to switch to another SVG and back.
Result::
The # fill is still visible.
-
Condition 2:
If I were to alter the opacity of the element with the # fill.
Result::
The # fill is still visible.
-
Condition 3:
If I were to both switch to another SVG & alter the opacity of the element with the # fill.
Result::
The # fill becomes invisible.
-
This is to mean the styles all appear to still be applied normally in the code- but there is no actual visible fill to be seen. This behaviour exists as far as I can see in Chrome and slightly differently in Safari. Firefox seems to be immune.
I've tried manually flicking the element to another fill and back in the browser to see if perhaps something had cached, no luck. I still think this may somehow be the case, with how the # refers to an inline pattern defined in the <defs> which may not have been loaded yet by the AJAX but the cached CSS rule still floating around.
If it helps matters, both SVGs that I am switching between both have the same <defs> and CSS styling applied. Is perhaps the double case of the defined pattern causing an issue?
After some investigation this appears to be an issue with the browsers (Chrome/Safari possibly others) not being able to keep up with rendering fill: url(#) and opacity for the same element at the same time, at least in cases of multiple/dynamically loaded SVGs.
To solve this, apply your opacity css to a containing element around the element that has the fill: url(#), example below:
<defs>
<pattern id="glass-floral" patternUnits="userSpaceOnUse" width="184" height="272">
<image xlink:href="../img/glass-floral.png" x="0" y="0" width="184" height="272"/>
</pattern>
</defs>
<style>.opacity-class { opacity: 0.33; }</style>
<g class="opacity-class">
<rect x="98.3" y="85.5" fill="url(#glass-floral)" width="365" height="318.8"/>
</g>
This allows the browser to do both independently and not ruin your pretty pictures.
I had multiple svg elements and problem was the same ID of all pattern tags. So, using different id="" for the pattern tag of each svg element solved my problem with disappearing fill="url()" on dynamic reload...

SVG filters and interpolated values

I am creating a visualization with d3.js, and the effect I would like to achieve relies on a filter using feFlood and feBlend. For each path in the visualization, I need to interpolate a different flood-opacity value for the feFlood filter primitive. The filter is pretty simple:
<filter id="multiplyOverlay" x="0" y="0" width="100%" height="100%">
<feFlood flood-color="steelblue" flood-opacity=".1" />
<feBlend mode="multiply" in2="SourceGraphic"/>
</filter>
I don't believe there is any way to pass a value in to the filter. Will I need to create a new filter for each path (about 200) in the visualization with the appropriate flood-opacity value? Or is there some other way to achieve this?
If you're going to use different flood-opacities then you'll need to do multiple filters (although using 200 different opacity settings seems like overkill). (If it's any help to you, flood-opacity is a property and can be styled via CSS.)
Addition: Also remember that you can animate things with the SMIL <animate> element - if that's why you're doing the interpolation

How can I dynamically update the patternTransform attribute for an SVG text

I have a simple text filled with a pattern like:
<svg>
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="690" height="200" patternTransform="translate(0,0) scale(1,1)">
<image xlink:href="http://lorempixel.com/690/200/" width="690" height="200"/>
</pattern>
</defs>
<text id='text1' y='200' fill='url(#img1)'>Hello</text>
</svg>
However I would like to dynamically update the pattern position through javascript.
I have tried to update through:
document.getElementById('img1').setAttribute('patternTransform', 'translate(0,200) scale(1,1)')
But it didn't work.
Your image seems to be a random bitmap which is 690 pixels wide and crucially 200 pixels high. When you change the pattern by calling this:
document.getElementById('img1').setAttribute('patternTransform', 'translate(0,200) scale(1,1)')
You move the pattern down by 200 pixels and patterns wrap around. Since this pattern is 200 pixels high, it wraps around so it looks exactly the same as it did before, like a runner in a race doing exactly one more lap looks like he's in the same position. Try using some other number than 200 and you'll see that the pattern does change.
Try this
$('#img1')[0].setAttribute('patternTransform', 'translate(0,200) scale(1,1)');
or
$('#img1').first().setAttribute('patternTransform', 'translate(0,200) scale(1,1)');

SVG Scaling and Coordinates

This is my first SVG project, and I’m not a programmer, but I dabble in interactive infographics. My previous experience in this area comes from working with ActionScript.
I’m using plain SVG (no Raphael, D3, etc.) and trying to create an interactive barchart. After some initial difficulty with the SVG coordinate system and scaling, I found some code online that handles the postscaling translation:
<text x="x_coord0" y="y_coord0" transform="scale(x_scale, y_scale) translate(-x_coord0*(x_scale-1)/x_scale, -y_coord0*(y_scale-1)/y_scale)" …>text</text>
And I converted it into this JavaScript:
var translationfactor = ((0 - y_position)*(y_scalefactor - 1) / y_scalefactor);
var matrix = "scale(1," + y_scalefactor + ") translate(0," + Number(translationfactor) + ")";
targetbar.setAttribute("transform", matrix);
The problem is that I need the bars “translated” back to the chart’s baseline, not the original locations of their topmost points. Currently the correctly scaled bars are hugging the top of the chart:
http://billgregg.net/miscellany/upsidedown-barchart.png
I’ve tried several fixes, including plugging the bars’ ”missing height” into translationfactor (the bars start out the full height of the chart and get scaled down dynamically). Nothing has worked. Part of my problem is that, besides being new to SVGs, I can stare at that code all day and my brain still can’t parse it. Multiplying negative numbers is too abstract and at a fundamental level I just don’t “get” the math, which of course makes modifying the code difficult.
My questions:
(1) What’s the fix for the code above to position the bars back on the baseline of the chart?
(2) Is there a more transparent, more pedestrian way of accomplishing the translation? My first thought along these lines was that if a bar’s height is reduced to 40% of its original value, then multiplying the original Y coordinate value by 250% should reset the bar to its original location (at least its topmost point), but that doesn’t seem to work.
(3) Is there a way to set a bar’s point of origin to its bottom? In Flash it’s possible, though as far as I know it’s a manual, not a programmatic task.
(4) Is there a method similar to .localToGlobal() in ActionScript that would allow me to avoid having to mess with the local coordinate system at all?
Behind the scenes there is matrix math going on and it can be hard to get your head around the pre and post multiplication of arrays.
It's not entirely clear what you are trying to achieve, but reading between the lines, it sounds like you are wanting to provide graph coordinates in their raw(ish) form and have the SVG scale and position them for you(?)
If that's the case, then I think the solution is simpler than what you think.
Assuming I'm right, we'll start with something that looks like this:
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<g transform="">
<rect x="0" width="1" height="5" fill="red"/>
<rect x="1" width="1" height="11" fill="green"/>
<rect x="2" width="1" height="12" fill="orange"/>
<rect x="3" width="1" height="8" fill="blue"/>
</g>
</svg>
Where x is obvious and the bar length is in height. y defaults to 0, so we don't need it here.
You basically want to know what goes in the transform to scale and position the bars on your page. The fact that your graph is "upside-down" helps a little. Because the origin in an SVG is at the top left.
First apply a scale. Let's make the bars 20 pixels wide, and scale the lengths up by 10.
<g transform="scale(20,10)">
Next you want to position the graph on the page. Let's put the top-left corner at (40,40).
In SVG the transformations are concatenated in order (post-multiplied) so in order for the translation to be what you specify and not be multiplied by the scale, you should put it first.
<g transform="translate(40,40) scale(20,10)">
So the final SVG looks like this:
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<g transform="translate(40,40) scale(20,10)">
<rect x="0" width="1" height="5" fill="red"/>
<rect x="1" width="1" height="11" fill="green"/>
<rect x="2" width="1" height="12" fill="orange"/>
<rect x="3" width="1" height="8" fill="blue"/>
</g>
</svg>
The above has been simplified by assuming you have already subtracted the values from your base 20%. If you wanted to keep the pure raw values, it's possible, but things get a bit trickier. You would need to either tinker with both the y and height value of each bar, or use clipping to hide the part of the bar above 20%.
For "right way up"/normal graphs. All you need to do is make the y scale negative and translate the graph so that the bottom-left is where you want it.
<g transform="translate(40,140) scale(20,-10)">
Hope this helps.

Trying to create a re-usable text-box (text with a square background-colour) in SVG 1.1?

I'm trying to create (what I thought would be!) a simple re-usable bit of SVG to show three lines of text, with a background colour - to simulate a 'post-it' note.
I have found some useful code here to get the Bounds of the Text http://my.opera.com/MacDev_ed/blog/2009/01/21/getting-boundingbox-of-svg-elements which I am using.
So: I'm creating an group of text elements like this in the 'defs' section of my SVG:
<svg id="canvas" width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="post_it">
<text x="0" y="30" id="heading" class="heading">My Heading</text>
<text x="0" y="45" id="description" class="description">This will contain the description</text>
<text x="0" y="60" id="company" class="company">Very Big Company Ltd.</text>
</g>
And I'm displaying the text with a 'use' element like this:
<use id="12345" class="postit" xlink:href="#post_it" onclick="showId(this);"/>
I'm using the onclick to trigger a call to the following javascript function (defined in 'defs' section):
function showId(elem) {
post_it_rect=getBBoxAsRectElement(elem);
document.getElementById('canvas').appendChild(post_it_rect);
}
(The 'getBBoxAsRectElement(elem)' is from the link I posted).
As this stands; this works just fine - however if I change my 'use' element to position the text in a different place like this:
<use x="100" y="100" id="12345" class="postit" xlink:href="#post_it" onclick="showId(this);"/>
Now, the text displays in the correct place, but the resultant 'background-color' (actually a 'rect' element with opacity of 0.5) still shows on the top-left of the svg canvass - and the function used to calculate the rect is returning '-2' rather than '100' ('-98'?) as I need (I think).
What do I need to do to line up the 'rect' elements and the text elements ?
The author of the (very helpful article btw) script provides a more advanced script to draw a box round any 'bb' in an SVG, but I couldn't get this to work (missing 'transform' functions?).
I'm using Firefox 7.x to render the SVG ; and I'm loading a .svg file (ie, not embedded in html etc) straight from disk to test this).
Yes, you may need to compensate yourself for the x and y attributes on the <use> element for the time being, I'll try to find some time to update the blogpost and script.
Here's a draft SVG 1.1 test that among other things checks that the effect of the x and y attributes are included in the bbox. The line starting [myUse] is the one that tests this case, if it's red then that subtest failed. Chromium and Opera Next both pass that subtest, while Firefox nightly and IE9 doesn't. Note that the test itself has not gone through full review yet, and that it may still change.

Categories