How to have default (pre) zoom of category axis in amcharts 4? - graph

For a chart like this
https://codepen.io/team/amcharts/pen/NmNLoL
function categoryAxisZoomed(ev) {
var axis = ev.target;
var start = axis.getPositionLabel(axis.start);
var end = axis.getPositionLabel(axis.end);
console.log("New range: " + start + " -- " + end);
}
How can I add a pre zoom to max level so that when a page loads, I see only one category.
I want to do this only for mobile.
Any help would be appreciated
Thanks

Use zoom to values like this
function zoomAxis(pass parameters) {
valueAxis.zoomToValues("start", "end");
}
For references: http://www.amcharts.com/docs/v4/tutorials/zooming-axis-via-api-or-external-scrollbar/

Related

Unable to see 2D text sprites in Autodesk Forge

I'm trying to render 2D text using Sprites in the Autodesk Forge viewer, but I can't get it to show up. If I consult the layer by console I see that it contains the created Sprite but nevertheless I can’t see it in the scene. I have tried different scaling and position settings but no results.
I attach the code below:
function createText(text, preferencia, tamanyo) {
var sprite = spriteTexto("Prueba texto sprite", preferencia, tamanyo);
if (!NOP_VIEWER.impl.overlayScenes['overlaySprites'])
NOP_VIEWER.impl.createOverlayScene('overlaySprites');
NOP_VIEWER.impl.addOverlay('overlaySprites', sprite);
}
function spriteTexto(text, preferencia, tamanyo) {
var fontface = NOP_VIEWER.fontName;
var fontsize = 18; //tamanyo
var borderThickness = 4;
var borderColor = { r:0, g:0, b:0, a:1.0 };
var backgroundColor = { r:0, g:0, b:0, a:0.0 };
var textColor = { r:0, g:0, b:255, a:1 }; //hexadecimalARgb(preferencia.color);
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
context.font = "Bold " + fontsize + "px " + fontface;
var metrics = context.measureText( text );
var textWidth = metrics.width;
context.fillStyle = "rgba(" + backgroundColor.r + "," + backgroundColor.g + "," + backgroundColor.b + "," + backgroundColor.a + ")";
context.strokeStyle = "rgba(" + borderColor.r + "," + borderColor.g + "," + borderColor.b + "," + borderColor.a + ")";
context.fillStyle = "rgba(" + textColor.r+", " + textColor.g + ", " + textColor.b + ", 1.0)";
context.fillText( text, borderThickness, fontsize + borderThickness);
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
var spriteMaterial = new THREE.SpriteMaterial( { map: texture, useScreenCoordinates: false } );
var sprite = new THREE.Sprite( spriteMaterial );
sprite.scale.set(1*fontsize,1*fontsize,1*fontsize);
sprite.position.set(5,5,6);
return sprite;
}
I would be very grateful if you could help me find the error, thank you very much in advance for your help!
EDIT:------------------------------------------------
We want to render 2D text that can be interacted with (specifically select, rotate, and move).
To do this currently we are working with meshes (using MeshBasicMaterial, Mesh and TextGeometry), but it turns out that the text does not look perfectly sharp, it presents aliasing and we’ve found that according to the API reference, the antialiasing is not applicable to 2d.
Here are some examples of the problem, as you can see, the more we move away from the plane, the worse the text looks (and even up close it doesn't look perfect):
We were trying to make a test representing the text with Sprites (despite the fact that it would mean having to change the entire implementation already made with meshes) to try to implement it in another way that will solve the problem. But we see that it is not possible either.
How can we correct the rendering of the text then? Is there a way to fix it or is this the most we can get in 2D? We've tried searching for information on this but we haven't find anything helpful.
Unfortunately, Forge Viewer doesn't support THREE.Sprite at present. It uses a self-maintained three.js r71 and removes this support as I know.
Could you share the use case in detail on why you want to use THREE.Sprite with Forge Viewer? If you don't want to share that publicly, you can send it to forge (DOT) help (AT) autodesk (DOT) com.

Show ToolTip on Series data on mouseover , in System.Web.UI.DataVisualization.Charting

I am working with System.Web.UI.DataVisualization.Charting to create some line charts. I want to show tooltips(x and y value of the datapoint) when mouse over on a data point of a series.
As shown in the chart image, i want a tooltip when mouse is hovered on the red circle.
chart image
I added series.ToolTip method but , its not working.
here is my createSeries meothod
private System.Web.UI.DataVisualization.Charting.Series CreateSeries(List<X> xAxisData, List<Y> yAxisdata)
{
// Chart Series
System.Web.UI.DataVisualization.Charting.Series _series =
new System.Web.UI.DataVisualization.Charting.Series(this.SeriesNameList[this.seriesCount]);
_series.ChartType = this.ChartType;
// Bind the data
_series.Points.DataBindXY(xAxisData, yAxisdata);
// Set Default Properties
_series.Font = this.GetFontForSeries();
_series.LabelForeColor = this.GetLabelColor();
// Add Transparent Marker to increase mouse area for ToolTip
_series.MarkerStyle = System.Web.UI.DataVisualization.Charting.MarkerStyle.Circle;
_series.MarkerSize = 7;
_series.ToolTip = "hello";
//// Smart Labels
_series.SmartLabelStyle.Enabled = true;
_series.SmartLabelStyle.MinMovingDistance = 5;
_series.SmartLabelStyle.MaxMovingDistance = 50;
_series.SmartLabelStyle.MovingDirection =
System.Web.UI.DataVisualization.Charting.LabelAlignmentStyles.Top |
System.Web.UI.DataVisualization.Charting.LabelAlignmentStyles.TopLeft |
System.Web.UI.DataVisualization.Charting.LabelAlignmentStyles.TopRight |
System.Web.UI.DataVisualization.Charting.LabelAlignmentStyles.Bottom |
System.Web.UI.DataVisualization.Charting.LabelAlignmentStyles.BottomLeft |
System.Web.UI.DataVisualization.Charting.LabelAlignmentStyles.BottomRight |
System.Web.UI.DataVisualization.Charting.LabelAlignmentStyles.Left |
System.Web.UI.DataVisualization.Charting.LabelAlignmentStyles.Right |
System.Web.UI.DataVisualization.Charting.LabelAlignmentStyles.Center;
_series.SmartLabelStyle.IsOverlappedHidden = true;
_series.SmartLabelStyle.AllowOutsidePlotArea = System.Web.UI.DataVisualization.Charting.LabelOutsidePlotAreaStyle.Yes;
this.seriesCount++;
return _series;
}
private void InitializeChart()
{
this.Chart.IsMapEnabled = false;
this.Chart.RenderType = System.Web.UI.DataVisualization.Charting.RenderType.ImageTag;
this.Chart.ImageType = System.Web.UI.DataVisualization.Charting.ChartImageType.Png;
this.Chart.AntiAliasing = System.Web.UI.DataVisualization.Charting.AntiAliasingStyles.Graphics;
this.Chart.TextAntiAliasingQuality = System.Web.UI.DataVisualization.Charting.TextAntiAliasingQuality.High;
this.CreateTitle();
this.CreateLegends();
}
Can someone help me ?
I searched through some of the questios but couldn't find a solution.
You need to add the tooltip to the points.
Points.DataBindXY does not have a way of binding extended chart properties like tooltips. (Points.DataBind appears to, btw)
Source: http://blogs.msdn.com/b/alexgor/archive/2009/02/21/data-binding-ms-chart-control.aspx
So a workaround is to loop through your series points and add the tooltip manually to the points. You can do so using / modifying the code below. (#VALX and #VAL is one way of adding the XY coordinate without directly reading the value, another way would be to read the XY values directly)
// Bind the data
_series.Points.DataBindXY(xAxisData, yAxisdata);
// Set Tooltips
foreach(var point in _series.Points)
{
point.ToolTip = "(#VALX, #VAL)";
}
// Set Default Properties
_series.Font = this.GetFontForSeries();
_series.LabelForeColor = this.GetLabelColor();
Alternate way not using keywords:
// Bind the data
_series.Points.DataBindXY(xAxisData, yAxisdata);
// Set Tooltips
foreach(var point in _series.Points)
{
point.ToolTip = "(" + point.X + ", " + point.YValues[0] + ")";
}
// Set Default Properties
_series.Font = this.GetFontForSeries();
_series.LabelForeColor = this.GetLabelColor();

Full calendar ResourceView horizontal and vertical axis

I'm using the fullcalendar resourceviews fork version 1.6.1.6...
I used an older version which had the resources on the top and the times on the left axis.
But now it is different. The times are on the top and the resources are on the left axis. It's not that good anymore. Is there a way to change it?
I need the newer version of it because of the refetchResources function.
I modified the resource object (using Ike Lin fullCalendar) and added an array which includes the number of the day, start time and end time like 0 -> 09:00 -> 12:00, 1 10:00 -> 15:30 ...
Then I changed the fullcalendar.js
function updateCells() {
var i;
var headCell;
var bodyCell;
var date;
var d;
var maxd;
var today = clearTime(new Date());
for (i=0; i<colCnt; i++) {
date = resourceDate(i);
headCell = dayHeadCells.eq(i);
if(resources[i].anwesenheit[date.getDay()-1] != null){
var von = resources[i].anwesenheit[date.getDay()-1].von;
var _von = von.substring(0, 5);
var bis = resources[i].anwesenheit[date.getDay()-1].bis;
var _bis = bis.substring(0, 5);
headCell.html(resources[i].name + "<p style='font-weight: normal; font-size: 11px;'>" + _von + " - " + _bis + " Uhr</p>");
} else {
headCell.html(resources[i].name);
}
headCell.attr("id", resources[i].id);
bodyCell = dayBodyCells.eq(i);
if (+date == +today) {
bodyCell.addClass(tm + '-state-highlight fc-today');
}else{
bodyCell.removeClass(tm + '-state-highlight fc-today');
}
setDayID(headCell.add(bodyCell), date);
}
}
This shows the work time from each resource right unter the name of the resource.
Also I added a serverside function to the select function which checks if the resource is available. If yes, then the event will be created, else the event won't be created and I get an error message.
Now I can work with it. It's not exactly what I wanted, but it's nice to use now. It updates the times under the resource name on every day change so I have an overview when a resource is available and when it's not available.

Change color of past events in Fullcalendar

I'm trying to implement this solution to "grey out" past events in Fullcalendar, but I'm not having any luck. I'm not too well versed in Javascript, though, so I assume I'm making some dumb mistakes.
I've been putting the suggested code into fullcalendar.js, inside the call for daySegHTML(segs) around line 4587.
I added the first two lines at the end of the function's initial var list (Why not, I figured)—so something like this:
...
var leftCol;
var rightCol;
var left;
var right;
var skinCss;
var hoy = new Date;// get today's date
hoy = parseInt((hoy.getTime()) / 1000); //get today date in unix
var html = '';
...
Then, just below, I added the other two lines inside the loop:
for (i=0; i<segCnt; i++) {
seg = segs[i];
event = seg.event;
classes = ['fc-event', 'fc-event-skin', 'fc-event-hori'];
if (isEventDraggable(event)) {
classes.push('fc-event-draggable');
}
unixevent = parseInt((event.end.getTime()) / 1000); //event date in Unix
if (unixevent < hoy) {classes.push('fc-past');} //add class if event is old
if (rtl) {
if (seg.isStart) {
classes.push('fc-corner-right');
}
...
Running this code results in a rendered calendar with no events displayed and an error message: Uncaught TypeError: Cannot call method 'getTime' of null
The "null" being referred to is, apparently, event.end.getTime(). But I'm not sure I understand what exactly is going wrong, or how things are being executed. As written, it seems like it should work. At this point in the code, from what I can tell, event.end contains a valid IETF timecode, but for some reason it's "not there" when I try to run it through getTime()?
This isn't a mission-critical tweak for me, but would still be nice—and I'd like to understand what's going on and what I'm doing wrong, as well! Any help greatly appreciated!
If you are using FullCalendar2 with Google Calendar, you will need to use the version of the code below. This uses Moment.js to do some conversions, but since FC2 requires it, you'll be using it already.
eventRender: function(event, element, view) {
var ntoday = new Date().getTime();
var eventEnd = moment( event.end ).valueOf();
var eventStart = moment( event.start ).valueOf();
if (!event.end){
if (eventStart < ntoday){
element.addClass("past-event");
element.children().addClass("past-event");
}
} else {
if (eventEnd < ntoday){
element.addClass("past-event");
element.children().addClass("past-event");
}
}
}
As per FullCalendar v1.6.4
Style past events in css:
.fc-past{background-color:red;}
Style future events in css:
.fc-future{background-color:red;}
There's no need to fiddle with fullcalendar.js. Just add a callback, like:
eventRender: function(calev, elt, view) {
if (calev.end.getTime() < sometime())
elt.addClass("greyclass");
},
you just have to define the correct CSS for .greyclass.
Every event has an ID associated with it. It is a good idea to maintain your own meta information on all events based on their ids. If you are getting the events popupated from a backend database, add a field to your table. What has worked best for me is to rely on callbacks only to get the event ids and then set/reset attributes fetched from my own data store. Just to give you some perspective, I am pasting below a section of my code snippet. The key is to target the EventDAO class for all your needs.
public class EventDAO
{
//change the connection string as per your database connection.
//private static string connectionString = "Data Source=ASHIT\\SQLEXPRESS;Initial Catalog=amit;Integrated Security=True";
//this method retrieves all events within range start-end
public static List<CalendarEvent> getEvents(DateTime start, DateTime end, long nParlorID)
{
List<CalendarEvent> events = new List<CalendarEvent>();
// your data access class instance
clsAppointments objAppts = new clsAppointments();
DataTable dt = objAppts.SelectAll( start, end);
for(int i=0; i<dt.Rows.Count; ++i)
{
CalendarEvent cevent = new CalendarEvent();
cevent.id = (int)Convert.ToInt64(dt.Rows[i]["ID"]);
.....
Int32 apptDuration = objAppts.GetDuration(); // minutes
string staffName = objAppts.GetStaffName();
string eventDesc = objAppts.GetServiceName();
cevent.title = eventDesc + ":" + staffName;
cevent.description = "Staff name: " + staffName + ", Description: " + eventDesc;
cevent.start = (DateTime)dt.Rows[i]["AppointmentDate"];
cevent.end = (DateTime) cevent.start.AddMinutes(apptDuration);
// set appropriate classNames based on whatever parameters you have.
if (cevent.start < DateTime.Now)
{
cevent.className = "pastEventsClass";
}
.....
events.Add(cevent);
}
}
}
The high level steps are as follows:
Add a property to your cevent class. Call it className or anything else you desire.
Fill it out in EventDAO class while getting all events. Use database or any other local store you maintain to get the meta information.
In your jsonresponse.ashx, retrieve the className and add it to the event returned.
Example snippet from jsonresponse.ashx:
return "{" +
"id: '" + cevent.id + "'," +
"title: '" + HttpContext.Current.Server.HtmlEncode(cevent.title) + "'," +
"start: " + ConvertToTimestamp(cevent.start).ToString() + "," +
"end: " + ConvertToTimestamp(cevent.end).ToString() + "," +
"allDay:" + allDay + "," +
"className: '" + cevent.className + "'," +
"description: '" +
HttpContext.Current.Server.HtmlEncode(cevent.description) + "'" + "},";
Adapted from #MaxD The below code is what i used for colouring past events grey.
JS for fullcalendar pulling in Json
events: '/json-feed.php',
eventRender: function(event,element,view) {
if (event.end < new Date().getTime())
element.addClass("past-event");
},
other options ....
'event.end' in my Json is a full date time '2017-10-10 10:00:00'
CSS
.past-event.fc-event, .past-event .fc-event-dot {
background: #a7a7a7;
border-color: #848484
}
eventDataTransform = (eventData) => {
let newDate = new Date();
if(new Date(newDate.setHours(0, 0, 0, 0)).getTime() > eventData.start.getTime()){
eventData.color = "grey";
}else{
eventData.color = "blue";
}
return eventData;
}
//color will change background color of event
//textColor to change the text color
Adapted from #Jeff original answer just simply check to see if an end date exists, if it does use it otherwise use the start date. There is an allDay key (true/false) but non allDay events can still be created without an end date so it will still throw an null error. Below code has worked for me.
eventRender: function(calev, elt, view) {
var ntoday = new Date().getTime();
if (!calev.end){
if (calev.start.getTime() < ntoday){
elt.addClass("past");
elt.children().addClass("past");
}
} else {
if (calev.end.getTime() < ntoday){
elt.addClass("past");
elt.children().addClass("past");
}
}
}
Ok, so here's what I've got now, that's working (kind of):
eventRender: function(calev, elt, view) {
var ntoday = new Date();
if (calev.start.getTime() < ntoday.getTime()){
elt.addClass("past");
elt.children().addClass("past");
}
}
In my stylesheet, I found I needed to restyle the outer and inner elements to change the color; thus the elt.children().addclass addition.
The only time check I could get to work, lacking an end time for all day events, was to look at the start time - but this is going to cause problems with multi-day events, obviously.
Is there another possible solution?

How does one determine the height of a data point using the ASP.Net charting controls?

I have a stacked column chart like so:
I'm using a text annotation to display the $2495 in the rightmost stacked column. I've determined the proper y position experimentally - obviously that won't work for dynamically generated content.
Does anyone know how I can determine the height of the data points which compose the column? I presumed it would be something like:
Chart1.Series[0][0].Height + Chart1.Series[1][0].Height + Chart1.Series[3][0].Height + Chart1.Series[4][0].Height
But, alas, it is apparently not that simple. Any thoughts or insight would be greatly appreciate.
Check out this link
http://support2.dundas.com/OnlineDocumentation/WebChart2005/Custom_Drawing_Using_the_Paint_Event.html
See the examples at the bottom.
It turns out that it's all much simpler than I thought...the annotations use chart coordinates. This means that all you have to do is sum the actual values and use that as a y coordinate. I ended up doing this to calculate the heights of the respective series:
private int CalculateHeight(int i, ChartGraphics graphics)
{
var height = 0.0;
// find the respective heights of series i, add them together
for (var x = 0; x < this.Chart1.Series.Count(); x++)
{
height += this.Chart1.Series[x].Points[i].YValues[0];
}
return (int)height;
}
I then call that function like so:
for (var i = 0; i < chart.Series[0].Points.Count(); i++ )
{
var height = this.CalculateHeight(i, e.ChartGraphics);
this.Chart1.Annotations[i].Y = height + verticalPadding;
}
Much simpler than I thought.

Resources