Apply zoom to multiple Amcharts 4 charts with jquery slider - javascript

I have a container with two or more XYCharts with dateAxis and I want to change the zoom for all my charts in the container at the same time, using a jQuery slider. I have tried to make the function below run, but it doesn't work.
$("#slider-range").slider({
animate: "fast",
range: true,
min: 0,
max: 1,
step: 0.01,
values: [0, 1],
slide: function (event, ui) {
for (var i = 0; i < container.children.length; i++) {
container.children[i].dateAxis[0].start = ui.values[0];
container.children[i].dateAxis[0].end = ui.values[1];
}
}
});
I always get the error message 'Cannot read property 'dateAxis' of undefined'
This is my code:
am4core.ready(function () {
am4core.useTheme(am4themes_animated);
container = am4core.create("container", am4core.Container);
container.width = am4core.percent(100);
container.height = am4core.percent(100);
container.layout = "vertical";
});
function createSimpleLineChart() {
var chart = container.createChild(am4charts.XYChart);
...
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.baseInterval = { "timeUnit": "second", "count": 1 };
...
return chart;
}

There are a couple of issues with your slide method:
1) You're going through your container's children incorrectly. The children property is not an array that you can directly index; it is a List object that has specific methods you can use to access each element. In this case, using the each method to loop through the children is the way to go.
2) There is no dateAxis property in the chart object. Each chart's axis objects are stored in the corresponding yAxes and xAxes properties, which are also List objects. Assuming each chart only has one date axis, you can access it directly by using getIndex. Also note that you might find calling the zoom method cleaner than modifying start and end directly.
Putting it all together:
slide: function (event, ui) {
container.children.each(function(chart) {
chart.xAxes.getIndex(0).zoom({start: ui.values[0], end: ui.values[1]}, false, true);
//chart.xAxes.getIndex(0).start = ui.values[0];
//chart.xAxes.getIndex(0).end = ui.values[1];
});
}
Demo below:
am4core.useTheme(am4themes_animated);
var container = am4core.create("container", am4core.Container);
container.width = am4core.percent(100);
container.height = am4core.percent(100);
container.layout = "vertical";
$("#slider-range").slider({
animate: "fast",
range: true,
min: 0,
max: 1,
step: 0.01,
values: [0, 1],
slide: function(event, ui) {
container.children.each(function(chart) {
chart.xAxes
.getIndex(0)
.zoom({ start: ui.values[0], end: ui.values[1] }, false, true);
//chart.xAxes.getIndex(0).start =ui.values[0];
//chart.xAxes.getIndex(0).end =ui.values[1];
});
}
});
createCharts();
function createCharts() {
var chart = container.createChild(am4charts.XYChart);
var data = generateData();
chart.data = data;
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.dateX = "date";
series.dataFields.valueY = "price";
series.tooltipText = "{valueY.value}";
series.name = "Series 1";
chart.zoomOutButton.disabled = true;
chart2 = container.createChild(am4charts.XYChart);
chart2.data = data;
var dateAxis2 = chart2.xAxes.push(new am4charts.DateAxis());
var valueAxis2 = chart2.yAxes.push(new am4charts.ValueAxis());
var series2 = chart2.series.push(new am4charts.ColumnSeries());
series2.columns.template.width = am4core.percent(50);
series2.dataFields.dateX = "date";
series2.dataFields.valueY = "quantity";
series2.yAxis = valueAxis2;
series2.tooltipText = "{valueY.value}";
series2.name = "Series 2";
chart2.zoomOutButton.disabled = true;
}
function generateData() {
var data = [];
var price = 100;
var quantity = 1000;
for (var i = 0; i < 300; i++) {
price += Math.round((Math.random() < 0.5 ? 1 : -1) * Math.random() * 100);
quantity += Math.round(
(Math.random() < 0.5 ? 1 : -1) * Math.random() * 1000
);
data.push({ date: new Date(2000, 1, i), price: price, quantity: quantity });
}
return data;
}
#container {
width: 95%;
height: 400px;
}
#slider-range {
width: 95%;
height: 10px;
border: 1px solid #000;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div id="container"></div>
<div id="slider-range"></div>

Related

Change the line color in a JavaScript line chart made by amCharts

