AmCharts remove gap at start of serialChart - javascript

I am trying AmCharts for the first time and having trouble with one small thing. I created a graph using the following javascript:
dayGraph = new AmCharts.AmGraph();
dayGraph.valueField = "value";
dayGraph.type = "line";
dayGraph.balloonText = "<b>[[value]]</b>";
dayGraph.connect = false;
dayGraph.lineThickness = 2;
dayGraph.lineColor = "#8B0000";
dayGraph.fillColor = "#8B0000";
dayGraph.fillAlphas = 0.5;
chartCursor = new AmCharts.ChartCursor();
energyChart = new AmCharts.AmSerialChart();
energyChart.categoryField = "time";
/* energyChart.startDuration = 1;*/
energyChart.addGraph(dayGraph);
energyChart.categoryAxis.parseDates = true;
energyChart.categoryAxis.minPeriod = "mm";
energyChart.chartCursor = chartCursor;
energyChart.categoryAxis.equalSpacing = true;
It seems to work well, but I can't seem to find a way to remove the gap at the start of the graph (before the 00:00 value). The first data point is exactly at 00:00, so I would expect this point to sit on the vertical axis. Instead, there is a small gap. See the images below for how it currently is, and how I want it to look.
The current graph looks like this:
I want it to look like this:

Each serial chart already has categoryAxis property with a reference to CategoryAxis object. So you can just set it's startOnAxis property to true:
energyChart.categoryAxis.startOnAxis = true;
or, if you need to instantiate your own:
energyChart.categoryAxis = new AmCharts.CategoryAxis();
energyChart.categoryAxis.startOnAxis = true;
Whatever floats your boat.
Also, it's worth noting, that for date-based category axes, startOnAxis will work only if equalSpacing is set to true.

Related

How to move the mouse with webshot function inside a dygraph widget

I'm stuck because I can not achive what I want with a dygraph widget created in R.
I have this time series.
#library(xts)
dts <- xts::xts(c(10508,8465,3175,3816,4532,2735,2534,9541,8253,9962),
order.by = seq(from = as.Date("2022-02-01"), to = as.Date("2022-11-01"), by = "month"))
I can plot it in a dygraph widget
#library(dygraph)
object <- dygraph((dts),
ylab = "") %>%
dyRangeSelector(height = 20, strokeColor = "") %>%
dyOptions(fillGraph = FALSE, stackedGraph = FALSE, drawGrid = FALSE, strokeWidth = 3) %>%
dyHighlight(highlightSeriesOpts = list(strokeWidth = 3,highlightCircleSize = 10))
and save it in a html page.
#library(htmlwidgets)
saveWidget(object, "temp.html", selfcontained = FALSE)
Now, I would like to take a screenshot of the plot. I know I can do it with
webshot::webshot(url = "images/temp.html", file = "screenshot.png")
No problem with that. But I should hover the mouse near the last data point before the screenshot, because I would like the chart to show the information of the last point in the legend.
I have tried with
webshot::webshot(url = "images/temp.html", file = "screenshot.png"),
eval = "this.mouse.click(1781, 109);")
I got the X,Y coordinates injecting the following code in the inspection frame of the page.
<html onclick="display(event)">
function display(event) {
let X = event.clientX;
let X = event.clientX;
alert = (X + Y);
}
But it does not seem to work.
I get
but I would like something like this
Actually, I would like to hover the last point regardless the time series.
I know it could be done with ggplot and save me a lot of steps but the dygraph is mandatory and I would like to get the static plot from it.
I know also that it is maybe more of a javascript or casperjs question. If so I wouldn't mind repeat the question in the appropriate forum.
In advance, thank you very much for your help.

AmCharts animated line on map chart

