How to programmatically set gridcount in Amcharts 4 - amcharts

I have a xychart with labels on the y axis. Every second label is being hidden:
Google suggests that I can set:
valueAxis.autoGridCount = false;
and:
valueAxis.gridCount
to the number of grids required by the data.
...but it doesn't have any effect, autoGridCount seems to be missing in the V4 documentation and there is no mention of it being removed.
How can I programmatically set gridcount?
EDIT: JSFiddle here

As you already figured out you can use axis.renderer.minGridDistance to show all labels:
categoryAxis.renderer.minGridDistance = 0;
To adjust the row height you can use series.columns.template.height to adjust the height of each element. I would suggest to set it to 100% and set a small border to the items:
series.columns.template.stroke = am4core.color('#fff');
series.columns.template.strokeWidth = 1;
series.columns.template.strokeOpacity = 1;
series.columns.template.height = am4core.percent(100);
To adjust the row height I would recommend increasing the chart height in general, because amcharts is trying to display all data in the area you provide. So increasing the height of the chart will cause all rows to have equal height and fill the provided area.
If you have varying data and don't know the number of rows, you can set the height of the chart dynamically according to the length of your data array and use an html scrollbar:
JavaScript:
document.getElementById('chart').style.height = `${chart.data.length * 50}px`;
HTML:
<div class="container">
<div id="chartdiv"></div>
</div>
CSS:
.container {
max-height: 300px;
overflow-y: auto;
}
#chartdiv {
min-height: 200px;
}
Here I created a code pen to show my suggestion.

Related

Svelte swipe animation works perfectly from top to bottom but not bottom to top

I am trying to achive a feature where the user will be able to drag a card component up or down for either extending the content and make the card cover the screen or close the card. The card is resting above a map.
I found this one svelte-gestures package with pan. It works like a sharm when the card sits on the top of the screen but when i put it at the bottom and try to get it to move up i run into all kind of diffcult models that doesnt work.
Here is the code that works with a card at the top extending its height downwards:
<script>
import { pan } from 'svelte-gestures';
let cardHeight = 100;
let initialY = 0;
let screenheight = window.innerHeight;
function handlePan(event) {
let delta = event.detail.y - initialY;
cardHeight += delta;
initialY = event.detail.y;
}
</script>
<div
use:pan="{{delay: 0}}"
on:pan="{handlePan}"
style="height: {cardHeight}px; background-color: lightblue; overflow: hidden; position: absolute; left: 0; right: 0;"
>
<!-- Card content here -->
<div style="height: {cardHeight}px;">
<h1>Card</h1>
<p>Extend and de-extend me!</p>
</div>
</div>
I tried using screenheight and inverting the logic but i just seem to run into very strange problems with the card lagging or flipping all over the place.
Any help would be appreciated!
Best Regards,
Rasmus

Gatsby-image-plugin layout constrained not working with dynamic images

