I have an svg component on my page to which I have appended my dimple chart. I want the chart to be sized responsively.
I have referred to this example in the documentation.
But when I use it in a similar fashion in my line chart, it does not seem to work. My code for a line chart is as follows:
var xpoints = chartData["xdata"];//Populated Dynamically
var ypoints = chartData["ydata"];//Populated Dynamically
var dataset = [];
var line1;
for (var i = 0; i < xpoints.length; i++) {
dataset.push({
x : xpoints[i],
y1 : parseFloat(ypoints[i])
});
}
var svg = dimple.newSvg("#" + mychart, "100%", "100%");
var x, y;
var myChart = new dimple.chart(svg, dataset);
myChart.setMargins("60px", "30px", "110px", "70px");
y = myChart.addMeasureAxis("y", "y1");
x = myChart.addCategoryAxis("x", "x");
line1 = myChart.addSeries("First", dimple.plot.line, [ x, y ]);
line1.lineMarkers = true;
var l = myChart.addLegend(65, 10, 510, 20, "right");
myChart.draw(1500);
window.onresize = function () {
myChart.draw(0, true);
};
Is it that I cannot do this in the same window itself and it is absolutely necessary for me to create a new window, as in the example?
The console does not show any errors, the chart is rendered correctly. It's just that the resize function does not work!
Okay, I found my mistake!
Turns out there is no need to create a new window.
It's just that, I had explicitly defined the height and width of the div (#mychart) to which I was appending my svg and these dimensions were in pixels. So the size of the svg remained the same even on window resize - because it was always 100% of a constant pixel value. So the function was actually firing earlier as well, but was ending up with the same dimensions.
I changed the dimensions of my div to percentage values and everything works fine :D
Related
I can't seem to get any output from the project I'm working on with paper.js
Doesn't seem to recognise raster.on as a function for some reason... Could anyone help me as to why the error is being displayed says not a function?
I've tried initialising the paperscript in a couple different ways (or what I thought I have - as very much a newbie).
Any help would be VERY much appreciated, been trying this last 3-4 days with no luck and a lot of trailing and error with no joy... boooooo :'(
Please see js fiddle below:
js fiddle - raster.on not a function
/*Paper JS Setup for working in CodePen */
/* ====================== *
* 0. Initiate Canvas *
* ====================== */
// expose paperjs classes into global scope
paper.install(window);
// bind paper to the canvas
paper.setup('canvas');
// Only executed our code once the DOM is ready.
window.onload = function() {
// Get a reference to the canvas object
var canvas = document.getElementById('myCanvas');
// Create a raster item using the image tag with id='mona'
var raster = new Raster('mona');
// Hide the raster:
raster.visible = false;
// The size of our grid cells:
var gridSize = 12;
// Space the cells by 120%:
var spacing = 1.2;
// As the web is asynchronous, we need to wait for the raster to load
// before we can perform any operation on its pixels.
raster.on('load', function() {
// Since the example image we're using is much too large,
// and therefore has way too many pixels, lets downsize it to
// 40 pixels wide and 30 pixels high:
raster.size = new Size(40, 30);
for (var y = 0; y < raster.height; y++) {
for(var x = 0; x < raster.width; x++) {
// Get the color of the pixel:
var color = raster.getPixel(x, y);
// Create a circle shaped path:
var path = new Path.Circle({
center: new Point(x, y) * gridSize,
radius: gridSize / 2 / spacing,
fillColor: 'black'
});
// Scale the path by the amount of gray in the pixel color:
path.scale(1 - color.gray);
}
}
// Move the active layer to the center of the view, so all
// the created paths in it appear centered.
project.activeLayer.position = view.center;
});
}
As explained in the documentation for raster, you should use raster.onLoad attribute:
raster.onLoad = function() {
console.log('The image has loaded.');
};
I have google material Line chart and need to get X and Y position of some datapoint in layout for add image to graph area... But web page in browser says:
chart.getChartLayoutInterface is not a function
I found, there is no method getChartLayoutInterface() in Google Material graphs available. If I switch this code to "classic graph" code (comment/uncomment) in code, that my example works...
There is my code:
var container = document.getElementById('chart_div');
var chart = new google.charts.Line(container);
//If I Uncomment this line, google uses old "Classic" line graphs and that works...
//var chart = new google.visualization.LineChart(container);
google.visualization.events.addListener(chart, 'ready', function () {
var layout = chart.getChartLayoutInterface();
var xPos = layout.getXLocation(data.getValue(210, 0));
var yPos = layout.getYLocation(data.getValue(210, 2));
var GameEvent = container.appendChild(document.createElement('img'));
GameEvent.src = '/nuke.png';
GameEvent.style.top = (yPos -0) + 'px';
GameEvent.style.left = (xPos) + 'px';
}
);
But I need to use material graphs (it works better on google chromecast as renderer).
Can you have any solution for me?
I've built a line-graph in dimple.js that can be found here. http://jsfiddle.net/lukehtravis/0twgc2uL/
You'll notice on the y-axis, there is a little "m" that is automatically generated by dimple and placed next to the numbers as a quantity label.
I combed through the documentation, but couldn't find anything about that little m.
Anyone know how to remove it? Here's the code
// Create the canvas to draw on
var svg = d3.select("#charty")
.append("svg")
.attr("width", 800)
.attr("height", 500);
// Create the chart object | contents of data visible in fiddle link above
var chart = new dimple.chart(svg, data);
//Create the x axis
var x = chart.addCategoryAxis("x", "Day");
x.showGridlines = true;
// Create the y axis
var y = chart.addMeasureAxis("y", "Volume");
y.title = "Volume (AF)";
y.overrideMin = 300000;
y.overrideMax = 1450000;
y.showGridlines = true;
// Add location as data series
var series = chart.addSeries("Location", dimple.plot.line);
// Decorate the lines in the graph
series.lineWeight = 2;
series.lineMarkers = true;
// Create the legend
chart.addLegend(100, 50, 200, 200);
// Draw the chart
chart.draw(3100);
Small m is not but conversion of units into million..
0.3million is your value 300000 .. Its pretty normal and not an error ..
If you dont want that then just add this line y.tickFormat = "1f"; after
y.showGridlines = true;
I have ScrollView and sequence of Surface elements in it.
I want to be able to scroll to the latest element as soon as it appears in the array.
Here is a demo, I want it to be scrolled just like in any chat application... old surfaces go beyond the scene, and new will be always at the bottom. The question is the same as here: Famo.us how to make a scrollview be filled from bottom to top (or right to left)?
http://jsfiddle.net/LA49a/
Famous.loaded(function () {
var Engine = Famous.Core.Engine;
var Surface = Famous.Core.Surface;
var Scrollview = Famous.Views.Scrollview;
var Timer = Famous.Utilities.Timer;
var mainContext = Engine.createContext();
var scrollview = new Scrollview();
var surfaces = [];
var i = 0;
scrollview.sequenceFrom(surfaces);
Timer.setInterval(function () {
var temp = new Surface({
content: "Surface: " + (i + 1),
size: [undefined, 50],
properties: {
backgroundColor: "hsl(" + (i * 360 / 40) + ", 100%, 50%)",
lineHeight: "50px",
textAlign: "center"
}
});
temp.pipe(scrollview);
surfaces.push(temp);
i++;
// scrollview.goToNextPage();
}, 400);
mainContext.add(scrollview);
});
This is supported in the famous-flex ScrollView by setting the alignment property to 1.
See this demo:
https://github.com/IjzerenHein/famous-flex-chat
I'm assuming you're putting in a very large, round number to get the scrollview to move to the end, which shows your 'latest' element.
If you've got surfaces that are the same width (assuming an X orientation of the scrollview) you might get a smoother result by checking for the actual number of pixels you need to move to position the last item at the right edge of scrollview. You have the original array that you ran sequenceFrom() on. Multiply the number of items in that by your surface width and subtract pixels for the scrollview's width (which could be set to 'undefined' in which case you'll need to look at the window's width) to adjust for getting the latest element to the right side of the scrollview instead of the left side.
If your surfaces are not the same size, you might change things to track the x-offset of each surface as you add them to the backing array by just adding a property to the surface. Then you could just ask the surface what its offset is and subtract the right amount for the width of the scrollview.
Hope that helps you get closer.
Solved, by rotating ScrollView by 180˚ and all surfaces inside it also by 180˚ http://jsfiddle.net/tamtamchik/LA49a/3/
Famous.loaded(function () {
var Engine = Famous.Core.Engine;
var Surface = Famous.Core.Surface;
var Scrollview = Famous.Views.Scrollview;
var Timer = Famous.Utilities.Timer;
var Transform = Famous.Core.Transform;
var StateModifier = Famous.Modifiers.StateModifier;
var ContainerSurface = Famous.Surfaces.ContainerSurface;
var mainContext = Engine.createContext();
var scrollview = new Scrollview();
var surfaces = [];
var i = 0;
var surfaceHeight = 50;
scrollview.sequenceFrom(surfaces);
Timer.setInterval(function () {
var container = new ContainerSurface({
size: [undefined, surfaceHeight]
});
var temp = new Surface({
content: "Surface: " + (i + 1),
size: [undefined, surfaceHeight],
properties: {
backgroundColor: "hsl(" + (i * 360 / 40) + ", 100%, 50%)",
lineHeight: "50px",
textAlign: "center"
}
});
var surfaceRotate = new StateModifier({
transform: Transform.rotateZ(Math.PI)
});
var surfacePush = new StateModifier({
transform: Transform.translate(window.innerWidth, surfaceHeight)
});
container.add(surfacePush).add(surfaceRotate).add(temp);
container.pipe(scrollview);
temp.pipe(scrollview);
surfaces.unshift(container);
i++;
}, 400);
var rotate = new StateModifier({
transform: Transform.rotateZ(Math.PI)
});
var push = new StateModifier({
transform: Transform.translate(window.innerWidth, window.innerHeight)
});
mainContext.add(push).add(rotate).add(scrollview);
});
hmm, that's pretty crafty! Its a couple of extra matrices which could get very slow if you have a lot of text content in those nodes tho...
By using a huge number, this is just to force famo.us to scroll to the end of the view, I assume?
if the render had happened you could also:
pos = getPosition(nodeNum) // for last elements scrollposition
setPosition(pos)
But if the insert happens in same code block as your movement control it's not rendered yet.
There's a complicated workaround offered here using events to trigger the sizing calculation after the deploy/render has occurred:
how can we get the size of a surface within famo.us?
and another trick here to make famous recalculate sizes from the inimitable #johntraver
how to make famo.us recalculate sizes?
did you also look at Engine.nextTick() or JQuery.deferred ?
It seems that immediately after you insert the content there will be a "not rendered" instant but after an update you could get the sizes OK.
I generate some squares dynamically using rahaeljs. These squares have an event handler. When I try to manipulate the style, it fails depending on the attr() I try to set:
function changeColor(obj) {
return function() {
obj.attr({cursor : 'pointer'});
}
}
var main = function () {
var width = 901;
var height = 868;
var space = 50;
var paper = Raphael('paper', width, height);
for (var y = 0; y < height; y += space) {
for (var x = 0; x < width; x += space) {
var r = paper.rect(x, y, space, space);
r.attr({fill : 'transparent'})
r.click(changeColor(r));
}
}
};
window.onload = main;
If I set the cursor to {cursor : 'pointer'}, this works fine, if I try to change the fill color with obj.attr({fill : '#ff00ff'}); in the changeColor-function, nothing happens. There is also no Error in the console.
I'm using the latest version of raphael.
Any suggestions?
Regards,
michael
You'll be either very amused or very frustrated by this answer... the problem has to do with the transparent fill attribute. SVG treats fully transparent objects as unclickable, letting click events filter down to the layer(s) beneath them. Therefore, your rectangles are not receiving click events.
If you can't set the color to a solid color, you can at least give the fill attribute a tiny, almost unnoticeable amount of alpha:
r.attr({ fill: 'rgba(255,255,255,0.001)' } );
That done, you should be back in business!