fabric.js works with subclass - subclass

I try to create new class working with fabric.js framework. This class should consist of 3 simple objects: 2 text and 1 rectangle. One of text object should be updated by time, for example each second. The problem is new value does not appear on canvas as expected, but it updates every time when you select object. Here is my code. Could anyone explain me, what should I do to make it updates by time?
var canvas = new fabric.Canvas('c');
fabric.Tag = fabric.util.createClass(fabric.Group, {
type: 'PItag',
initialize: function() {
options = {};
options.top = 0;
options.left = 0;
var defaults = {
width: 100,
height: 40,
originX: 'center',
originY: 'center'
};
var defaults1 = {
width: 100,
height: 20,
originX: 'center',
originY: 'top',
top: -20,
backgroundColor: 'red'
};
var defaults2 = {
width: 100,
height: 20,
originX: 'center',
originY: 'top',
top: 0
};
var items = [];
items[0] = new fabric.Rect($.extend({}, defaults, {
fill: '#77AAFF',
}));
items[1] = new fabric.Textbox('PI tag name', $.extend({}, defaults1, {
textAlign: 'center',
fontSize: 14
}));
items[2] = new fabric.IText('####', $.extend({}, defaults2, {
textAlign: 'center',
fontSize: 16
}));
this.callSuper('initialize', items, options);
},
getTagName: function () {
return this._objects[1].text;
},
setTagName: function (value) {
this._objects[1].text = value;
},
getValue: function () {
return this._objects[2].text;
},
setValue: function (value) {
this._objects[2].text = value;
this.canvas.renderAll();
},
_render: function(ctx) {
this.callSuper('_render', ctx);
}
});
var pi = new fabric.Tag();
pi.setTagName("Unix time");
canvas.add(pi);
setInterval(function() {
pi.setValue(Math.floor((new Date()).getTime() / 1000).toString());
canvas.renderAll();
}, 1000);

var canvas = new fabric.Canvas('c');
fabric.Tag = fabric.util.createClass(fabric.Group, {
type: 'PItag',
initialize: function() {
options = {};
options.left = 100;
options.top=100;
var defaults = {
width: 100,
height: 40,
originX: 'center',
originY: 'center'
};
var defaults1 = {
width: 100,
height: 20,
originX: 'center',
originY: 'top',
top: -20,
backgroundColor: 'red'
};
var defaults2 = {
width: 100,
height: 20,
originX: 'center',
originY: 'top',
top: 0
};
var items = [];
items[0] = new fabric.Rect($.extend({}, defaults, {
fill: '#77AAFF',
}));
items[1] = new fabric.Textbox('PI tag name', $.extend({}, defaults1, {
textAlign: 'center',
fontSize: 14
}));
items[2] = new fabric.IText('####', $.extend({}, defaults2, {
textAlign: 'center',
fontSize: 16
}));
this.callSuper('initialize', items, options);
},
getTagName: function () {
return this._objects[1].text;
},
setTagName: function (value) {
this._objects[1].text = value;
},
getValue: function () {
return this._objects[2].text;
},
setValue: function (value) {
this._objects[2].set({ text: value });
this.canvas.renderAll();
},
_render: function(ctx,noTransform) {
console.log('xs')
this.callSuper('_render', ctx);
//ctx._objects[1].text = this._objects[1].text;
}
});
var pi = new fabric.Tag();
// canvas.pi.async = true;
pi.setTagName("Unix time");
canvas.add(pi);
setInterval(function() {
pi.setValue(Math.floor((new Date()).getTime() / 1000).toString());
canvas.renderAll();
}, 1000);
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.9/fabric.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="c" height="418" width="400" style="border: 1px solid rgb(170, 170, 170);"></canvas>
just change this function
setValue: function (value) {
this._objects[2].set({ text: value });
this.canvas.renderAll();
},

Related

amcharts5 - chart above another chart using same xaxis?