I am trying to get an array of images of varying aspect ratios to fit nicely inside a modal - that is the modal will have a larger height for vertical images and smaller height for horizontals. I therefore do not want to specify a height in the graphql query because the images should scale down to fit their container.
const data = useStaticQuery(graphql`{
allFile(filter: {sourceInstanceName: {eq: "images"}, ext: {eq: ".jpg"}}) {
nodes {
id
name
relativeDirectory
childImageSharp {
original {
height
width
}
gatsbyImageData(quality: 100, layout: CONSTRAINED)
}
}
}
}
`);
I have passed the photos into a modal, a carousel, and a dummy div with height of 300pixels and the result is always the same: the images are huge and cropped to fit the container. When I set max height in the query to 500 pixels, everything works fine, but the verticals are much too tiny for the modal. When I set height on GatsbyImage directly, the images are the right size, but something is adding (Gatsby Image wrapper?) 1000 or so pixels of padding on the left and right sides of the image.
Carousel styles:
<div
ref={scrollContainer}
tabIndex={0}
css={`
max-width: 100vw;
max-height: 60vh;
overflow-x: auto; etc...
GatsbyImage styles:
<GatsbyImage
alt=""
objectFit='contain'
// above doesn't work
image={getImage(photo)}
key={photo.id}
// style={{ height: '60vh' }}
//above works but adds excessive padding somewhere
imgStyle={{ objectFit: 'contain' }}
//above doesn't work
/>

Scrollbar amchart legend

I want a scrollbar for a label when the label more then the chart height. I mentioned in image where I want scrollbar. Actually sometime I have many labels therefore.
As described in the Documentation here:
https://www.amcharts.com/docs/v4/tutorials/chart-legend-in-an-external-container/#Making_legend_scrollable
You need to put the Legend into an external div thats inside a wrapper div.
The Div Structure:
<div id="legendwrapper">
<div id="legenddiv"></div>
</div>
Putting the legend in the external div:
var legendContainer = am4core.create("legenddiv", am4core.Container);
legendContainer.width = am4core.percent(100);
legendContainer.height = am4core.percent(100);
Then you can make it scrollable by styling it like this:
#legenddiv {
width: 150px;
}
#legendwrapper {
max-width: 120px;
overflow-x: none;
overflow-y: auto;
}
A simple way to do this with AMCharts 4
chart.legend = new am4charts.Legend();
chart.legend.position = "right"; // Positionning your legend to the right of the chart
chart.legend.scrollable = true: // Make it scrollable
See a full example as below :
https://codepen.io/team/amcharts/pen/eYmLvoR

I have a nice way to speed up scatter plots in d3 if someone can help me with panning

This is related a question I posted earlier
d3 got slow all of a sudden
In that question, I pointed out a slowdown in d3.js that happened a few versions back (3.2). The slowdown is most noticeable in IE, but is definitely there in other browsers as well. The problem comes up when clicking the mouse, and it takes a long time (2.5 seconds in IE) before the mouse event even gets to our code. The problem is caused by the amount of data in the plot. Simple scatterplots do not have this problem.
No answers were forthcoming on the topic, so I am solving the problem a different way. I am using nested divs like this:
<div class = "plot_container" id = "thing_plot_container">
<div class = "ghost_container" id = "thing_ghost_container"></div>
</div>
And this set of styles:
div.plot_container {
position: relative;
margin:0px; padding:0px; /* insurance */
border: none;
}
div.ghost_container {
position: absolute;
margin:0px; padding:0px; /* insurance */
top: 0px;left: 0px;
width:0px; height:0px; /* width and height are irrelevant */
overflow: visible; /* insurance */
border: none;
}
This lets me put my d3.js plot in the outer plot_container div and a separate div in ghost_container that I attach mouse events to.
Here is the rest of the relevant code. First the main d3 svg:
var div = d3.select("body").append("div")
.attr("class","tooltip")
.style("opacity",0);
var viewportWidth = window.innerWidth - 40;
var viewportHeight = window.innerHeight - 80;
var svg = d3.select("#thing_plot_container").append("svg")
.attr("id", "mySVG")
.attr("width",viewportWidth)
.attr("height",viewportHeight)
.call(zoom)
.on("dblclick.zoom", null)
//.on("mousewheel.zoom", zoomFun)//for FF
.on("DOMMouseScroll.zoom", zoomFun)//for FF(1.7 or earlier)
.on("wheel.zoom", zoomFun)
.append("g")
.attr("class", "main")
.attr("transform","translate("+(left_shift)+","+(top_shift)+")");
And this is the ghost div overlaying the regular div:
//
// set up ghost/overlay svg element to handle mouse clicks
//
var use_overlay = true;
var catcherWidth = viewportWidth;
var catcherHeight = viewportHeight;
var svgns = "http://www.w3.org/2000/svg";
if (use_overlay == true){
var mouse_div = document.getElementById('thing_ghost_container');
var mouse_svg_container = document.createElementNS(svgns, "svg");
console.log('replace these magic numbers with viewportWidth and height');
mouse_svg_container.setAttribute("width",catcherWidth+"px"); // clips on chrome/ff if not done this way
mouse_svg_container.setAttribute("height",catcherHeight+"px");
mouse_div.appendChild(mouse_svg_container);
var rect_mouse = document.createElementNS(svgns, "rect");
rect_mouse.setAttribute("x",0);
rect_mouse.setAttribute("y",0);
rect_mouse.setAttribute("fill","blue");
rect_mouse.setAttribute("fill-opacity",0.05); // set this to 0.0 when working
rect_mouse.setAttribute("width", catcherWidth+"px");
rect_mouse.setAttribute("height", catcherHeight+"px");
rect_mouse.setAttribute("onclick", "ghost_click(evt)"); // this HAS to be evt to get all browsers cooperating
// leaving these mouse down/mouseup events to the original svg does not work. The overaly svg kills it
rect_mouse.setAttribute("onmousedown", "ghost_mousedown(evt)");
rect_mouse.setAttribute("onmouseup", "ghost_mouseup(evt)");
mouse_svg_container.appendChild(rect_mouse)
}
This works very well as far as it goes. This completely sidesteps the slowdown issue with element-heavy plots like scatter plots. The mouse click event immediately gets served this way. The problem is that I cannot grab with the mouse and pan my chart! I need help getting the mouse events passed into the d3 pan/zoom code.
Here is a fiddle showing what I have so far:
https://jsfiddle.net/pkrouse/5sbqchnn/

Mouse hover applied to jQPLOT X AXIS TICKS

I am trying to add mouse hover function to my axis ticks.
what i want is to show long ticks full text only on hover else it would be showing only few characters . i am adding a hover event to .jqplot-xaxis-tick .But it doesnot even respond to hover.Please suggest !
.jqplot-xaxis-tick {
top: 0px;
/* initial position untill tick is drawn in proper place */
left: 15px;
/* padding-top: 10px;*/
vertical-align: top;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.jqplot-xaxis-tick :hover{
overflow:visible;
white-space: normal;
width: auto;
position: absolute;
background-color:yellow;
}
The hover is not detecting because of the z-index of the canvas which lies on top of the whole chart. I did the following and now it's shorten the tootip by CSS ellipsis and show the tooltip with full name on hover.
Based on the Gyandeep's answer, the exact JS and CSS I used are,
Javascript:
$('div.jqplot-xaxis-tick').each(function (i, obj) {
$(this).prop('title', ($(this).text()));
$(this).css('z-index', 999); // this is important otherwise mouseover won't trigger.
});
CSS:
.jqplot-xaxis .jqplot-xaxis-tick {
position: absolute;
white-space: pre;
max-width: 92px; // Change it according to your need
overflow: hidden;
text-overflow: ellipsis;
}
The JavaScript part needs to be executed after every rendering of chart. It's better to put them right after plotting the chart and may in the AJAX success handler.
I managed to add a tooltip kindof feature to axis ticks.When I hover upon them it shows a separate box with full text else only 3-4 characters are shown.
The code is something like this
$($('.jqplot-xaxis-tick')[i]).bind('mouseover', function () {
// var m= '-webkit-marquee';
$($('.jqplot-xaxis-tick')[i]).css('white-space','pre-line');
$($('.jqplot-xaxis-tick')[i]).css('overflow','visible');
$($('.jqplot-xaxis-tick')[i]).css('width','auto');
$($('.jqplot-xaxis-tick')[i]).css('position','absolute');
$($('.jqplot-xaxis-tick')[i]).css('background-color','#666666');
$($('.jqplot-xaxis-tick')[i]).css('color','white');
$($('.jqplot-xaxis-tick')[i]).css('top','-45px');
// $($('.jqplot-xaxis-tick')[i]).css('overflow-x',m);
// console.log($($('.jqplot-xaxis-tick')[i]).text());
}).bind('mouseout', function () {
//var m= '';
//$($('.jqplot-xaxis-tick')[i]).css('overflow-x',m);
$($('.jqplot-xaxis-tick')[i]).css('white-space','nowrap');
$($('.jqplot-xaxis-tick')[i]).css('overflow','hidden');
$($('.jqplot-xaxis-tick')[i]).css('width','50');
$($('.jqplot-xaxis-tick')[i]).css('background-color','');
$($('.jqplot-xaxis-tick')[i]).css('color','grey');
$($('.jqplot-xaxis-tick')[i]).css('top','0px');
});
Here's the solution I'm using to display monthly high and low temperatures. Hovering over the x-axis tick will display an alert with the active month name and temps.
// Set up hover function
$('#monthlyTemps .jqplot-xaxis-tick').hover(function () {
setActiveColumn($(this));
});
// Set active column
function setActiveColumn(sender) {
// Display values
var monthName = sender.text();
var monthIndex = monthNames.indexOf(monthName);
var monthLowTemp = getMonthLowTemp(monthIndex);
var monthHighTemp = getMonthlHighTemp(monthIndex);
alert(monthName + ': ' + monthLowTemp + ' / ' + monthHighTemp);
}
// Get month low temp
function getMonthLowTemp(monthIndex) {
var value= $("#monthlyTemps .jqplot-point-label.jqplot-series-0.jqplot-point-" + monthIndex).text();
return value;
}
// Get month high temp
function getMonthlyHighTemp(monthIndex) {
var value= $("#monthlyTemps .jqplot-point-label.jqplot-series-1.jqplot-point-" + monthIndex).text();
return value;
}
var monthNames = new Array(12);
monthAbbreviations[0] = "Jan";
monthAbbreviations[1] = "Feb";
monthAbbreviations[2] = "Mar";
monthAbbreviations[3] = "Apr";
monthAbbreviations[4] = "May";
monthAbbreviations[5] = "Jun";
monthAbbreviations[6] = "Jul";
monthAbbreviations[7] = "Aug";
monthAbbreviations[8] = "Sep";
monthAbbreviations[9] = "Oct";
monthAbbreviations[10] = "Nov";
monthAbbreviations[11] = "Dec";

Resources