I want to use amCharts for create connection map.
I take this demo: https://www.amcharts.com/demos/animations-along-lines
But, I want to have a growing line instead of an plane. Can this be implemented?
var planeImage = plane.createChild(am4core.Sprite);
planeImage.scale = 0.08;
planeImage.horizontalCenter = "middle";
planeImage.verticalCenter = "middle";
planeImage.path = "m2,106h28l24,30h72l-44,-133h35l80,132h98c21,0 21,34 0,34l-98,0 -80,134h-35l43,-133h-71l-24,30h-28l15,-47";
planeImage.fill = chart.colors.getIndex(2).brighten(-0.2);
planeImage.strokeOpacity = 0;
The issue can be closed.
I found solution from documentation: https://www.amcharts.com/docs/v4/tutorials/animating-map-lines-with-css/

AmCharts 4 handling null data

I am working on AmCharts where I load data dynamically. Sometimes, there may be null data sent from the response. I need to handle null data in AmCharts4.
In this link I see the example for Amcharts3 handling null data
var chart = am4core.create("reason_for_failure", am4charts.PieChart);
// Add and configure Series
var pieSeries = chart.series.push(new am4charts.PieSeries());
pieSeries.dataFields.value = "litres";
pieSeries.dataFields.category = "country";
pieSeries.slices.template.stroke = am4core.color("#fff");
pieSeries.slices.template.strokeWidth = 2;
pieSeries.slices.template.strokeOpacity = 1;
// This creates initial animation
pieSeries.hiddenState.properties.opacity = 1;
pieSeries.hiddenState.properties.endAngle = -90;
pieSeries.hiddenState.properties.startAngle = -90;
chart.data = [];
It looks like the sample code he provided is more/less straight out of one of our Pie Chart demos, e.g. Pie Chart With Legend, so I mixed and matched that with the solution in the mirror GitHub issue (demo link on the bottom).
Again, the beforevalidated event is perfect for handling the case of the chart.data being assigned an empty array, e.g.
chart.events.on("beforevalidated", function(event) {
// check if there's data
console.log(event.target.data.length);
if (event.target.data.length == 0) {
// handle null data here
}
});
It would have to be the beforevalidated event, because if there's no data, beforedatavalidated does not trigger.
Demo:
https://codepen.io/team/amcharts/pen/88d11b5385a2669319c1a0fcdaa1e199/

Openlayers feature not drawn without map refreshing