I am attempting to show a column chart (or a line chart would work too) above a gannt chart using the same xaxis (timestamp) and having trouble with spacing as well as getting any data to show in the column chart. I don't even know if this is possible to do, but the help docs made it sound like it was so I am more than likely missing quite a few things in the configuration or doing things wrong.
I've created a codepen with what I have so far. The original gannt chart shows fine, then I am able to get the column chart's yaxis to show (although it overlaps the gannt instead of being above it and does not show any data).
Any assistance/explanation with this would be appreciated.
// Set data
var data = [{
"State": "Idle",
"Start": 1424321864000,
"End": 1424321875000,
"Duration": 11
}, {
"State": "Idle",
"Start": 1424322649000,
"End": 1424322669000,
"Duration": 20
}, {
"State": "Idle",
"Start": 1424322970000,
"End": 1424322981000,
"Duration": 11
}, {
"State": "Idle",
"Start": 1424323093000,
"End": 1424323139000,
"Duration": 46
}, {
"State": "Active",
"Start": 1424323250000,
"End": 1424323268000,
"Duration": 18
}, {
"State": "Idle",
"Start": 1424323680000,
"End": 1424323703000,
"Duration": 23
}];
var mousekeys = [{
"Timestamp": 1424318400000,
"Clicks": "20",
"Keypresses": "30"
}];
/**
* ---------------------------------------
* This demo was created using amCharts 5.
*
* For more information visit:
* https://www.amcharts.com/
*
* Documentation is available at:
* https://www.amcharts.com/docs/v5/
* ---------------------------------------
*/
// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");
//font size theme
var myTheme = am5.Theme.new(root);
myTheme.rule("Label").setAll({
fontSize: 12
});
root.setThemes([
am5themes_Animated.new(root),
myTheme
]);
root.locale = am5locales_en_US;
//chartReg['chart'].utc = true; //force chart to show in UTC instead of device timezone
root.timezone = am5.Timezone.new('UTC'); //user timezone
//duration format
root.durationFormatter.setAll({
baseUnit: "second",
durationFormat: "hh'h' mm'm' ss's'"
});
//create chart
var chart = root.container.children.push(am5xy.XYChart.new(root, {
panX: false,
panY: false,
wheelX: false,
wheelY: false,
layout: root.verticalLayout,
marginTop: 0,
marginRight: 0,
marginBottom: 0,
marginLeft: 0,
paddingTop: 0,
paddingRight: 20,
paddingBottom: 20,
paddingLeft: 10,
}));
//zoom button
//chart.zoomOutButton.setAll({
// forceHidden: true, //disables zoom button
//});
chart.zoomOutButton.get("background").setAll({
fill: am5.color("#BDBDBD"),
});
chart.zoomOutButton.get("background").states.create("hover", {}).setAll({
fill: am5.color("#8a8a8a"),
});
chart.zoomOutButton.get("background").states.create("down", {}).setAll({
fill: am5.color("#707070"),
});
chart.zoomOutButton.get("background").states.create("active", {}).setAll({
fill: am5.color("#707070"),
});
//create axes
var yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, {
text: "State",
fontWeight: "500",
height: am5.percent(70),
categoryField: "State",
renderer: am5xy.AxisRendererY.new(root, {}),
tooltip: am5.Tooltip.new(root, {}),
}));
var yAxis2 = chart.yAxes.push(am5xy.ValueAxis.new(root, {
text: "Clicks",
fontWeight: "500",
height: am5.percent(30),
min: 0, //min 'hint', but not forced
//strictMinMax: true, //forces the min/max
//extraMax: 0.1, //extra 10% to the value range which acts as 'padding' to the yaxis
renderer: am5xy.AxisRendererY.new(root, {})
}));
//the order is top to bottom ends up bottom to top on the chart
yAxis.data.setAll([
{ State: "Idle" },
{ State: "Active" }
]);
//y-axis dash lines
var yRenderer = yAxis.get("renderer");
yRenderer.grid.template.setAll({
strokeDasharray: [6]
});
var xAxis = chart.xAxes.push(am5xy.DateAxis.new(root, {
baseInterval: { timeUnit: "second", count: 1 },
renderer: am5xy.AxisRendererX.new(root, {}),
tooltip: am5.Tooltip.new(root, {}),
tooltipDateFormat: "EEE, MMM dd # h:mm:ss a"
}));
//x-axis dash lines
var xRenderer = xAxis.get("renderer");
xRenderer.grid.template.setAll({
strokeDasharray: [6],
});
//series
var series = chart.series.push(am5xy.ColumnSeries.new(root, {
xAxis: xAxis,
yAxis: yAxis,
openValueXField: "Start",
valueXField: "End",
categoryYField: "State",
sequencedInterpolation: true,
tooltip: am5.Tooltip.new(root, {
//labelText: "[bold {Color} fontSize: 16px]{State}[/]\n[bold]Start :[/] {openValueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '#' h':'mm':'ss a\")}\n[bold]End :[/] {valueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '#' h':'mm':'ss a\")}\n[bold]Duration :[/] {Duration.formatDuration(\"hh'h' mm'm' ss's'\")}",
labelText: "[bold]Start :[/] {openValueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '#' h':'mm':'ss a\")}\n[bold]End :[/] {valueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '#' h':'mm':'ss a\")}\n[bold]Duration :[/] {Duration.formatDuration(\"hh'h' mm'm' ss's'\")}",
getFillFromSprite: false
})
}));
series.get("tooltip").get("background").setAll({
fill: am5.color("#ffffff"),
fillOpacity: 1,
strokeWidth: 2,
stroke: am5.color("#bbbbbb"),
});
//series columns
series.columns.template.setAll({
fillOpacity: 1,
stroke: 0,
strokeWidth: 0, //doesn't seem to work use 'stroke:0'
tooltipText: "{State}:\n[bold]{openValueX}[/] - [bold]{valueX}[/]"
});
series.columns.template.adapters.add("fill", function (text, target, key) {
//console.log(target);
//have to check for empty
//if(target.dataItem) {
if(target.dataItem.dataContext.State == "Active") {
return am5.color("#7bc07b"); //active
} else {
return am5.color("#55bfe6"); //idle
}
//} else {
// return null;
//}
});
//series
var series2 = chart.series.push(am5xy.ColumnSeries.new(root, {
name: "Clicks",
fill: am5.color("#679fd0"),
xAxis: xAxis,
yAxis: yAxis2,
valueYField: "Clicks",
valueXField: "Timestamp",
tooltip: am5.Tooltip.new(root, {
labelText: "{valueY}",
getFillFromSprite: false
})
}));
series2.get("tooltip").get("background").setAll({
fill: am5.color("#ffffff"),
fillOpacity: 1,
strokeWidth: 2,
stroke: am5.color("#bbbbbb"),
});
//series columns
series2.columns.template.setAll({
fillOpacity: 1,
stroke: 0,
strokeWidth: 0, //doesn't seem to work use 'stroke:0'
});
series2.get("tooltip").label.adapters.add("text", function (text, target, key) {
//console.log(target);
//have to check for empty
if(target.dataItem) {
return "Total : [bold]{Clicks}[/]\nTimestamp : [bold]{Timestamp}[/]";
} else {
return null;
}
});
//title
var title = chart.children.unshift(am5.Label.new(root, {
fontSize: 12,
textAlign: "left",
x: am5.percent(0),
y: am5.percent(0),
marginTop: 0,
marginRight: 0,
marginBottom: 30,
marginLeft: 0,
paddingTop: 0,
paddingRight: 0,
paddingBottom: 0,
paddingLeft: 0,
text: "some label"
}));
//cursor
var cursor = chart.set("cursor", am5xy.XYCursor.new(root, {
snapToSeries: [ series ],
snapToSeriesBy: "x",
behavior: "zoomX"
}));
cursor.lineX.set("visible", false);
cursor.lineY.set("visible", false);
//formatting
series.data.processor = am5.DataProcessor.new(root, {
dateFields: ["Start", "End"],
dateFormat: "xxxxxxxxxxxxx"
});
//formatting
series2.data.processor = am5.DataProcessor.new(root, {
numericFields: ["Clicks"],
dateFields: ["Timestamp"],
dateFormat: "xxxxxxxxxxxxx"
});
//scrollbar
chart.set("scrollbarX", am5.Scrollbar.new(root, {
orientation: "horizontal",
marginTop: 0,
marginRight: 0,
marginBottom: 30,
marginLeft: 0,
paddingTop: 0,
paddingRight: 0,
paddingBottom: 0,
paddingLeft: 0,
}));
//exporting
exporting = am5plugins_exporting.Exporting.new(root, {
dataSource: data,
dataFields: {
State: 'State', Start: 'Start', End: 'End', Duration: 'Duration'
},
dateFields: ["Start", "End"],
dateFormat: "MM/dd/yyyy hh:mm:ss a",
durationFields: ["Duration"],
durationFormat: "hh'h' mm'm' ss's'",
filePrefix: 'User Activity'
});
//add data
series.data.setAll(data);
series2.data.setAll(mousekeys);
//make stuff animate on load
series.appear(1000);
series2.appear(1000);
chart.appear(1000, 100);
yAxis and yAxis2 are not stacked. You have to be more explicit and add this line of code:
chart.leftAxesContainer.set("layout", root.verticalLayout);
If you want to place your column chart above, you need to push yAxis2 before yAxis or use unshift():
var yAxis2 = chart.yAxes.unshift(am5xy.ValueAxis.new(root, {
// ...
}));
I put your code below with these two little modifications:
// Set data
var data = [{
"State": "Idle",
"Start": 1424321864000,
"End": 1424321875000,
"Duration": 11
}, {
"State": "Idle",
"Start": 1424322649000,
"End": 1424322669000,
"Duration": 20
}, {
"State": "Idle",
"Start": 1424322970000,
"End": 1424322981000,
"Duration": 11
}, {
"State": "Idle",
"Start": 1424323093000,
"End": 1424323139000,
"Duration": 46
}, {
"State": "Active",
"Start": 1424323250000,
"End": 1424323268000,
"Duration": 18
}, {
"State": "Idle",
"Start": 1424323680000,
"End": 1424323703000,
"Duration": 23
}];
var mousekeys = [{
"Timestamp": 1424318400000,
"Clicks": "20",
"Keypresses": "30"
}];
/**
* ---------------------------------------
* This demo was created using amCharts 5.
*
* For more information visit:
* https://www.amcharts.com/
*
* Documentation is available at:
* https://www.amcharts.com/docs/v5/
* ---------------------------------------
*/
// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");
//font size theme
var myTheme = am5.Theme.new(root);
myTheme.rule("Label").setAll({
fontSize: 12
});
root.setThemes([
am5themes_Animated.new(root),
myTheme
]);
root.locale = am5locales_en_US;
//chartReg['chart'].utc = true; //force chart to show in UTC instead of device timezone
root.timezone = am5.Timezone.new('UTC'); //user timezone
//duration format
root.durationFormatter.setAll({
baseUnit: "second",
durationFormat: "hh'h' mm'm' ss's'"
});
//create chart
var chart = root.container.children.push(am5xy.XYChart.new(root, {
panX: false,
panY: false,
wheelX: false,
wheelY: false,
layout: root.verticalLayout,
marginTop: 0,
marginRight: 0,
marginBottom: 0,
marginLeft: 0,
paddingTop: 0,
paddingRight: 20,
paddingBottom: 20,
paddingLeft: 10,
}));
chart.leftAxesContainer.set("layout", root.verticalLayout); // <--- HERE
//zoom button
//chart.zoomOutButton.setAll({
// forceHidden: true, //disables zoom button
//});
chart.zoomOutButton.get("background").setAll({
fill: am5.color("#BDBDBD"),
});
chart.zoomOutButton.get("background").states.create("hover", {}).setAll({
fill: am5.color("#8a8a8a"),
});
chart.zoomOutButton.get("background").states.create("down", {}).setAll({
fill: am5.color("#707070"),
});
chart.zoomOutButton.get("background").states.create("active", {}).setAll({
fill: am5.color("#707070"),
});
//create axes
var yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, {
text: "State",
fontWeight: "500",
height: am5.percent(70),
categoryField: "State",
renderer: am5xy.AxisRendererY.new(root, {}),
tooltip: am5.Tooltip.new(root, {}),
}));
var yAxis2 = chart.yAxes.unshift(am5xy.ValueAxis.new(root, { // <--- HERE
text: "Clicks",
fontWeight: "500",
height: am5.percent(30),
min: 0, //min 'hint', but not forced
//strictMinMax: true, //forces the min/max
//extraMax: 0.1, //extra 10% to the value range which acts as 'padding' to the yaxis
renderer: am5xy.AxisRendererY.new(root, {})
}));
//the order is top to bottom ends up bottom to top on the chart
yAxis.data.setAll([
{ State: "Idle" },
{ State: "Active" }
]);
//y-axis dash lines
var yRenderer = yAxis.get("renderer");
yRenderer.grid.template.setAll({
strokeDasharray: [6]
});
var xAxis = chart.xAxes.push(am5xy.DateAxis.new(root, {
baseInterval: { timeUnit: "second", count: 1 },
renderer: am5xy.AxisRendererX.new(root, {}),
tooltip: am5.Tooltip.new(root, {}),
tooltipDateFormat: "EEE, MMM dd # h:mm:ss a"
}));
//x-axis dash lines
var xRenderer = xAxis.get("renderer");
xRenderer.grid.template.setAll({
strokeDasharray: [6],
});
//series
var series = chart.series.push(am5xy.ColumnSeries.new(root, {
xAxis: xAxis,
yAxis: yAxis,
openValueXField: "Start",
valueXField: "End",
categoryYField: "State",
sequencedInterpolation: true,
tooltip: am5.Tooltip.new(root, {
//labelText: "[bold {Color} fontSize: 16px]{State}[/]\n[bold]Start :[/] {openValueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '#' h':'mm':'ss a\")}\n[bold]End :[/] {valueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '#' h':'mm':'ss a\")}\n[bold]Duration :[/] {Duration.formatDuration(\"hh'h' mm'm' ss's'\")}",
labelText: "[bold]Start :[/] {openValueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '#' h':'mm':'ss a\")}\n[bold]End :[/] {valueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '#' h':'mm':'ss a\")}\n[bold]Duration :[/] {Duration.formatDuration(\"hh'h' mm'm' ss's'\")}",
getFillFromSprite: false
})
}));
series.get("tooltip").get("background").setAll({
fill: am5.color("#ffffff"),
fillOpacity: 1,
strokeWidth: 2,
stroke: am5.color("#bbbbbb"),
});
//series columns
series.columns.template.setAll({
fillOpacity: 1,
stroke: 0,
strokeWidth: 0, //doesn't seem to work use 'stroke:0'
tooltipText: "{State}:\n[bold]{openValueX}[/] - [bold]{valueX}[/]"
});
series.columns.template.adapters.add("fill", function (text, target, key) {
//console.log(target);
//have to check for empty
//if(target.dataItem) {
if(target.dataItem.dataContext.State == "Active") {
return am5.color("#7bc07b"); //active
} else {
return am5.color("#55bfe6"); //idle
}
//} else {
// return null;
//}
});
//series
var series2 = chart.series.push(am5xy.ColumnSeries.new(root, {
name: "Clicks",
fill: am5.color("#679fd0"),
xAxis: xAxis,
yAxis: yAxis2,
valueYField: "Clicks",
valueXField: "Timestamp",
tooltip: am5.Tooltip.new(root, {
labelText: "{valueY}",
getFillFromSprite: false
})
}));
series2.get("tooltip").get("background").setAll({
fill: am5.color("#ffffff"),
fillOpacity: 1,
strokeWidth: 2,
stroke: am5.color("#bbbbbb"),
});
//series columns
series2.columns.template.setAll({
fillOpacity: 1,
stroke: 0,
strokeWidth: 0, //doesn't seem to work use 'stroke:0'
});
series2.get("tooltip").label.adapters.add("text", function (text, target, key) {
//console.log(target);
//have to check for empty
if(target.dataItem) {
return "Total : [bold]{Clicks}[/]\nTimestamp : [bold]{Timestamp}[/]";
} else {
return null;
}
});
//title
var title = chart.children.unshift(am5.Label.new(root, {
fontSize: 12,
textAlign: "left",
x: am5.percent(0),
y: am5.percent(0),
marginTop: 0,
marginRight: 0,
marginBottom: 30,
marginLeft: 0,
paddingTop: 0,
paddingRight: 0,
paddingBottom: 0,
paddingLeft: 0,
text: "some label"
}));
//cursor
var cursor = chart.set("cursor", am5xy.XYCursor.new(root, {
snapToSeries: [ series ],
snapToSeriesBy: "x",
behavior: "zoomX"
}));
cursor.lineX.set("visible", false);
cursor.lineY.set("visible", false);
//formatting
series.data.processor = am5.DataProcessor.new(root, {
dateFields: ["Start", "End"],
dateFormat: "xxxxxxxxxxxxx"
});
//formatting
series2.data.processor = am5.DataProcessor.new(root, {
numericFields: ["Clicks"],
dateFields: ["Timestamp"],
dateFormat: "xxxxxxxxxxxxx"
});
//scrollbar
chart.set("scrollbarX", am5.Scrollbar.new(root, {
orientation: "horizontal",
marginTop: 0,
marginRight: 0,
marginBottom: 30,
marginLeft: 0,
paddingTop: 0,
paddingRight: 0,
paddingBottom: 0,
paddingLeft: 0,
}));
//exporting
exporting = am5plugins_exporting.Exporting.new(root, {
dataSource: data,
dataFields: {
State: 'State', Start: 'Start', End: 'End', Duration: 'Duration'
},
dateFields: ["Start", "End"],
dateFormat: "MM/dd/yyyy hh:mm:ss a",
durationFields: ["Duration"],
durationFormat: "hh'h' mm'm' ss's'",
filePrefix: 'User Activity'
});
//add data
series.data.setAll(data);
series2.data.setAll(mousekeys);
//make stuff animate on load
series.appear(1000);
series2.appear(1000);
chart.appear(1000, 100);
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
#chartdiv {
width: 100%;
height: 500px;
}
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
<script src="https://cdn.amcharts.com/lib/5/locales/en_US.js"></script>
<script src="https://cdn.amcharts.com/lib/5/plugins/exporting.js"></script>
<div id="chartdiv"></div>
You can see a column if you use the horizontal scrollbar and go completely to the left. The reason is there:
var xAxis = chart.xAxes.push(am5xy.DateAxis.new(root, {
baseInterval: { timeUnit: "second", count: 1 },
// ...
}));
Your interval is tiny (one second), so your column width is tiny. You have to tweak timeUnit or count in baseInterval if you want a wider column.

