Transcript
This transcript was autogenerated. To make changes, submit a PR.
Hello everyone, my name is Reinaldi and I'm going to be giving the talk
using our own custom graphics library to show them naltics.
So before we begin, I'd like to give a big thank you to Mark
and rest of the Conf 42 team for organizing this amazing conference.
And I'm using to be enjoying learning from every one of the
speakers here. So I hope that you guys can enjoy learning from
every one of the speakers here, as well as to enjoy my particular talk as
well, and take some value out of it for your own needs.
So let's get into it a bit about myself. I'm a
founder and developer advocate, and I'm
a founder essentially of GrEs Studio and I'm a developer advocate in the
tech community. So I've been a speaker in the open source community for
about four years now, and for the past four years
I've been participating in various conferences talking about various issues
and talking about best practices such as
cloud based practices, security practices,
and also just talking in general about
projects that I'm working on, such as programming based projects based in Python
or JavaScript, or more such as that.
I'm a certified AWS solutions architect
and DevOps engineer professional as well as a CCNA,
and my personal field of interest is in penetration
testing, intrusion and other security related best practices.
So if you're interested in talking to me about it,
I'm always happy to basically hear you out and basically have
a good conversation with you about those topics.
On those side I run meetups, those occasional hackathon,
as I enjoy being able to learn from people in the hackathon,
as well as to be able to encourage people to develop
new solutions to solve problems within various
issues regarding the community and in general.
I also am a VR tech enthusiast,
so I really love being able to explore developments
in new VR applications and such.
So if you are also an advocate
of VR technology, and if you really enjoy
developing applications as well within VR and such,
then definitely chat me up. I'm really happy to talk about
developments, my own developments, and also in general, what developments there
currently are in the community and how we can best proceed with further
VR technology. So first off,
we're going to start off with talking about what to aim for in creating graphics
libraries. So first off, clear,
concise visuals is a must. When we create graphics libraries,
we need to ensure that the libraries we have can portray clear
message. People should be able to interpret what we are
writing easily inside those libraries. People need
to be able to see the graphics libraries,
the graphics that are portrayed from these libraries and just think, oh,
right, it's going to portray this particular threshold amount,
or it goes from x to Y and it's
trying to portray this particular thing and we
can see this particular pattern. So people need to be able to interpret
your graphics libraries very well. So you need to keep that in
mind when you create graphics libraries. Second off,
provide novel elements. So when I say novel elements,
I mean you need to put a distinguishing factor between you
and the other graphics libraries. So you need to
be able to have that. Why? Why should I use
your graphic library in particular compared to other graphics libraries?
What benefit do you have? For example, what benefit
do you have over the standard canvas library?
So it's all something that you need to take into consideration
while you're making those judgments. And essentially, you need to
have that why factor, and you need to also ask yourself,
why do you make that particular library? Can you
already actually have that libraries?
Can you already actually do what you need to do from other
libraries, or are you introducing something new that is
not yet available in other libraries? Third,
follow the errors guideline. And I'm using to be talking in depth about this in
the next couple of slides.
So before we go on, I need to stress that
an accustomed library doesn't mean no dependencies.
So when I say we're going to develop this from scratch,
I don't mean that we will exclude other graphics
libraries because reusability is
a very important part of software development. If we actually have
existing code that can actually help us in our development,
why not we use that? Why got we use already existing libraries
to also help us in developing new libraries. So some
examples of this is chart js,
canvas js, two js. So even if you're developing
a new library, it doesn't mean that you can't use them.
So the heirs guideline, it's a personal guideline which I established
myself. So first off, you need to decide
what the aim is. So when I talk about aim, I'm talking
about why you have that library. What are you trying to accomplish with
that library? So you need to have a clear aim,
such as why do you need
a new library in place, essentially? And what problem are
you trying to solve with those library? Are you trying to visualize temperature
data? Are you trying to visualize something else? It all
depends on you information.
What information do you want to display in the graph?
You need to think about the types of information that you can display
because each type of information can have different thresholds
and different types of measurements. That you need to put in place. For example,
say you will want to visualize temperature data or
particle matter data, or the number of
HTTP error responses. It all have very different graphical
implications and essentially you need to consider those
while you're going along, because every type of information
have different implications on what it means for your particular
use for making new graphics library. So you need to consider this while
you go along. Resilience.
Now, what comes to mind when resilience
is mentioned in this particular instance,
resilience is the adaptability towards various
threshold stretches that may be encountered by a graphics
library. Say for example,
you have temperature data and in your particular
city temperature data may only stretch between 20
and 30, but suddenly temperature
may jump up to 100. How will you visualize that?
Will you those to actually put in
a zero to 100 on a scale and actually have that to 20 to 30
on a flat line? Or can you actually
make those graphics library adaptable somehow to that particular
instance? And that's what I'm going to be talking about as well later on
and showing how you can make the graphics library adaptable
towards changes in data such that structure.
Structure, essentially in this kind of scenario means how will
you structure your libraries? What kind of structure do you
want your data to have? Do you want it to display a
particular bar graph? Do you want it to display line chart?
So essentially, how do you want to structure your data to
an extent to make the data clear, to be able to be
interpreted by people. So this is another very important factor that
you need to consider while creating graphics libraries.
All right, well, without further ado, we're just going to jump into the use
case directly. So I'm going to be showing a bit about how I implemented
my own library directly for my own use case.
Now, to give you a bit of context, in this particular context, I'm implementing
it for being able to record data based
on data that I've collected from my sensors. So essentially
how this works is that the data that I've collected
will be sent from my device to web
API cloud platform called Thinkspeak,
which is then in turn sends the data
to my visualization on
my website. And that visualization has
this custom graphics library implemented. So as
I said before as well, dependencies are definitely okay.
You need to strive to be able to use
those kinds of implementations in order to make your life easier.
So as you can see over here, those dependencies I particularly
use are jquery 1.1 as well as
canvas graphics library.
Next up, you need to plan out your functionality so
in my own personal use case, I have four steps,
and this is how you plan out functionality for a graphics library which aims
to retrieve HTTP requests as well from those server.
So start off with you need first initialize the variables.
You need to first initialize stuff such as what
is the step size that you want to make in your graphs? What is
your x minimum and x maximum, as well as
the y minimum and y maximum. How do you want to scale your
data essentially to be able to do this?
Next up, define the web based functions necessary
for the functionality. So these are
examples of HTTP and Ajax requests. And essentially
what you want to do is you want to be able to define in
such a way that these functions are ready for you to use in implementation,
and you can just call them and basically have them used as you
go along.
Define a core functions for the graphics library.
Now this is where you start implementing the core functions,
and I'm going to be showing you a bit about how to do it in
the next few slides as well. But essentially you need to be
able to show how to initialize the graphics that's going to be
made on the site and other core features of
the graphics as well that you use, and finally execute,
put into motion, draw it on your website, start putting it into motion,
and start retrieving data and such and start basically
putting data into motion and start the whole visualization in
motion. All right,
the first step of the whole process, initialize variables.
So as I mentioned, as you can see over here,
we're initializing some pretty
straightforward stuff, such as init. In this
case, init simply is a state.
So state is essentially a kind of a way to be
able to initialize what particular element,
if the graphics library is already drawn or not, based on the data that is
received, and Ajax.
In this case, we just declare it to be able to get XML
HTTP request object. And as you can see for Ymax
ymin y step, we have eight different values. This is because we have
eight different kinds of data that we are obtaining and eight different graphs
we want to draw. That's why we're specifying
eight different values based on the particular maximum
minimums that will most likely be associated with each particular
type of graph.
And we define a few more stuff, such as the data average
period and of course also the sending data
period, which is essentially the period of data
that will be sent to thinkspeak, for example, from the
device and specifying a time zone.
We specify also a sensor data
to also check if the sensor data is in or not and also
specify a URL target. In this case it's the Thinkspeak
website. And as you can see I specify my own channel and I'm going to
show you how to be able to use this in your code later.
And the other functions will be
talked about later as we go along these implementation.
So start off with, we start off with the old, good old getter,
and that goes with the getaxml HTTP request object
function should be really self explanatory if
you're used to using Ajax in JavaScript, but essentially
we're making an if else clause here.
So we want to be able to recognize if
the browser that is being used is an Internet Explorer
browser or if it's another browser. So for Explorer
and especially for the older versions, we need to
actually put in an activex object for the Ajax request.
If not, then we can assume that it's probably a new browser or new
version of engine Explorer and we can basically call
Ajax and instead take an XmL HTTP request.
So essentially it works to serve both cases.
So now we start off with having a function
to initialize the graphics.
So as you can see over here, we start
off with needing to draw basic graphic drawing
background. So we draw the x and y axis line,
cross line and the y scale text with this particular start
to the function. So that's why we have a for loop looping over eight times.
So as you can see over there we have capturing variables
of like x length, y length, and the
increments that we want to take as part of the step sizes.
So as you can see, we start also calling
those canvas library that we already managed
to import into the particular project in order
to start converting string first and
eventually start getting the element by id, to be
able to get the particular graph by the id, and we
start to use it to draw further functions.
If you're already used to using the canvas library, some of these will be pretty
straightforward, but I'm going to be just talking about these in general.
So most people here can probably
follow. So just some functions such as got context
to get in clear rectangle,
to be able to basically initialize
the canvas width and canvas height based on our specified parameters,
and some other customization stuff such
as declaring the line width and the stroke style.
So that's mainly for that particular
part of the code. And essentially we have another for loop
and this time we want to be able to draw the crossline background.
So for this we start off
by calling another for loop and basically putting it
to the extent of until it reaches basically
the step size that we put in place. So this
will mean that it starts off with the y length and plus 20.
So it'll continue on decreasing by the y increment value until it reaches
ten. And this will mean that it begins the path and it'll continue moving
towards the particular specified eye.
To be able to draw the crossline in the background and the horizontal lines
that are actually necessary. Same thing with the below
feature. We also are drawing vertical lines this time,
and we only draw the left and right most lines.
And probably it's not making as much sense right
now, but I'm going to be showing the visualization at the end,
so it definitely will make much more sense by then.
And for drawing the vertical line, as you can see at the bottom most code,
we're going with continuing to begin the
path and just moving the path,
creating a line to the path and declaring more of the fonts, such as
stroke, move to line to, and such.
Continuing with that. As you can see, we have continuing
modifications towards the font,
and we start off by drawing
an axis line. So this is where we draw the access line. We start
declaring a line width and stroke style, and again
begin path. So this time it's for the axis line compared
to the other ones. And afterwards we
then draw the text for the y scale. So we
start off by declaring the normal font standards,
such as declaring fonts first, fill style,
fill a text, align, and basically afterwards
just filling the text. And this is a particularly crucial part
of the text. So as you can see, we have a wide
difference variable there. So why do
we need a wide diff variable? We need it
for that adaptability purpose, as I mentioned before. So we're
calculating the difference between y max and y diff
in order to calculate the difference between the two. So essentially
what we're doing here is we're adapting the
particular text, the particular ranges
by the new maximum and the new minimum.
So basically we're scaling them accordingly.
And that's what I was saying about adaptability. We want
people to be able to see custom graphics library in such a
way that they do not omit
data, such as if we have a 100 when we have only a scale from
2030, so it'll scale the graphics
accordingly and it'll put new measurements as required.
And you don't have to worry about the graphics
library going over the limit either, or actually kind
of like being stuck with 100. Like only one
point has 100, while all the other data has a 20 and a 30.
Like sure, the data will be visualized, but because we put it on a period,
data will eventually keep moving leftwards and eventually disappear,
and afterwards it will scale back to 20 and 30 again. So outliers
will still be displayed for a short moment, but in the end it'll be
regulated to the point where we will go back to actually
just having the standard library and actually going back
to the standard measurement. So as long as we can
still have a period where it captures the data, we're still able to
represent the data correctly, but also still are
able to make it adaptable to the point where we don't have to worry about
that kind of data using neglected and not being
taken into account of individualizations. Because who knows, some of
those data may be necessary as well for if you need further
data analysis to be done. And as you can see over here,
that's why we have a y max minus y div for the fill
text function and such.
So some bored functions to add as part of the libraries.
So some of these functions, as you can see over here,
include stuff like getobserver data,
got web server data and get web server all data.
So getwebserver data in those
case we are using that to be able to retrieve the data from the
source URL through Ajax. Same as get web server for all data as
well. Essentially got web server all data has
a specified period of retrieving the web
server data though gets web server data, is just opening a connection
and being able to get the data in general and send that Ajax
request. So as you can see,
we're using our URL target variable here and we are opening
it based on particular specified string on the
URL that we have specified. So we're opening
it and we're pushing a get request on either method.
And as you can see, that's how more or less like both methods
will work. And afterwards we then
have a display all data function. So this
will display data in those form of rows and that's for another
segment of the website. So we can display the
data in the form of graph, but you can also display it in the form
of rows as well, should we require it.
So for this one we are basically deleting
the previous rows if there are any rows as
well, which is why we have the delete row function as
you can see over there. But before
that though, we of course declare table length first and
just go with the roast length variable that we declare.
And further towards the bottom,
we then declare variable as sensor
data. And we want to parse the data that is obtained
from those local storage. And that's why
we have local storage, sensor data
storage. And essentially if the sensor data is null,
it'll just return null. But afterwards we
just declare more variables as well, like the max length,
the tail, body and row
that is associated with the particular
data.
And continuing on from those, we then continue
on to basically declare
more of the variables in terms of
the, to establish the rows and the table. So as
you can see, we have declared
s as kind of like the container for taking
in the variables. And as you can see, we have different fields.
We have field one, field two up to field eight, and that's where
we basically start to take in the sensor data and portray it on the
table. So to do this, we then get the element by
id again, and we basically take up
the row and we insert it as a row and basically
it's inserted to the table that way, essentially towards
the bottom. You then start comparing those
data for each field data value for the
current data row to the field maximum and
minimum y values. As you can see, it's quite a long
line of code, so it basically is just
a list of while loops. So essentially it
first checks out if basically
the value is more than those maximum y value or less than a
minimum y value. So it'll update the appropriate maximum
and minimum y value accordingly based on fields. And as
I mentioned before, this is part of the adaptability feature that the
graphics library aims to have, so that you're able to adapt
your particular library accordingly. And as
you can see over here, we start to do it by
doing the while loops. After checking that the
sensor data does go above the y max or is
smaller than the y min, and afterwards adjust the y min
to decrease by a step if it's
less than a minimum, or increase by a step if it's by a
maximum.
All right, and we then move on to making a
function to draw. So now this is where it starts
to get pretty interesting as well. This is where we start to put
in a those drawing feature into the graphics library.
So as you can see here, we define a function called draw line
graphics. And what we do over here is we
first initialize basically
based on the graphics libraries, the graphic in it function
that we already created before.
So after this we then are able
to set sensor data to parse from local storage
again and set some more variables, such as
the data sensor length or the x increments
values and the current data period x length, y length.
So these are all stuff that we will use as variables within
the particular, within querying
the data to be able to be received as part of the
tables and the other implementations on the website. And also
we also collect values such as previous y
values and some values. And I'm going to be talking
more about that a bit more. Well, when we see
that code being used, variables being used in
the code. So we then go on
to declare for loop here. We go
on to calculate the timestamps essentially
at the created at field in the sensor data
and convert it to minutes and divide by data
average period. And then we finally round it. And you can see this by the
formula that is currently there from the current
data period. So we're essentially repeating this
until the x pause reaches to bigger than or equal to
30, because 30 was the value we specified as
those particular stopping point in the chart value
in terms of those length that we want
it to be. And afterwards
we then loop over all those eight data and
we then start to sum it all up.
So essentially for this one,
we then round up the timestamp period for the data
which is still within a particular period of time. And we basically
sum the value for every particular field.
And afterwards we just kind of like raise the counter by one every time
we finish that. So we're
doing this to be able to average then those
field sum values for the same time period, to be able to then portray the
data as best as we can based on the averages that are done
based on the sums of data. And this will help us to portray
the data in a much more efficient way. And averaging
those data helps us to keep track of the data better and be
able to further develop better analytics based
on the averaging data. And this especially helps
us to steer clear of potential outliers and such.
Continuing on, we continue on with another for
loop for this function. So as you can see,
for this particular one, we go on to basically
average the field sum values as mentioned before continuing
on from the last slide. And eventually we
are then able to set the
individual sum values and the individual sum
values are represented by I as the index. So we have that formula in
place to be able to take some values as those relative position from the
bottom to plot drawing, and we added
with 30 minus y towards
the bottom, basically.
Furthermore, from there we then continue on by
using canvas Ctx and canvas Id again, and also
declaring day, hour, minute, current time period and
closest hour xpause values variables in order
to further loop through all the eight graphics in order
to start drawing the necessary graphics.
So this is where we start drawing those tiny circle, for example on
the spot point. And basically this is where
we will start marking the particular points of data that
has been recognized. So as you can see, we have similar stuff
here as the previous slides, declan canvas id,
canvas Ctx and begin path
arc arcs where we start to actually
put in the specific data. So as you can see, we're starting
to draw center of a circle,
center of circle, pause at the
x pause basically at the exposition.
And essentially from there we then put
in those sum of values, the averaging, and we then
basically go about it with creating
it with radius three. And afterwards just
some additional customizations, putting a red as the
color of those particular circles and just filling it in.
And we then have a conditional.
So to check if the x pause is equals to
x length plus 30, we then basically at
the beginning of the graphic, which is the most right part,
we then put timescale text in the canvas and
basically get the day, hour and minute
from the current at data to calculate the
nearest hour to the end of the graph. So this will help us parse
the data in terms of days, hours and minutes.
And you can see the implementation towards the bottom
and get the current time period and the closest
hour towards the exposition
that is currently made in order towards
the current time period that is currently available.
And initialize some more fonts for us to be
able to visualize the kind of data.
And yeah, continuing from there, just more fonts with font
style text align. And also for
being able to put a time mark for every 2 hours starting
from the closest x hour position. We use the
for loop looping, kind of like a mechanism for
initializing the variable k as a closest hour exposition.
And we continue on to put the time mark at the particular
location where we have decided that we should
based on the current part of k. And that's why we
fill text at k. And we
then go initialize the variable hour to display,
to display the hour plus time zone and
also check if the hour to display is bigger
than recruit 24. And if so, we put it in a
standard, kind of like a visualization.
And afterwards we then fill in the
text and we then do this to
draw a vertical line at those point. And these vertical lines are
going to make sense once you see the graphics visualization as well.
So just standard stuff, just using move to line two
and stroke again to be able to do so. And another
check for if the
hour is smaller than zero, then yeah, we'll just add to
the hours, basically 24 to the hours.
And this is where the tricky part starts we finished all our
functions that we need to make. We finished making our request
functions. We've finished making our graphics library specific
functions. Now we just have to start putting it all together and making the
Ajax requests. So in order to
do this, we then start making
an Ajax already state change function.
So afterwards we then start to
check if the statuses are currently already received correctly.
And we do this by checking the Ajax status. So as you can see over
there, if we put an Ajax status, if it's bigger than 200
and smaller than 300, or if it's
actually those hundred and four, then yeah, sure it can got to go through,
otherwise it'll just return an error. So afterwards
we then go ahead with initializing
a display data variable in order to check if the data is going to be
displayed or not based on if the
data has already been received. So afterwards we
then check if the init variable is zero and in it,
as I mentioned before, is a variable to check essentially if
the data is already visualized. So here
we are putting in variables as string sensor data to put
a response text, putting a header length and
essentially to be able to search through feeds
to be able to retrieve the particular header length
and essentially get also added to the time zone
and also search for data n which
we get by using the length function.
And from there we then continue on
by doing a window local storage in order to set the
particular item as the sensor
data storage and go on to
declare another web get timer function to set an interval.
And as you can see over there, we start getting
the web server data. And with those
we're basically putting 120,000
milliseconds, which is a two minute interval. So we're waiting for 120,000
milliseconds before we are actually getting
to get the data that is retrieved.
And since we already done
it one time, we can basically continue on
and set the inlet to one so that the routine will
read the initial historical data will not run again and
the new data will be available. So we'll set
display data to one to enable to display the new data that has
already been received. However, if the n
is got one, not zero,
we will just continue on with saving the
new read data from the web server to a variable with the
new read data function where we parse
the JSON based on response text. And we
then set sensor data to parse
with JSON those local storage and get
the sensor data storage from the local storage and we
will get the id of the latest data and check whether
it is the same with the latest one in the local storage.
And we do this with the data length and
latest id variables being declared and we
go on to basically check if
the new read data entry id is equal to the latest
id and if so then we will add the latest data and store
back to those local storage and we'll push that data and we
will stringify that data and we will set the item as necessary
and set the display to one, essentially as
an alternate scenario to if the init was a zero.
And finally we will start displaying the fields. So this is where
we start creating variables such as create a transform, so new
read data and created at time.
And basically this is just to be able to set more variables,
just to be able to check if the data was created at
a particular time and basically to be able to display
the current data results on the left side
of those whole visualization, to be able to
recreate as well the created data format that
was made basically during the coding as well. So basically
it's just checking when the created time was
and just putting in behaviors, if so.
And finally we can then display
the data by doing a document get element by id
and basically getting the data and displaying it in the new read data
field. And this can be then put into motion in HTML,
which I will show in the next slide. And that's pretty much all
of it for being able to put the data into visualization.
And of course some good HTML and CSS for
supporting the JavaScript that we have already implemented. Because after all,
HTML is our main pillar of support for our whole website.
So as you can see, we're putting quite
a number of our functions into play here. So we can start
declaring the necessary construction of the
table that we want of the latest variables
you want. So as you can see over there, that's why we put number of
fields to be displayed for the HTML code.
And we also put the canvas
library to motion as well here. And that's where we start drawing
with our customs graphic library. We start basically drawing
with canvas. Also the number of fields
that are currently, we have currently already specified,
and we also have the CSS.
As you can see, we basically can specify more
fonts that are necessary for use in the website
and just declare more containers and labels. So I'm
not using to be going too deep into this because we're focusing only on the
JavaScript side. It's creating a JavaScript library after all,
but it's just an example of how it's used on
the HTML and CSS side and finally,
it'll result in something like this. As you can see, we have our
latest data on the left, our results on the right,
our table of results, and our visualization
of charts which we made using our own graphics libraries at the middle.
And this is an example of when the whole visualization
is populated with data. And as you can see, we have those small circles
which we created through the
function that we already defined on there. And as
you can see, at first this is based on in it,
but now after initializing it, after collecting
data, it'll continue collecting new data and it'll continue
moving toward the data towards the left, and it'll continue
inputting new data from the right and it
can adapt based on the maximum and minimum data, as I
mentioned before. And that's what I mean by the data not being
able to actually outlier data,
not being able to ruin the data, because at some point with our specified interval
it'll eventually be off those chart anyway. So it won't those
much of a problem and it'll continue moving on
until it's out of sight.
So to wrap up, it's not hard to make your own libraries.
Definitely takes a bit of practice, but once you know more or less
like what you want to make, the aim errors,
guidelines mentioned before, and pretty much just go
ahead with it and just give it a try. And making a custom
one is great, but remember that you can still use dependencies if needed. Don't be
afraid to use a canvas as a dependency or two js
or other canvas libraries that are available. As long as you are
able to meet your particular objective and help solve a problem, then it's all
good. And of course experiment,
experiment, experiment. It takes a long while to be able to find
the perfect library that can really match your needs. It takes lots of
research, and if you're creating a library especially,
you'll need to be able to research which dependencies you need as well,
what tools you'll need, how to be able to best code it, and how to
be able to make it most efficient. Even until now, I'm still looking for a
way to make my library efficient as I share in the open source community.
As one of the biggest things that you need to keep in
mind in sharing these kinds of libraries is of course the readability
and how the open source community can best perceive it.
Because people won't really have a use for a library that is
not able to be read clearly or actually is not
easily understandable or has no function. So you need to experiment with
the best approaches you need to make and how you can actually best approach
it in the open source community to have people adopt the library and
actually have them also use it for their own purposes as well.
So that's all for me. Thank you so much for listening to my
talk. And before we close up,
remember to connect with me if you have any questions, or if you would like
to talk to me about anything else I mentioned before. If you have any interesting
insights about any of the topics I mentioned, or if you have any interesting insights
about any of the topics code I've
talked about, then feel free to share it with me. I'm happy as well to
talk to you about it. So remember, you can connect with me
with my twitter at Reynold G or through
my LinkedIn at Reynoldsbroto. So thank
you again, and I hope you enjoy the rest of the talks at the conference.