I am trying to draw the icon of the feature (defined as OpenLayers.Feature.Vector) after clicking on it (different than the original one, at the same point). The process of clicking works really good, however I want to change the graphic of clicked feature and I have problems with that.
What am I doing?
At first I declare both layers (one for the original, selectable feature and then for the one that should be drawn after the first one is selected) and add it to the map:
var firstLayer = new OpenLayers.Layer.Vector('Layer1');
map.addLayer(firstLayer);
var selectedLayer = new OpenLayers.Layer.Vector('Selected');
map.addLayer(selectedLayer);
The layers are clickable, proper handlers are attatched to them. What is more, I create styles for features that could be drawn on both layers:
// Styling feature of type1 for Layer1
type1Marker = openLayers.Util.applyDefaults(type1Marker, openLayers.Feature.Vector.style['default']);
type1Marker.externalGraphic = "somefile.svg";
type1Marker.pointRadius = iconsRadius;
type1Marker.fillOpacity = 1;
// Styling feature of type1 for Selected layer
type1MarkerSelected= openLayers.Util.applyDefaults(type1MarkerSelected, openLayers.Feature.Vector.style['default']);
eventObdConnectionLostIconSelectedStyle.externalGraphic ="somefile_selected.svg";
type1MarkerSelected.pointRadius = iconsRadius;
type1MarkerSelected.fillOpacity = 1;
// Styling feature of type2 for Layer1
type2Marker = openLayers.Util.applyDefaults(type2Marker, openLayers.Feature.Vector.style['default']);
type2Marker.externalGraphic = "somefile2.svg";
type2Marker.pointRadius = iconsRadius;
type2Marker.fillOpacity = 1;
// Styling feature of type2 for Selected layer
type2MarkerSelected= openLayers.Util.applyDefaults(type2MarkerSelected, openLayers.Feature.Vector.style['default']);
type2MarkerSelected.externalGraphic = "somefile2_selected.svg";
type2MarkerSelected.pointRadius = iconsRadius;
type2MarkerSelected.fillOpacity = 1;
Then some features for Layer1 are created at different points. I store those features in an array of features expanded by some additional data that I use later to distinguish the type of the marker that I want to use and I store the position of the marker on the map. And now there goes some logic that is executted after clicking on any feature :
var size = new OpenLayers.Size(30, 30);
var offset = new OpenLayers.Pixel(-(size.w / 2), -size.h);
var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png', size, offset);
var marker = new OpenLayers.Feature.Vector(closestPoint, icon);
var markerSel = new OpenLayers.Feature.Vector(closestPoint.event.point, icon);
switch (closestPoint.type) {
case "type1":
markerSel.style = type1MarkerSelected;
break;
case "type2":
markerSel.style = type2MarkerSelected;
break;
}
var selectedLayer = map.getLayersByName('Selected')[0];
if (selectedLayer.features.length != 0)
selectedLayer.removeAllFeatures();
selectedLayer.addFeatures(markerSel);
selectedLayer.redraw({ force: true });
What is going on is really weird for me, i.e.: after clicking on the marker from Layer1 nothing happens, then if I scroll out the map it disappears and finally when I scroll more, the marker is displayed with the style I wanted (that is selected one). Especially the disappearing of the feature from Layer1 is something that I do not get at all - why it disappears while no operations on that layer are performed? I would like to stack the new icon above the one from Layer1 (zOrdering of the map is set to true and the Layer1 is defined before the Selected layer).
Does anybody know what could cause the problem? I have spent several hours on trying to fix it but now I'm out of ideas. Thank you in advance!

Shadow map appearing on wrong place

I'm trying to make use of the built-in shadow map plugin in three.js. After initial difficulties I have more or less acceptable image with one last glitch. That one being shadow appearing on top some (all?) surfaces, with normal 0,0,1. Below are pictures of the same model.
Three.js
Preview.app (Mac)
And the code used to setup shadows:
var shadowLight = new THREE.DirectionalLight(0xFFFFFF);
shadowLight.position.x = cx + dmax/2;
shadowLight.position.y = cy - dmax/2;
shadowLight.position.z = dmax*1.5;
shadowLight.lookAt(new THREE.Vector3(cx, cy, 0));
shadowLight.target.position.set(cx, cy, 0);
shadowLight.castShadow = true;
shadowLight.onlyShadow = true;
shadowLight.shadowCameraNear = dmax;
shadowLight.shadowCameraFar = dmax*2;
shadowLight.shadowCameraLeft = -dmax/2;
shadowLight.shadowCameraRight = dmax/2;
shadowLight.shadowCameraBottom = -dmax/2;
shadowLight.shadowCameraTop = dmax/2;
shadowLight.shadowBias = 0.005;
shadowLight.shadowDarkness = 0.3;
shadowLight.shadowMapWidth = 2048;
shadowLight.shadowMapHeight = 2048;
// shadowLight.shadowCameraVisible = true;
scene.add(shadowLight);
UPDATE: And a live example over here: http://jsbin.com/okobum/1/edit
Your code looks fine. You just need to play with the shadowLight.shadowBias parameter. This is always a bit tricky. (Note that the bias parameter can be negative.)
EDIT: Tighten up your shadow-camera near and far planes. This will help reduce both shadow acne and peter-panning. For example, your live link, set shadowLight.shadowCameraNear = 3*dmax;. This worked for me.
You can also try adding depth to your table tops, if it's not already there.
You can try setting renderer.shadowMapCullFrontFaces = false. This will cull back faces instead of front ones.

Categories

Resources