How to create gauge diagram with amchart 5 with arabic text in it

I want to create a gauge diagram with amcharts 5 with persian text on it. All the code sample I found is working correctly with english text on it. But when I want to use persian or arabic text (rtl languages), it doesn't show texts correct. How can I solve this problem?
Here is my code:
<script>
var root = am5.Root.new("chartdiv");
root.setThemes([
am5themes_Animated.new(root)
]);
var chart = root.container.children.push(am5radar.RadarChart.new(root, {
panX: false,
panY: false,
startAngle: 160,
endAngle: 380
}));
var axisRenderer = am5radar.AxisRendererCircular.new(root, {
innerRadius: -40
});
axisRenderer.grid.template.setAll({
stroke: root.interfaceColors.get("background"),
visible: true,
strokeOpacity: 0.8
});
var xAxis = chart.xAxes.push(am5xy.ValueAxis.new(root, {
maxDeviation: 0,
min: -40,
max: 100,
strictMinMax: true,
renderer: axisRenderer
}));
var axisDataItem = xAxis.makeDataItem({});
var clockHand = am5radar.ClockHand.new(root, {
pinRadius: am5.percent(20),
radius: am5.percent(100),
bottomWidth: 40
})
var bullet = axisDataItem.set("bullet", am5xy.AxisBullet.new(root, {
sprite: clockHand
}));
xAxis.createAxisRange(axisDataItem);
var label = chart.radarContainer.children.push(am5.Label.new(root, {
fill: am5.color(0xffffff),
centerX: am5.percent(50),
textAlign: "center",
centerY: am5.percent(50),
fontSize: "3em"
}));
axisDataItem.set("value", 50);
bullet.get("sprite").on("rotation", function () {
var value = axisDataItem.get("value");
var text = Math.round(axisDataItem.get("value")).toString();
var fill = am5.color(0x000000);
xAxis.axisRanges.each(function (axisRange) {
if (value >= axisRange.get("value") && value <= axisRange.get("endValue")) {
fill = axisRange.get("axisFill").get("fill");
}
})
label.set("text", Math.round(value).toString());
clockHand.pin.animate({ key: "fill", to: fill, duration: 500, easing: am5.ease.out(am5.ease.cubic) })
clockHand.hand.animate({ key: "fill", to: fill, duration: 500, easing: am5.ease.out(am5.ease.cubic) })
});
var i = 0;
var a = setInterval(function() {
if (i === 9) {
axisDataItem.animate({
key: "value",
to: Math.round(28),
duration: 100,
easing: am5.ease.out(am5.ease.cubic)
});
}
else if (i === 25) {
clearInterval(a);
}
else {
axisDataItem.animate({
key: "value",
to: Math.round(Math.random() * 140 - 40),
duration: 2000,
easing: am5.ease.out(am5.ease.cubic)
});
i++;
}
}
, 100);
var bandsData = [{
title: "لاغری مفرط",
direction: "rtl",
position: "right",
orientation: "rtl",
color: "#ee1f25",
lowScore: -40,
highScore: -20
}, {
title: 'لاغر',
color: "#f04922",
lowScore: -20,
highScore: 0
}, {
title: "نرمال",
color: "#fdae19",
lowScore: 0,
highScore: 20
}, {
title: "اضافه وزن",
color: "#f3eb0c",
lowScore: 20,
highScore: 40
}, {
title: "چاق",
color: "#b0d136",
lowScore: 40,
highScore: 60
}, {
title: "چاقی زیاد",
color: "#54b947",
lowScore: 60,
highScore: 80
}, {
title: "چاقی مفرط",
color: "#0f9747",
lowScore: 80,
highScore: 100
}];
am5.array.each(bandsData, function (data) {
var axisRange = xAxis.createAxisRange(xAxis.makeDataItem({}));
axisRange.setAll({
value: data.lowScore,
endValue: data.highScore
});
axisRange.get("axisFill").setAll({
visible: true,
fill: am5.color(data.color),
fillOpacity: 0.8
});
axisRange.get("label").setAll({
text: data.title,
inside: true,
radius: 15,
fontSize: "0.9em",
fill: root.interfaceColors.get("background")
});
});
chart.rtl = true;
chart.appear(1000, 100);
chart.rtl = true;
</script>
Final result is like this image:
amcharts5 result
I also searched about it in documentation of amcharts 5 but I couldn't find the answer.