I'm using amCharts to create a JavaScript line chart with amCharts. amCharts is an awesome open-source third-party plug-in like the chart.js for data visualization, but its javascript code is confusing.
In a demo line chart, I want to change the color of the line from blue to red (or any other colors). Unlike chart.js, I didn't find a place in the demo chart that allow me to add the color parameter. The JavaScript codes in HTML of this demo line chart is:
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<style>
#chartdiv {
height: 500px;
}
</style>
</head>
<body>
<div id="selectordiv"></div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Area Chart</h6>
</div>
<div class="card-body">
<div class="chart-line">
<div id="chartdiv"></div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://cdn.amcharts.com/lib/4/core.js"></script>
<script src="https://cdn.amcharts.com/lib/4/charts.js"></script>
<script src="https://cdn.amcharts.com/lib/4/themes/animated.js"></script>
<script src="https://cdn.amcharts.com/lib/4/plugins/rangeSelector.js"></script>
<script>
am4core.useTheme(am4themes_animated);
var chart = am4core.create("chartdiv", am4charts.XYChart);
chart.paddingRight = 20;
var data = [];
var visits = 10;
for (var i = 1; i < 50000; i++) {
visits += Math.round((Math.random() < 0.5 ? 1 : -1) * Math.random() * 10);
data.push({
date: new Date(2018, 0, i),
value: visits
});
}
chart.data = data;
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.renderer.grid.template.location = 0;
dateAxis.minZoomCount = 5;
dateAxis.groupData = true;
dateAxis.groupCount = 500;
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.dateX = "date";
series.dataFields.valueY = "value";
series.tooltipText = "{valueY}";
series.tooltip.pointerOrientation = "vertical";
series.tooltip.background.fillOpacity = 0.5;
chart.cursor = new am4charts.XYCursor();
chart.cursor.xAxis = dateAxis;
var scrollbarX = new am4core.Scrollbar();
scrollbarX.marginBottom = 20;
chart.scrollbarX = scrollbarX;
var selector = new am4plugins_rangeSelector.DateAxisRangeSelector();
selector.container = document.getElementById("selectordiv");
selector.axis = dateAxis;
// Add DatePicker
selector.events.on("drawn", function(ev) {
$(".amcharts-range-selector-range-wrapper input").datepicker({
dateFormat: "yy-mm-dd",
onSelect: function() {
selector.updateZoom();
}
});
});
</script>
</body>
</html>
The output of the chart is:
With the property stroke: am5.color('hexColor')
var series = chart.series.push(
am5xy.LineSeries.new(root, {
name: "Series",
xAxis: xAxis,
yAxis: yAxis,
valueYField: "value",
valueXField: "date",
stroke: am5.color('#f00'), // this property
tooltip: am5.Tooltip.new(root, {
labelText: "{valueY}",
}),
})
);
Ref: https://www.amcharts.com/docs/v5/charts/xy-chart/series/line-series/ & https://www.amcharts.com/docs/v5/concepts/colors-gradients-and-patterns/

How to set distance amchart line chart tooltip

I have problem to make my tooltip in amchart have to look nice, I just want to make that tooltip not struck down by other tooltip, this is my screen shoot amchart tooltip
how can I solve my problem? this is my code with amchart
< style > #chartdiv {
height: 280 px;
position: relative;
} < /style>
<!-- Chart code -->
< script >
am4core.ready(function() {
// Themes begin
am4core.useTheme(am4themes_kelly);
am4core.useTheme(am4themes_animated);
// Themes end
// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);
// Enable chart cursor
chart.cursor = new am4charts.XYCursor();
chart.cursor.lineX.disabled = true;
chart.cursor.lineY.disabled = true;
// Enable scrollbar
chart.scrollbarX = new am4core.Scrollbar();
// Add data
chart.data = <?php
echo $realisasi;
?>;
// Create axes
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.dataFields.category = "Date";
dateAxis.renderer.grid.template.location = 0.5;
dateAxis.dateFormatter.inputDateFormat = "yyyy-MM-dd";
dateAxis.renderer.minGridDistance = 40;
dateAxis.tooltipDateFormat = "MMM dd, yyyy";
dateAxis.dateFormats.setKey("day", "dd");
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
// Create series
var series = chart.series.push(new am4charts.LineSeries());
series.tooltipText = "{date}\n[bold font-size: 17px]realisasi: {valueY}[/]";
series.tooltip.valign = "middle";
series.dataFields.valueY = "realisasi";
series.dataFields.dateX = "date";
series.strokeDasharray = 3;
series.strokeWidth = 2
series.strokeOpacity = 0.3;
series.strokeDasharray = "3,3"
var bullet = series.bullets.push(new am4charts.CircleBullet());
bullet.strokeWidth = 2;
bullet.stroke = am4core.color("#fff");
bullet.setStateOnChildren = true;
bullet.propertyFields.fillOpacity = "opacity";
bullet.propertyFields.strokeOpacity = "opacity";
var hoverState = bullet.states.create("hover");
hoverState.properties.scale = 1.7;
function createTrendLine(data) {
var trend = chart.series.push(new am4charts.LineSeries());
trend.dataFields.valueY = "pakta";
trend.dataFields.dateX = "date";
trend.strokeWidth = 2
trend.stroke = trend.fill = am4core.color("#c00");
trend.data = data;
var bullet = trend.bullets.push(new am4charts.CircleBullet());
bullet.tooltipText = "{date}\n[bold font-size: 17px]pakta: {pakta}[/]";
bullet.strokeWidth = 2;
bullet.stroke = am4core.color("#fff")
bullet.circle.fill = trend.stroke;
var hoverState = bullet.states.create("hover");
hoverState.properties.scale = 1.7;
return trend;
};
// createTrendLine();
createTrendLine(<?php
echo $pagu;
?>);
}); // end am4core.ready()
< /script>
<!-- HTML -->
< div id = "chartdiv" > < /div>
Help me to solve my problem, or whether other solution to make my two tooltip is not struck down.
You didn't specify any sample data on your code, but try replacing valign:
series.tooltip.valign = "middle";
with pointerOrientation:
series.tooltip.pointerOrientation = "down";

