I'm working with chart.js v2 and I am trying simulate the hover state of a segment on a doughnut graph when the chart loads so it appears there is a section alright highlighted.
I've been searching and combing the code for a day now and can't figure out a good way to do this.
Thanks in advance!
Setting a segment's hover style is a bit confusing because its not really documented anywhere. Nevertheless, I was able to figure it out a while back when I wanted to highlight a segment when it's legend label was hovered.
To do this, you need to use the pie chart .updateHoverStyle() prototype method and pass in the segment you want highlighted. The chart segments are stored in the _meta object in an array where each segment index matches the position of each value in your chart's data array.
Here is an example (assuming your chart instance is stored in a var called myPie.
// get the segment we want to highlight
var activeSegment = myPie.data.datasets[0]._meta[0].data[segmentIndexToHihlight];
// update the hover style
myPie.updateHoverStyle([activeSegment], null, true);
// render so we can see it
myPie.render();
You just need to define what segment you want to highlight and store it in a var called segmentIndexToHihlight and it should work.
Here is a codepen example demonstrating this. Note, I purposely did not highlight the segment on load (I wait 3 seconds) so that you can see the change occur.
I found another way to preselect a segment, basically you can simulate a click event on the point. You can find in the dataset model the position x and y. Here you can find my solution:
function simulateClick(x, y) {
const clickEvent = document.createEvent('MouseEvents');
clickEvent.initMouseEvent('click', true, true, window, 0, 0, 0, x, y,
false, false, false, false, 0, null);
document.elementFromPoint(x, y).dispatchEvent(clickEvent);
}
function initActivePoint(index) {
const activePoint = myChart.data.datasets[0]._meta[0].data[index];
simulateClick(activePoint._model.x, activePoint._model.y);
}
initActivePoint(0);
Related
I'm using chart.js 2.6.0, which is the latest version.
I'm trying to overwrite the bar charts in order to make the corners rounded. I found this script: https://github.com/jedtrow/Chart.js-Rounded-Bar-Charts/blob/master/Chart.extentions.js and it works good.
I created a new graph option: "is_curved" because I have multiple graphs on the same page and I want to make rounded corners only for some of them.
The problem in my case is that if I'm using the following code, all the charts have rounded corners:
Chart.elements.Rectangle.prototype.draw = function() {
//code to make corners rounded
}
The function:
Chart.elements.Rectangle.prototype.draw
Is called on all the charts. I want it to be executed only when the option "is_curved" is set to true. So I tried:
Chart.elements.Rectangle.prototype.draw = function() {
if(!this._chart.options.is_curved) {
return;
}
//code to make corners rounded
}
But this is still wrong because the graphs that doesn't have the "is_curved" option set to true are empty, I guess that the fact that I call the .draw method removes all the existing functionality, even if I don't add new functionality for them.
Any idea how can I set the draw function to work only for the charts with "is_curved" option set to true? Thanks.
change this line of code:
var cornerRadius = 5;
to this :
var cornerRadius = this._chart.options.is_curved ? 5 : 0;
this will set barĀ's corner radius to 5 , if the is_curved property is set to true for any particular chart, otherwise will set to 0 .
see - working example on JSFiddle
I am writing a simple game in JS using EaselJS. I try to keep everything object-oriented to keep in sync state of game, state of EaselJS objects and what is displayed on my canvas. I would like to have possibility to change stroke color of shapes that are displayed on canvas by changing their attributes. I've found in docs append() here, but I can't get it working.
Here's what I've achieved so far:
Shape definition:
var bLetter = new createjs.Shape();
bLetter.graphics.append({exec: setPoweredState});
bLetter.graphics.moveTo(0, 0)
.lineTo(0, segSize * 2)
.arc(circSize, segSize * 2, circSize, Math.PI, Math.PI + 0.0001, true);
setPoweredState function - When i set bLetter.powered = true, the line color should change:
setPoweredState = function(ctx, shape) {
if(shape.powered) {
shape.color = consts.COLOR_LINE_ACTIVE;
} else {
shape.color = consts.COLOR_LINE_INACTIVE;
}
shape.graphics.beginStroke(shape.color).setStrokeStyle(consts.STROKE_SIZE, 'round', 'round');
}
When I set bLetter.powered = true and I check bLetter.color it seems that the function is executed - the bLetter.color property changes. However, the bLetter object on canvas is not updated. What's more, it's not drawn at all - probably I am using append() in incorrect way. What am I missing?
BTW: I omit the code with initializing createjs.Stage on canvas and adding bLetter as it's child, I don't think it's an issue, the shape is drawn correctly, only color won't change.
The issue is that you are continually appending new stroke / strokestyle commands to the end of the graphics queue, so they have no effect on the preceding paths.
The easiest approach in my opinion would be to save off the command as Lanny suggested, and modify its style in your setPoweredState method.
Here's an example of the above, implement with minimal modifications to your approach:
https://jsfiddle.net/u4o4hahw/
Instead of using append, consider just storing off commands to modify.
Here is another question that I answered outlining how it works: Injecting a new stroke color into a shape, and here is a blog post: http://blog.createjs.com/new-command-approach-to-easeljs-graphics/
Basically, you can store any command, then change its properties later:
var cmd = shape.graphics.beginFill("red").command;
shape.graphics.otherInstructionsHere();
// Later
cmd.style = "blue";
Here is a link to the docs on the Fill command used in the sample code: http://createjs.com/docs/easeljs/classes/Graphics.Fill.html
While generating a track with the help of dygraph library, I have set the legend: always (this display the legend with series name present on that particular track even without mouseover). But when I move to certain graph, the legend changes and shows the value of each series at that particular mouse pointer. I don't want the legend to change and it should just show the series name and not the values. I am using javascript to implement my app. Any way to do the same?
One trick that might be good enough is to supply a custom valueFormatter function for each axis which simply returns an empty string:
axes: {x: {valueFormatter: function (x) {return ''}},
y: {valueFormatter: function (y) {return ''}},
y2: {valueFormatter: function (y2) {return ''}}
}
This prevents the values from being shown, but still switches between line samples and ':' characters depending on the position of the mouse.
At the moment there's no easy way to do this. Your best bets are to either generate the legend yourself using dygraphs' API or to throw a transparent div over your chart which captures all the mouse events.
Well! it might be not a good way but I have found an alternative to do it. Declared a new boolean variable in dygraph.js which checks whether user wish to see x-y values on legend. Using this variable in function generateLegendHTML (defined in legend.js), i have made the control to always go in the first if loop. This makes the dygraph to always show static legend.
You can do the following -
Step 0 - Add a few necessary options and tags -
labelsDiv: document.getElementById("labels"),// in the dygraph options
<div id="labels"></div> <!-- Add this somewhere in your HTML-->
Step 1 - Declare a variable -
var defaultLabelHTML = undefined;
Step 2 - Use drawCallback option -
drawCallback: function(dygraph, is_initial){
if (is_initial)
{
defaultLabelHTML = document.getElementById("labels").innerHTML;
}
},
Step 3 - Use highlightCallback option -
function(e, x, pts, row)
{
document.getElementById("labels").innerHTML = defaultLabelHTML;
}
I have several lines and I know that clicking on the "dot" in the legend will hide/show it.
However, I need to start with some of the lines being disabled and not displayed, and the user will have to click on the dot in the legend to show it on the graph.
(eg. I graph the number of questions on stackoverflow per language, but with C, PHP and javascript disabled by default). the graph only shows python, ruby... but on the legend, you have all the languages, including C, PHP and js with these 3 being disabled.
I haven't found a method/attribute for each data serie to set the default show/hide status. Am I missing something?
After reading this answer I still had to do some more reading in order for me to understand how to set a stream disabled from my JSON data-stream for the graphs.
The example below is what solved it for me disabled: true
{
key: "something",
disabled: true,
values: [...]
}
You can change which streams are enabled/disabled by using the chart.state() object. For example:
// Assuming your chart is called 'chart'
var state = chart.state();
for(var i=0; i < state.disabled.length; i++) {
state.disabled[i] = ...LOGIC RETURNING TRUE OR FALSE...;
}
chart.dispatch.changeState(state);
chart.update();
For each of your data series that you want disabled, just do:
series.disabled=true
nvd3 does not do everything, but if you are willing to peruse the code it is actually quite flexible. I discovered this by finding this line in the source of several of the chart models:
state.disabled = data.map(function(d) { return !!d.disabled });
You could start out with a hidden chart and try something like this:
// Array of series you want to hide
var hidden = [0, 2];
// Dispatch click event to each element
var e = document.createEvent('UIEvents');
e.initUIEvent('click', true, true);
d3.select('.nv-legend')
.selectAll('.nv-series')
.filter(function(d, i){return hidden.indexOf(i) !== -1;})
.node()
.dispatchEvent(e);
Once this finishes, unhide your chart and the series will be disabled.
below is the link to code regarding to dynamic graph. I am having a problem of making the red line, being updated and move forward together with the blue line.. I don't know where the problem is that make the red line static in the dynamic graph..
And solution to the code? Thanks again for helping..
http://jsfiddle.net/EkkBQ/
You need to tell it to also update the second series of data. I couldn't figure out the smoothing or if it's possible to smooth once you have > 1 data stream.
http://jsfiddle.net/EkkBQ/8/
Key code added:
var seriesA = this.series[1];
setInterval(function() {
var x = (new Date()).getTime(), // current time
y = Math.random();
seriesA.addPoint([x, y], true, true);
}, 1000);
I duplicated the call where the series data is added to the chart - changed the series variable to seriesA and then told it to pull the second series of data (series1).
Hope this helps.