How do I add an image to a label in AmChart5?

In data I have a am5.Picture object
icon = am5.Picture.new(root, {
height: 28,
src: src
});
The image fits on the text, is not inserted next to it
this doesn't work either
series.labels.template.set("text", "{icon} {name}") // return only name
Used Container
series.labels.values.forEach((label, index) => {
if (label.dataItem.dataContext.icon) {
let container = am5.Container.new(root, {
layout: root.horizontalLayout
})
container.children.push(label.dataItem.dataContext.icon)
container.children.push(
am5.Label.new(root, {
text: label.dataItem.dataContext.name,
fontSize: 10,
textAlign: "left",
centerY: am5.percent(50),
paddingLeft: 5,
})
)
label.children.clear()
label.children.push(container)
} else {
label.setAll({
fontSize: 10,
fontWeight: "300",
textAlign: "left",
maxWidth: 260,
oversizedBehavior: "wrap",
text: "{name}"
})
}
})

Animation - How to turn animated values into real values via interpolate

I'm trying to simultaneously restrict the values of my animation (using clamp as well as interpolate) but also get the values out of the interpolation so I can use them. Specifically because I want to update a piece of state with them and create an observable from that. I just can't figure out how to extract the 'real' value out of the AnimatedValue that is produced by the interpolation (in this case state.panValue). I've tried
this.state.panValue.value
and
this.state.panValue._value
and they come back as undefined. If anyone could help me out would be amazing!
EDIT: I'd also be really happy to just have the
this.state.pan.x
variable updated within the limits so I can skip the whole updating the state variable 'panValue' thing. A nice guy on Facebook suggested that I could implement this limit somehow inside the onPanResponderMove by switching the variable to a function or something but I've tried several things and all I get are errors, I guess because I don't really know how to 'safely' amend these animated values.
onPanResponderMove: Animated.event([
null,
{ dx: this.state.pan.x },
]),
Original Code:
import React, { Component } from 'react';
import {
View,
Animated,
PanResponder,
Text,
} from 'react-native';
import styles from './styles';
class ClockInSwitch extends Component {
constructor(props) {
super(props);
this.state = {
pan: new Animated.ValueXY(),
panValue: 0,
};
}
componentWillMount() {
this._animatedValueX = 0;
this._animatedValueY = 0;
this.state.pan.x.addListener((value) => {
this._animatedValueX = value.value;
this.setState({
panValue: this.state.pan.x.interpolate({
inputRange: [-30, 0, 120,],
outputRange: [-10, 0, 120,],
extrapolate: 'clamp',
}),
});
});
this._panResponder = PanResponder.create({
// Ask to be the responder:
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {
this.state.pan.setOffset({
x: this._animatedValueX,
});
this.state.pan.setValue({ x: 0, y: 0 });
},
onPanResponderMove: Animated.event([
null,
{ dx: this.state.pan.x },
]),
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
this.state.pan.flattenOffset();
Animated.timing(this.state.pan, {
toValue: 0,
duration: 500,
}).start();
},
onPanResponderTerminate: (evt, gestureState) => {
},
onShouldBlockNativeResponder: (evt, gestureState) => {
return true;
},
});
}
componentWillUnMount() {
this.state.pan.x.removeAllListeners();
}
render() {
const animatedStyle = {
transform: [{
translateX: this.state.panValue,
},
],
};
return (
<View>
<Text>{this.state.pan.x._value}</Text>
<View style={styles.buttonStyle}>
<Animated.View
style={[styles.sliderButtonStyle, animatedStyle]}
{...this._panResponder.panHandlers}
/>
</View>
</View>
);
}
}
export default ClockInSwitch;
I think this is what you're looking for. I'm using exponent so your declaration for vector icons would probably need to be changed. Cheers!
/**
* #providesModule ClockInSwitch
* #flow
*/
import React, {Component} from 'react';
import {View, Animated, StyleSheet, PanResponder, Text} from 'react-native';
import {FontAwesome} from '#exponent/vector-icons';
export class ClockInSwitch extends Component {
constructor(props) {
super(props);
this.state = {
pan: new Animated.ValueXY(),
panValue: 0
};
}
componentWillMount() {
this._panResponder = PanResponder.create({
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderGrant: (e, gestureState) => {
this
.state
.pan
.setValue({x: 0, y: 0});
},
//here's where you can check, constrain and store values
onPanResponderMove: (evt, gestureState) => {
// 300 is the width of the red container (will leave it to you to calculate this
// dynamically) 100 is the width of the button (90) plus the 5px margin on
// either side of it (10px total)
var newXVal = (gestureState.dx < 300 - 100)
? gestureState.dx
: 300 - 100;
this
.state
.pan
.x
.setValue(newXVal);
//set this state for display
this.setState({panValue: newXVal});
},
onPanResponderRelease: (e, {vx, vy}) => {
this
.state
.pan
.flattenOffset();
Animated
.spring(this.state.pan, {
toValue: 0,
duration: 400,
overshootClamping: true
})
.start();
this.setState({panValue: 0});
}
});
}
componentWillUnMount() {
this
.state
.pan
.x
.removeAllListeners();
}
render() {
//decouple the value from the state object
let {pan} = this.state;
let [translateX,
translateY] = [pan.x, pan.y];
let translateStyle = {
transform: [{
translateX
}, {
translateY
}]
};
return (
<View>
<Text style={styles.leftText}>Power Button Demo</Text>
<View style={styles.buttonStyle}>
<Animated.View
style={[styles.sliderButtonStyle, translateStyle]}
{...this._panResponder.panHandlers}>
<FontAwesome
name="power-off"
color="#EA2E49"
style={{
alignSelf: "center",
marginHorizontal: 10
}}
size={36}/>
</Animated.View>
</View>
<Text style={styles.rightText}>{this.state.panValue}: x value</Text>
</View>
);
}
}
export default ClockInSwitch;
const styles = StyleSheet.create({
sliderButtonStyle: {
borderColor: '#FCFFF5',
borderStyle: 'solid',
borderWidth: .5,
backgroundColor: '#FCFFF5',
borderRadius: 45,
height: 90,
width: 90,
justifyContent: 'center',
textAlign: 'center',
marginHorizontal: 5,
shadowColor: '#333745',
shadowOffset: {
width: 2,
height: 2
},
shadowOpacity: .6,
shadowRadius: 5
},
buttonStyle: {
borderColor: '#FCFFF500',
backgroundColor: '#DAEDE255',
borderStyle: 'solid',
borderWidth: 1,
height: 100,
width: 300,
justifyContent: 'center',
borderRadius: 50,
margin: 5,
flexDirection: 'column'
},
rightText: {
justifyContent: 'center',
textAlign: 'right',
fontWeight: '100',
marginHorizontal:15,
fontSize: 20,
color: '#FCFFF5',
marginVertical:25,
flexDirection: 'column'
},
leftText: {
justifyContent: 'center',
textAlign: 'left',
fontWeight: '100',
marginHorizontal:15,
fontSize: 24,
color: '#FCFFF5',
marginVertical:25,
flexDirection: 'column'
}
});

