How can we make plotly animation smooth - javascript

I try to make a surface chart and to add a slider to animate it.
I'm new with Plotly and tried to copy the transition parameters, animations methods, frames parameters from this example : https://plot.ly/javascript/gapminder-example/ but it still jump from one state to the next one without transition.
Then : is it possible to have smooth transitions with any chart or not?
here is my code:
<head>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<div id="myDiv"> </div>
<script >
var traces = [{"name":"Asia", "type":"surface","z":[["28.801", "55.23","43.077","30.015", "62.485"],["28.801", "55.23","43.077","30.015", "62.485"],["779.4453145", "1601.056136","2449.008185","3520.610273", "5911.315053"], ["8425333", "1282697","9279525","4232095", "17876956"]],"id":["Afghanistan","Albania","Algeria","Angola", "Argentina"],"text":["Afghanistan","Albania","Algeria","Angola", "Argentina"]},//"mode":"markers","marker":{"size":["8425333"],"sizemode":"area","sizeref":200000}},];
var layout = {"xaxis":{"title":"Life Expectancy","range":[30,85]},
"yaxis":{"title":"GDP per Capita","type":"log"},
"hovermode": "text",
"updatemenus":[{"x":0,"y":0,"yanchor":"top","xanchor":"left","showactive":false,"direction":"left","type":"buttons","pad":{"t":87,"r":10},
"buttons":[{"method":"animate",
"args":[null,{"mode":"immediate","fromcurrent":true,"transition":{"duration":300},"frame":{"duration":500,"redraw":false}}],
"label":"Play"},
{"method":"animate",
"args":[[null],{"mode":"immediate","transition":{"duration":0},"frame":{"duration":0,"redraw":false}}],
"label":"Pause"}]}],
"sliders":[{"pad":{"l":130,"t":55},
"currentvalue":{"visible":true,
"prefix":"Year:",
"xanchor":"right",
"font":{"size":20,"color":"#666"}},
"steps":[{"method":"animate","label":"1952","args":[["1952"],{"mode":"immediate","transition":{"duration":300},"frame":{"duration":300,"redraw":false}}]},
{"method":"animate","label":"1957","args":[["1957"],{"mode":"immediate","transition":{"duration":300},"frame":{"duration":300,"redraw":false}}]},
{"method":"animate","label":"1962","args":[["1962"],{"mode":"immediate","transition":{"duration":300},"frame":{"duration":300,"redraw":false}}]}
]}]};
var frames = [
{"name":"1952","data":[{"z":[["28.801","55.23","500.077","30.015","62.485"],["28.801","55.23","500.077","30.015","62.485"],["779.4453145","1601.056136","2449.008185","3520.610273","5911.315053"],["8333","5419","8050","42095","6890"]], "id":["Afghanistan","Albania","Algeria","Angola","Argentina"],"text":["Afghanistan","Albania","Algeria","Angola","Argentina"]}]},
{"name":"1957","data":[{"z":[["30.332","59.28","450.685","41.999","64.399"],["30.332","59.28","450.685","41.999","64.399"],["820.8530296","1942.284244","3013.976023","9827.940465","6856.856212"],["9244","1951","6413","61361","7506"]], "id":["Afghanistan","Albania","Algeria","Angola","Argentina"],"text":["Afghanistan","Albania","Algeria","Angola","Argentina"]}]},
{"name":"1962","data":[{"z":[["70.332","100.28","400.685","51.999","64.399"],["70.332","100.28","400.685","51.999","64.399"],["920.8530296","2342.284244","6013.976023","10827.940465","6856.856212"],["4094","2670","5096","1361","8065"]], "id":["Afghanistan","Albania","Algeria","Angola","Argentina"],"text":["Afghanistan","Albania","Algeria","Angola","Argentina"]}]},
];
Plotly.newPlot("myDiv", {data: traces, layout: layout, frames: frames});
</script>

Related

how to focus the clicked bar in C3.js bar graph?

I have this code which makes a graph using c3.js : https://jsfiddle.net/1bxe2scd/
<!DOCTYPE html>
<html>
<head>
<title>Dsnap - Charts</title>
<!-- Load c3.css -->
<link href="c3/c3.css" rel="stylesheet" type="text/css">
<!-- Load d3.js and c3.js -->
<script src="d3/d3.min.js" charset="utf-8"></script>
<script src="c3/c3.min.js"></script>
</head>
<body>
<div id="chart" style="width:480px;height:400px"></div>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
var chart = c3.generate({
bar: {
width: 15
},
padding: {
left: 60
},
data: {
x: 'Date',
columns:
[
['Date', '2011-02','2013-01','2013-02','2013-03','2013-04','2013-05','2013-06','2013-07','2013-08','2013-09','2013-10','2013-11','2013-12','2014-01','2014-02'],
['value', 777,53,165,269,344,376,410,421,405,376,359,392,433,455,978]
],
type: 'bar',
onclick: function(e) { console.log(e.x);}
},
axis: {
rotated: true,
x: {
type: 'category'
}
},
tooltip: {
grouped: false
},
legend: {
show: false
}
});
</script>
</body>
</html>
I want the bar on which the user clicks to be focused and the rest of the bar should become faded, how can I achieve that?
How can I get the Y value of the clicked bar(eg: 2011-02 etc)?
You can do this for highlighting the bar:
onclick: function(e) {
//make all the bar opacity 0.1
d3.selectAll(".c3-shape").style("opacity",0.1);
var k = ".c3-shape-"+ e.index;
//make the clicked bar opacity 1
d3.selectAll(k).style("opacity",1)
}
Working code here
On clicking out side in the chart if you wish to bring back all the bars attach the click listener to the chart and on click make all bar's opacity 1:
d3.selectAll("#chart").on("click", function(d) {
//reset all the bars
d3.selectAll(".c3-shape").style("opacity", 1);
})
Working code here
EDIT
So now since you have two charts specify the id also to make it specific to the chart note the id in the selector: (#chart/#chart1):
d3.selectAll("#chart1").on("click", function(d) {
//reset all the bars for chart1
d3.selectAll("#chart1 .c3-shape").style("opacity", 1);
})
d3.selectAll("#chart").on("click", function(d) {
//reset all the bars for chart
d3.selectAll("#chart .c3-shape").style("opacity", 1);
})
On click for chart1 bar will look like this:
onclick: function(e) {
//make all the bar opacity 0.1 for chart1
d3.selectAll("#chart1 .c3-shape").style("opacity", 0.1);
var k = "#chart1 .c3-shape-" + e.index;
//make the clicked bar opacity 1
d3.selectAll(k).style("opacity", 1)
event.stopPropagation()
}
Working code here
Hope this helps!
C3 has callbacks, for specifying what should happen when a click (or mouseover/mouseout) event occurs:
http://c3js.org/reference.html#data-onclick
It also has "APIs": functions you can call to basically act like the user made a selection or focused:
http://c3js.org/reference.html#api-focus
You could hook one of these up to trigger the other, like have the onclick() function call focus().
But given what you're precisely looking for, the impediment would be that the focus() function doesn't accept the indices of individual bars on the graph. So it can only highlight an entire column/series of data at once, not individual bars. Here's the GitHub issue:
https://github.com/c3js/c3/issues/1389

Straight-lines chart with dynamic data (currently using graphael lib)

I am trying to build a dynamically fed (data) straight lines chart. I built a prototype using graphael.
Here is my code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Line Charts</title>
<script src="raphael.js"></script>
<script src="g.raphael.js"></script>
<script src="g.line.js"></script>
<script language="JavaScript" type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>
window.onload = function () {
var r = Raphael("holder");
var yAxisTags = ["A","B","C","D"];
var xData = [
[2000,2015],//hack line, transparent; used to specify the range of the axis
[2008,2014],[2004,2005],[2009,2010],[2000,2007],[2000,2014],[2010,2012]
];
var yData = [
[1, 1],//y coordinates of hack line
[0, 0],[1, 1],[1, 1],[2, 2],[3, 3],[0,0],
[0, 0]//hack line, transparent.Used to be able to draw straight lines
];
var colors = [
'transparent',//line 1
'red','green','green','purple','turquoise','black',
'transparent'];//'transparent' IS A MUST, a hack to make it have a straight line
var options = {
nostroke: false,
gutter: 90,
axis: "0 0 1 1",
symbol: "circle",
axisxstep:10,
axisystep:3,
colors: colors
};
var lines = r.linechart(100, 10, 700, 300,xData,yData,options);
// AXIS (x and y) have values but do not drawn the lines
lines.axis[0].attr([{stroke: false}]);
lines.axis[1].attr([{stroke: false}]);
// Thickness of symbols (ie dots)
lines.symbols.attr({ r: 4 });
// Animate dots on first load
lines.animate({"stroke-width": 1}, 1000);//ALL lines,1000 is animation time
// Set text for Y axis coordinates (instead of numbers)
$.each(lines.axis[1].text.items, function(index, label) {
this.attr("text", yAxisTags[index]);
});
};
</script>
</head>
<body>
<div id="holder" style="width:50%"></div>
</body>
</html>
And here is how it looks like:
So basically I want a time related (jumps +2 years from point to point) line chart graph with labels on Y-axis, that is made by drawing straight lines and to which dynamic data is being fed. The current code works with this specific configuration only but once i start modifying the data, the display is not accurate anymore:
x-axis (time axis) gets buggy and time doesn't jump +2 years
if there is a large difference in between two years (2 X coordinates), the line is drawn as a dot
will have to modify axisxstep and axisxstep (don't understand how the logic behind these works to be honest)
etc..
Is there a technique/hack around to make my desired line chart concept work with dynamic data using graphael? or it is not feasible with this library?
For anyone stuck with this same scenario:
Since I am using AngularJS, I ended up using angular-google-chart.
It is a directive wrapper around google chart; it is stable and straightforward to use.

While Removing div using javascript, the backgroundimage stayed

I am having a problem with the background-image inside a div.
I am trying to program a html-webgame, using mainly canvas. So as a result, my index looks like this.
<head>
<title>Cardgame</title>
<link rel="stylesheet" type="text/css" href="resoursces/css/index.css">
</head>
<body>
<div class='game_object' id='game_object'>
<canvas class='main_canvas' id='main_canvas'>Error</canvas>
</div>
<script type="text/javascript" src='main.js'></script>
</body>
The problem comes along like this:
window.onload = (function() {
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
drawing();
} resizeCanvas();
})();
in the function "drawing()" i am doing 2 things.
The first one is to remove all divs, i have created so far,
and the second is the i am drawing all div's new with new x-coordinate, y-coordinat, hight and width. So it looks like this
function drawing() {
delete_div();
create_div();
}
function delete_div() {
battlefield_div.style.removeAttribute("backgroundImage", false);
battlefield_div.parentNode.removeChild(battlefield_div);
}
funtciont create_div() {
var board_div= document.createElement("div");
board_div.setAttribute("id", "board");
board_div.style.position = 'absolute';
board_div.style.top = board.y1+"px";
board_div.style.left = board.x2+"px";
board_div.style.height = board.y2 - board.y1+"px";
board_div.style.width = board.x1 - board.x2+"px";
board_div.style.zIndex = '2';
board_div.style.backgroundImage="url(resoursces/images/board.png)";
board_div.style.backgroundSize = "100% 100%";
game_object.appendChild(board_div);
}
This game is a cardgame and i wanted to make it to resize when ever you change the height and the width of the browser without loosing its function. The divs i am creating are part of the functionality.
Everything works fine with it, except one thing: Whenever you resice the browser, the divs are getting remove and new ones are calculated but the background-images is still there. So when you resized your browser like 4 times, you are just seeing the background-images.
What am i doing wrong?
Can anyone help me?

FabricJS - add line to canvas and control only it's length

I am using FabricJS to develop a simple floor plan editor. When adding a Line (that should be a wall) to the canvas, I want the ability to control only the length of the line, not it's width-height.
I have tried setting lockScalingY: true but the problem is that when adding a line the control handles are so close to each other that I can't interact only with the horizontal control handles... the corner handles actually block the horizontal handles...
How can this be done?
Fine control of adjoining FabricJS lines
The way graphics programs like photoshop deal with this common problem is to let the user position lines near the desired intersection and then use the arrowkeys to "nudge" the line into place pixel one at a time.
The code below illustrates a rough solution that does the same thing for FabricJS lines:
User selects a line.
Turn off the control handles and borders.
Let the user "nudge" the line into perfect alignment (here the line length is increased).
Turn the the control handles and borders back On.
This is just "proof of concept" code. In your production app:
You'll probably want to use arrowkeys instead of buttons to "nudge".
I made nudging go 10px at a time--you might do this 1px at a time.
And when the user starts nudging, you'll automatically turn off the handles and borders for them.
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/dd742/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript" src="fabric.min.js"></script>
<style>
body{ background-color: ivory; padding:30px; }
canvas{border: 1px solid red; }
</style>
<script>
$(function(){
var canvas = new fabric.Canvas('canvas');
var selectedLine;
var line1=newLine(50,100,150,100,"red");
var line2=newLine(160,50,160,150,"green");
canvas.add(line1,line2);
function newLine(x1,y1,x2,y2,color){
var line=new fabric.Line(
[x1,y1,x2,y2],
{fill:color,strokeWidth:15,selectable:true}
);
return(line);
};
$("#hOff").click(function(){
selectedLine.hasBorders=false;
selectedLine.hasControls=false;
canvas.renderAll();
});
$("#hOn").click(function(){
selectedLine.hasBorders=false;
selectedLine.hasControls=true;
canvas.renderAll();
});
$("#shorter").click(function(){
changeLineLength(selectedLine,-10);
canvas.renderAll();
});
$("#longer").click(function(){
changeLineLength(selectedLine,10);
canvas.renderAll();
});
function changeLineLength(line,adjustment){
if(!selectedLine){return;}
if(line.get("y1")==line.get("y2")){ // line is horizontal
line.set("x2",line.get("x2")+adjustment);
}else
if(line.get("x1")==line.get("x2")){ // line is vertical
line.set("y2",line.get("y2")+adjustment);
}else{ // line is diagonal
line.set("x2",line.get("x2")+adjustment);
line.set("y2",line.get("y2")+adjustment);
}
}
canvas.observe('object:selected', function(eventTarget) {
var event=eventTarget.e;
var target=eventTarget.target;
selectedLine=target;
});
}); // end $(function(){});
</script>
</head>
<body>
<p>Select a line,</p><br/>
<p>Turn handles Off</p><br/>
<p>Make lines intersect by pressing longer/shorter</p><br/>
<canvas id="canvas" width="600" height="200"></canvas>
<button id="hOff">Handles Off</button>
<button id="shorter">Shorter</button>
<button id="longer">Longer</button><br/>
<button id="hOn">Handles On</button>
</body>
</html>
May be helps somebody.
Add handler to event
'object:selected': _objSelected
Then at handler set unneeded control to false.
function _objSelected(e)
{
if(e.target.objectType == 'line')
{
var cv = e.target._controlsVisibility;
// mt - middle top, tl - top left and etc.
cv.mt = cv.mb = cv.tl = cv.bl = cv.tr = cv.br = false;
}
}
Also I added objectType (custom property) and padding (for beauty) to new object Line
var obj = new fabric.Line([50, 50, 150, 50], { padding: 10, objectType: 'line' });

How do you switch the cursor to a pointer cursor when hovering over the bars in a Kendo UI bar chart

I have a Kendo UI Datavis Bar Chart for which I wish to show the pointer (hand) cursor when hovering over the bars in the chart and labels for those bars. When moving off the bars in the chart the cursor should return to the standard arrow pointer.
I noticed that the cursor turned into the text cursor when hovering over the axis labels (left, right, and bottom) and on the legend. So in addition to the above I would like the cursor to remain the standard cursor (arrow) when hovering over the axis labels and legend (since you cannot edit these). I would also like the cursor to switch to the pointer cursor when hovering over the x-axis (bottom) labels.
I can easily show a pointer cursor for the entire chart when hovering anywhere over the chart but that is not desired.
I have tried various strategies using the seriesHover event but so far nothing has worked.
How do I achieve the above?
Thomas your answer almost has me there. However, I need one additional piece of information:
How would I use the technique you show in your answer below within a CSS file. I have several Kendo UI charts some for which I need this behavior and some for which I do not. I have both ids and classes associated with the divs that contain the kendo UI charts (one div per chart). The actual charts are created using JavaScript code at load time. I tried to add the following, to the CSS within the CSS file but this had no effect:
#barChart {
/*cursor: pointer;*/
(svg > path):last-child {cusror: pointer;}
}
where #barChart is the Id of the div containing the KendoUI chart within the HTML
<div id="barChart" class="bargraph"></div>
Is there a way to do what you have shown below for charts that are created at load time within predefined divs? Does this have to be done by hooking into the charts hover event?
Just tried styling the Kendo UI bar chart demo with CSS; both turning the cursor into a hand and leaving it the default cursor on text works quite well. I just had to add two lines of CSS (and change the script/CSS URLs):
<html>
<head>
<title></title>
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://cdn.kendostatic.com/2012.3.1114/js/kendo.all.min.js"></script>
<link href="http://cdn.kendostatic.com/2012.3.1114/styles/kendo.common.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2012.3.1114/styles/kendo.default.min.css" rel="stylesheet" />
<style type="text/css">
/* When hovering over a bar, Kendo dynamically adds
a bar as the last child of the SVG element that
works as an overlay. So, effectively, we're
hovering over the last (dynamically added) child */
svg > path:last-child {cursor:pointer;}
svg {cursor:default}
</style>
</head>
<body>
<div id="example" class="k-content">
<div class="chart-wrapper">
<div id="chart" style="background: center no-repeat url('../../content/shared/styles/world-map.png');"></div>
</div>
<script>
function createChart() {
$("#chart").kendoChart({
theme: $(document).data("kendoSkin") || "default",
title: {
text: "Internet Users"
},
legend: {
position: "bottom"
},
chartArea: {
background: ""
},
seriesDefaults: {
type: "bar"
},
series: [{
name: "World",
data: [15.7, 16.7, 20, 23.5, 26.6]
}, {
name: "United States",
data: [67.96, 68.93, 75, 74, 78]
}],
valueAxis: {
labels: {
format: "{0}%"
}
},
categoryAxis: {
categories: [2005, 2006, 2007, 2008, 2009]
},
tooltip: {
visible: true,
format: "{0}%"
}
});
}
$(document).ready(function() {
setTimeout(function() {
// Initialize the chart with a delay to make sure
// the initial animation is visible
createChart();
$("#example").bind("kendo:skinChange", function(e) {
createChart();
});
}, 400);
});
</script>
</div>
<script type="text/javascript">
console.log("hi")
document.addEventListener("click",function(e){document.write(e.target)},false)
</script>
</body>
</html>​
If you have multiple charts and want this behavior only for some charts, I'd suggest using classes, like
<div id="barChart" class="bargraph cursorPointer"></div>
And change the CSS like
.cursorPointer svg > path:last-child {cursor:pointer;}
.cursorPointer svg {cursor:default}
(If you want the arrow cursor on text of all graphs, omit the .cursorPointer on the second line.)
If you want to change the cursor only in those labels where you have defined axisLabelClick event. You can do this:
var chart = $("#chart").data("kendoChart");
In my case, I just handle the first label, so I only want the pointer cursor in there:
var idLabel = chart._plotArea.axisY.children[0].options.id;
$('#' + idLabel).css('cursor', 'pointer');
Interestingly enough this worked for me perfectly (Only Bar Chart Kendo 2016):
svg > g g g g g g {cursor:pointer;}
svg {cursor:default}
Since this isn't a setting in Kendo yet, as #ThomasW, wrote you need to find a way to target the overlay path that gets shown when you hover over the graph elements.
In my case I noticed that all of those overlays have fill-opacity="0.2" and this did the trick:
.kendo-chart-wrapper [fill-opacity="0.2"] {
cursor: pointer;
}

Categories

Resources