How to add another column to this chart?

Here is the code to show the users ranking using amCharts Javascript library.
The code's output is something like this:
As you can see there are 6 users that are ranked from 1 to 6 all aligned to the left side of the page (The first group).
Now the problem is I want to continue ranking users from 7 to 12 (Second group) and align them to the right side of the page.
Something like this one :
Unfortunately, I can't handle this.
Here is the code on CodePen.
And here is the Javascript code:
am4core.useTheme(am4themes_animated);
var chart = am4core.create("chartdiv", am4charts.XYChart);
chart.data = [{
"profileName": "John",
"slogan": "Slogan Sentence Related to Profile Name 6",
"level": "6.",
"income": 0,
"bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Koen-VanGeert-circle-ScripturaEngage.png"
}, {
"profileName": "Sara",
"slogan": "Slogan Sentence Related to Profile Name 5",
"level": "5.",
"income": 0,
"bullet": "https://i1.wp.com/teacupwellness.com/wp-content/uploads/2018/03/Amanda-Blankinship-profile-circle.png?fit=300%2C300&ssl=1"
}, {
"profileName": "Nima",
"slogan": "Slogan Sentence Related to Profile Name 4",
"level": "4.",
"income": 0,
"bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Pauline-Suy-circle-ScripturaEngage.png"
}, {
"profileName": "Max",
"slogan": "Slogan Sentence Related to Profile Name 3",
"level": "3.",
"income": 0,
"bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Koen-VanGeert-circle-ScripturaEngage.png"
}, {
"profileName": "Megan",
"slogan": "Slogan Sentence Related to Profile Name 2",
"level": "2.",
"income": 0,
"bullet": "https://i1.wp.com/teacupwellness.com/wp-content/uploads/2018/03/Amanda-Blankinship-profile-circle.png?fit=300%2C300&ssl=1"
}, {
"profileName": "Inna",
"slogan": "Slogan Sentence Related to Profile Name 1",
"level": "1.",
"income": 0,
"bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Pauline-Suy-circle-ScripturaEngage.png"
} ];
// Chart A:
//create category axis for Names Column
var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "profileName";
categoryAxis.renderer.grid.template.location = -100;
categoryAxis.renderer.inside = true;
categoryAxis.renderer.labels.template.dy = -60;
categoryAxis.renderer.labels.template.dx = 200;
categoryAxis.labelsEnabled = false;
categoryAxis.renderer.labels.template.fontSize = 20;
categoryAxis.renderer.labels.template.fill = am4core.color("#4286f4");
//create category axis for Slogans Column
var categoryAxis2 = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis2.dataFields.category = "slogan";
categoryAxis2.renderer.grid.template.location = 100;
categoryAxis2.renderer.inside = true;
categoryAxis2.renderer.labels.template.dy = -20;
categoryAxis2.renderer.labels.template.dx = 200;
categoryAxis2.renderer.labels.template.fontSize = 12;
//create category level
var categoryAxis3 = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis3.dataFields.category = "level";
categoryAxis3.renderer.grid.template.location = 100;
categoryAxis3.renderer.inside = true;
categoryAxis3.renderer.labels.template.dy = -20;
categoryAxis3.renderer.labels.template.dx = 170;
categoryAxis3.renderer.labels.template.fontSize = 16;
categoryAxis3.renderer.labels.template.fill = am4core.color("#ccd3e0");
//create value axis for income and expenses
var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
valueAxis.renderer.opposite = true;
valueAxis.min = 0;
valueAxis.max = 10;
valueAxis.strictMinMax = true;
valueAxis.renderer.minGridDistance = 25;
valueAxis.renderer.labels.template.disabled = true;
valueAxis.disabled = true;
//create columns
var series = chart.series.push(new am4charts.ColumnSeries());
series.dataFields.categoryY = "profileName";
series.dataFields.valueX = "income";
series.name = "Income";
series.columns.template.fillOpacity = 0.5;
series.columns.template.strokeOpacity = 0;
// Do not crop bullets
chart.maskBullets = false;
chart.paddingTop = 64;
chart.paddingBottom = -30;
// Add bullets
var bullet = series.bullets.push(new am4charts.Bullet());
var image = bullet.createChild(am4core.Image);
image.horizontalCenter = "middle";
image.verticalCenter = "bottom";
image.width = 120;
image.height = 120;
image.dy = 0;
image.dx = 100;
image.y = am4core.percent(100);
image.propertyFields.href = "bullet";
image.tooltipText = series.columns.template.tooltipText;
image.propertyFields.fill = "color";
image.filters.push(new am4core.DropShadowFilter());
Html code:
<!-- Resources -->
<script language="JavaScript" src="amcharts4/core.js"></script>
<script language="JavaScript" src="amcharts4/charts.js"></script>
<script language="JavaScript" src="amcharts4/themes/animated.js"></script>
<div id="chartdiv"></div>
<link rel="stylesheet" href="Style.css">
<script src="Script.js"></script>
and CSS:
#chartdiv {
width: 1500px;
height: 840px;
}
body {
margin: 40 100 100 20;
background-color: transparent;
overflow:hidden;
font-family: "Helvetica Neue";
font-weight: 800;
src: url(helveticaneue-ultrathin.woff);
}
Any suggestions are extremely appreciated...