Jsplumb dragging connection to top does not create scroll

How can I create scroll when I drag jsplumb connections to the top of the browser?
I searched through the net but couldn't find a solution to create scrolls.
Click here to check the Demo
JSPlumb or JQuery
<script>
var targetDropOptions = {
};
connectorHoverStyle = {
lineWidth: 7,
strokeStyle: "#2e2aF8",
cursor: 'pointer'
}
//Setting up a Target endPoint
var targetColor = "#316b31";
var targetEndpoint = {
anchor: "LeftMiddle",
endpoint: ["Dot", { radius: 8}],
paintStyle: { fillStyle: targetColor },
//isSource: true,
scope: "green dot",
connectorStyle: { strokeStyle: targetColor, lineWidth: 8 },
connector: ["Flowchart", { curviness: 63}],
maxConnections: 1,
isTarget: true,
dropOptions: targetDropOptions,
connectorHoverStyle: connectorHoverStyle
};
//Setting up a Source endPoint
var sourceColor = "#ff9696";
var sourceEndpoint = {
anchor: "RightMiddle",
endpoint: ["Dot", { radius: 8}],
paintStyle: { fillStyle: sourceColor },
isSource: true,
scope: "green dot",
connectorStyle: { strokeStyle: sourceColor, lineWidth: 4 },
connector: ["Flowchart", { curviness: 63}],
maxConnections: 1,
// isTarget: true,
dropOptions: targetDropOptions,
connectorHoverStyle: connectorHoverStyle
};
jsPlumb.bind("ready", function () {
jsPlumb.animate($("#A"), { "left": 50, "top": 100 }, { duration: "slow" });
jsPlumb.animate($("#B"), { "left": 300, "top": 100 }, { duration: "slow" });
var window = jsPlumb.getSelector('.window');
jsPlumb.addEndpoint(window, targetEndpoint);
jsPlumb.addEndpoint(window, sourceEndpoint);
jsPlumb.draggable(window);
});
</script>
HTML
<div id="A" class="a window"
style="width: 100px; height: 100px; border: solid 1px;">
<strong>A</strong>
</div>
<div id="B" class="b window"
style="width: 100px; height: 100px; border: solid 1px;">
<strong>B</strong>
</div>
In my case I have one div with the properties position:relative and overflow:scroll and all shapes inside of this one make scroll up and down. I hope can help you.

Resources