I'm working on a somewhat long-in-the-tooth AngularJS 1.2 application that uses angular-google-charts as a wrapper. I've tried and succeeded at getting the chart to display the way I want it to when I emulate the print media in Chrome Inspector. However, when I actually go to print, the chart is reduced to a 400 x 200 w/h ratio, and the labels start to overlap.
I've used the chartArea options in the chart object to fix the print version of the chart to 400 x 600, with a small offset for the vAxis, and, again, it works when I am developing from the emulated print view.
I've also attempted to use the PNG-generating getImageURI() method, which I can resize, but the resolution stays the same - so I get a grainy PNG with labels overlapping.
I've also attempted a callback method to re-set the chartOptions on load, and I'm able to reset the overall size, but I don't see how to do the chartArea with a callback.
let resizeChart = {'height': 456, 'width': 678};
$scope.resizeChartPrintOptions = function (chartWrapper) {
chartWrapper.setOption("height", resizeChart['height']);
chartWrapper.setOption("width", resizeChart['width']);
console.log('chartWrapper: ', chartWrapper); // this shows chart size but not chart area
}
I'm at a loss for how to debug the print preview, other than to use the Chrome Inspector render emulator, which isn't serving me the way I expected.
How can I print a Google Chart to the desired size?
Related
I'm new to D3, NVD3 and Angular-NVD3. I need to create a chart that looks similar to this, using Angular-NVD3:
SO question: NVD3 Stacked Bar Chart Plus Line Overlapped
(there's a JS Fiddle on the SO question).
Angular-NVD3 has two charts which each accomplish most of what I need, but not all of it:
Those would be the MultiBar and the MultiChart. (http://krispo.github.io/angular-nvd3/#/quickstart)
Examples:
That is, I need a stacked bar chart with a line (or lines) overlaid on top of the bar chart. I believe that to do this, one must use a "multiChart" instead of "multiBar" chart. (Please correct me if I'm wrong).
The SO example above modifies the NVD3 library, which I would like to avoid. After researching, I can see why they chose this approach.
nv.d3.js (version 1.8.2), for the multiChart object, Lines 9068-9069 :
bars1 = nv.models.multiBar().stacked(false).yScale(yScale1),
bars2 = nv.models.multiBar().stacked(false).yScale(yScale2),
If you change these lines to .stacked(true), it does stack the bars.
How can I use Angular-NVD3 and accomplish what I need without changing the library?
Ideally the solution would be pure configuration. The next most ideal situation would be to set the "stacked" value at runtime from inside my enclosing component, but I can't seem to get access to the object.
I would like to avoid a highly intricate solution if possible because the whole point of these abstractions is to avoid such complexities. However, all solutions are welcome.
I found the answer:
you can change the stacked value in the callback() event handler, specified in your config:
chart: {
type: 'multiChart',
...
callback: function (chart) {
chart.bars1.stacked(true);
chart.bars2.stacked(true);
chart.update();
},
...
}
};
Use multiChart. To get the bars side by side set yAxis: 1 on both bar data sets.
https://github.com/novus/nvd3/blob/master/examples/multiChart.html
(the repo examples cover more then the website)
I have trouble getting Map behave properly when calling ZoomToResolution and PanTo
I need to be able to Zoom into specific coordinate and center map.
The only way I got it working is by removing animations:
this.MapControl.ZoomDuration = new TimeSpan(0);
this.MapControl.PanDuration = new TimeSpan(0);
Otherwise if I make call like this:
control.MapControl.ZoomToResolution(ZoomLevel);
control.MapControl.PanTo(MapPoint());
It does one or another (i.e. pan or zoom, but not both). If (after animation) I call this code second time (map already zoomed or panned to needed position/level) - it does second part.
Tried this:
control.MapControl.ZoomToResolution(ZoomLevel, MapPoint());
Same issue, internally it calls above commands
So, my only workaround right now is to set Zoom/Pan duration to 0. And it makes for bad UX when using mouse.
I also tried something like this:
this.MapControl.ZoomDuration = new TimeSpan(0);
this.MapControl.PanDuration = new TimeSpan(0);
control.MapControl.ZoomToResolution(ZoomLevel);
control.MapControl.PanTo(MapPoint());
this.MapControl.ZoomDuration = new TimeSpan(750);
this.MapControl.PanDuration = new TimeSpan(750);
Which seems to be working, but then mouse interaction becomes "crazy". Mouse scroll will make map jump and zoom to random places.
Is there known solution?
The problem is the second operation replaces the previous one. You would have to wait for one to complete before starting the next one. But that probably doesn't give the effect you want.
Instead zoom to an extent, and you'll get the desired behavior. If you don't have the extent but only center and resolution, you can create one using the following:
var zoomToExtent = new Envelope(point.X - resolution * MapControl.ActualWidth/2, point.Y, point.X + resolution * MapControl.ActualWidth/2, point.Y);
Btw it's a little confusing in your code that you call your resolution "ZoomLevel". I assume this is a map resolution, and not a level number right? The esri map control doesn't deal with service-specific levels, but is agnostic to the data's levels and uses a more generic "units per pixels" resolution value.
Im using Angular Kendo - Im not sure if thats really relevant only to say its not as 'simple' as calling refresh. - I have two scope variables one is the Kendo DataSource the other is the Kendo Chart Options which are assigned like this
$scope.ChartOptions = {
// All The other Chart Stuffs
dataSource : $scope.ChartDataSource
}
<div kendo-chart k-options="ChartOptions" />
This works fine - the issue is that the chart data can vary quite a bit and the area I'm using is small so what happens is the value axis ends up looking okay with values of just 2 or 3 but when you get to 20 or more the labels bunch up is there some way to reset the options after the data is retrieved. Maybe by changing the valueaxis skips etc.
What you are looking for is actually the CategoryAxis Step value. Based upon your data, you need to figure out what the max value is, and then calculate a reasonable step value that will appropriately render out your chart control based upon the space that you have. I can't really give you an example, as this will be entirely dependent upon your data and will likely require a bit of trial and error til you land on a calculation that yields acceptable results.
Documentation for the CategoryAxis step: http://docs.telerik.com/kendo-ui/api/dataviz/chart#configuration-categoryAxis.labels.step
Here is an example for finding the maximum data point:
var data = [1, 3, 4, 9, 10];
var max = Math.max.apply(Math, data);
//code here to do some kind of calculation of step value
Once you know what your appropriate step value should be based upon your data, you can then create your chart and set the CategoryAxis.Labels.Step value to it during grid creation.
I am trying to use the TransformToVisual method to get an Image element's absolute coordinates like this:
var transform = img.TransformToVisual( this ); // this is the current page
Point absolutePosition = transform.Transform( new Point(0, 0) );
For the first time I use it, this code returns an incorrect value (it is always 155,255). However, it always returns the correct coordinates afterwards.
This code runs in a Tap event handler, so the UI is already completely rendered when it is being executed. I tried calling InvalidateMeasure and InvalidateArrange (both on the Image element and on the page), but it did not help (I don't know if those calls have any connection whatsoever with TransformToVisual).
What could be the problem?
UPDATE: If I pin lock my phone and then unlock it, then the above issue does not happen.
UPDATE2: The position seems to be where the upper left hand corner of the image would be if it was at the center of the page. (The image's size is fixed 170x260. I get the coordinates 155,255. 2*155 + 170 = 480, 2*255 + 260 = 770 (okay the second one is not exactly 800, but it is suspicious anyway. The Application bar and the System tray are both hidden.))
UPDATE3: The problem occurs on the main page of my app. However, if I navigate to another page, then come back to the main page, it also works correctly.
I have an IP-camera that serves images. These images are then processed via EmguCV and then I want to display the processed images.
To show the images, I use this code:
Window1(){
...
this.Dispatcher.Hooks.DispatcherInactive
+= new EventHandler(Hooks_DispatcherInactive);
}
Hooks_DispatcherInactive(...)
{
Next()
}
Next() the calls calls the image processing methods and (should) display the image:
MatchResult? result = survey.Step();
if (result.HasValue)
{
Bitmap bit = result.Value.image.Bitmap;
ImageSource src = ConvertBitmap(bit);
show.Source = src;
...
}
This works fine when I hook up a normal 30fps webcam. But, the IPCam's images take over a second to get here, also when I access them via a browser. So, in the mean time, WPF shows nothing, not even the previous image that was processed.
How can I get WPF to at least show the previous image?
You can copy the image's buffer into a new BitmapSource image of the same format (PixelFormat, Height, Width, stride) using Create (from Array) or Create (from IntPtr) and display that BitmapSource in WPF's Image control,
or you can use DirectX to do that faster (for 30fps (and 1fps) the BitmapSource approach should do).
Also, consider NOT using events in the view, instead use bindings and commands.