Add and Remove Custom attribute in fabric js

I am trying to draw grid on canvas with custom attribute. After that trying to remove that grid using those added custom attribute.
So Grid is showing on canvas, but when i am trying to remove the grid. it's not working.
Code
//Draw Grid
function draw_grid(){
var grid = 50;
canvas.getObjects().forEach(function(o) {
if(o.custom_class == 'canvas_grid') {
console.log(o.custom_class);
canvas.remove(o);
}
});
for (var i = 0; i < (600 / grid); i++) {
var grid_line1 = new fabric.Line([i * grid, 0, i * grid, 600], {
stroke: '#ccc',
selectable: false,
'custom_class' : 'canvas_grid'
});
canvas.add(grid_line1);
var grid_line2 = new fabric.Line([0, i * grid, 600, i * grid], {
stroke: '#ccc',
selectable: false,
'custom_class' : 'canvas_grid'
});
canvas.add(grid_line2);
}
}
draw_grid();
/* Hide/Show Grid */
$(document).on('change','#show_grid',function(){
if($(this).is(':checked'))
{
draw_grid();
}
else
{
canvas.getObjects().forEach(function(o) {
if(o.custom_class === 'canvas_grid') {
canvas.remove(o);
}
});
}
});
Codepen
https://codepen.io/dhavalsisodiya/pen/OQEzVE
Just change the visible property, no need to add and remove all time.
DEMO
var canvas = new fabric.Canvas('canvas1');
//Draw Grid
function draw_grid() {
var grid = 50;
var lines = [];
for (var i = 0; i <= 600; i += grid) {
lines.push(new fabric.Line([i, 0, i, 300],{stroke:'#000',strokeWidth: 2}));
}
for (var i = 0; i <= 300; i += grid) {
lines.push(new fabric.Line([0, i, 600, i],{stroke:'#000',strokeWidth: 2}));
}
gridObj = new fabric.Group(lines, {
selectable:false,
evented:false,
hoverCursor: 'auto',
left: -2,
top: -2,
visible:false
});
canvas.add(gridObj);
canvas.renderAll();
console.log(gridObj.toJSON())
}
draw_grid();
/* Hide/Show Grid */
$(document).on('change', '#show_grid', function() {
gridObj.visible = $(this).is(':checked');
gridObj.dirty = true;
canvas.renderAll();
});
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Show Grid: <input type="checkbox" id="show_grid" />
<canvas id="canvas1" width="600" height="300" style="border:1px solid #000000;"></canvas>
Here is codepen.
Or
Get all the objects having custom_class = canvas_grid property and remove them using canvas.remove(). Here is codepen.

How to render a Float32Array cube with vtk.js?

I want to render a 3D volume with vtk.js. My issue is that all the tutorials/examples in the vtk.js documentation load and render vti files. In my case, my data is just a Float32Array which contains the values of a 3D image. How can I volume-render that using vtk.js? I need a solution that creates no additional files on the file system.
I managed (with a coworker's help) to render a random cube volume like this:
// pseudo imports (avoids having to use fully qualified names)
var vtkFullScreenRenderWindow = vtk.Rendering.Misc.vtkFullScreenRenderWindow;
var vtkImageData = vtk.Common.DataModel.vtkImageData;
var vtkDataArray = vtk.Common.Core.vtkDataArray;
var vtkVolume = vtk.Rendering.Core.vtkVolume;
var vtkVolumeMapper = vtk.Rendering.Core.vtkVolumeMapper;
var vtkColorTransferFunction = vtk.Rendering.Core.vtkColorTransferFunction;
var vtkPiecewiseFunction = vtk.Common.DataModel.vtkPiecewiseFunction;
var VtkDataTypes = vtkDataArray.VtkDataTypes;
function initRandomCubeVolume() {
var width = 50, height = 50, depth = 50;
var size = width * height * depth;
var values = [];
for (var i = 0; i < size; i++) {
values[i] = Math.random();
}
var scalars = vtkDataArray.newInstance({
values: values,
numberOfComponents: 1, // number of channels (grayscale)
dataType: VtkDataTypes.FLOAT, // values encoding
name: 'scalars'
});
var imageData = vtkImageData.newInstance();
imageData.setOrigin(0, 0, 0);
imageData.setSpacing(1, 1, 1);
imageData.setExtent(0, width - 1, 0, height - 1, 0, depth - 1);
imageData.getPointData().setScalars(scalars);
var volumeMapper = vtkVolumeMapper.newInstance();
volumeMapper.setInputData(imageData);
volumeMapper.setSampleDistance(0.7);
var volumeActor = vtkVolume.newInstance();
volumeActor.setMapper(volumeMapper);
initProps(volumeActor.getProperty());
var view3d = document.getElementById("view3d");
var fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({
rootContainer: view3d,
containerStyle: {
height: '100%',
overflow: 'hidden'
},
background: [0, 0, 0]
});
var renderer = fullScreenRenderer.getRenderer();
renderer.addVolume(volumeActor);
renderer.resetCamera();
renderer.getActiveCamera().elevation(-70);
renderer.updateLightsGeometryToFollowCamera();
var renderWindow = fullScreenRenderer.getRenderWindow();
renderWindow.render();
}
function initProps(property) {
property.setRGBTransferFunction(0, newColorFunction());
property.setScalarOpacity(0, newOpacityFunction());
property.setScalarOpacityUnitDistance(0, 4.5);
property.setInterpolationTypeToLinear();
property.setUseGradientOpacity(0, true);
property.setGradientOpacityMinimumValue(0, 0, 5);
property.setGradientOpacityMinimumOpacity(0, 0.0);
property.setGradientOpacityMaximumValue(0, 1);
property.setGradientOpacityMaximumOpacity(0, 1.0);
property.setShade(true);
property.setAmbient(0.2);
property.setDiffuse(0.7);
property.setSpecular(0.3);
property.setSpecularPower(8.0);
}
function newColorFunction() {
var fun = vtkColorTransferFunction.newInstance();
fun.addRGBPoint(0, 0.4, 0.2, 0.0);
fun.addRGBPoint(1, 1.0, 1.0, 1.0);
return fun;
}
function newOpacityFunction() {
var fun = vtkPiecewiseFunction.newInstance();
fun.addPoint(0, 0);
fun.addPoint(0.5, 0);
fun.addPoint(0.5, 1);
fun.addPoint(1, 1);
return fun;
}
initRandomCubeVolume();
#view3d { height: calc(100vh - 20px); /* avoid scrollbar because of margins */ }
<script src="https://unpkg.com/vtk.js"></script>
<div id="view3d"></div>
Resistance is futile!

Categories

Resources