[MUSIC PLAYING]
BRIAN YU: OK.
Welcome back to CS50 Beyond.
Hope you're all staying warm.
So we'll pick up where we left
off, diving a little bit more
into JavaScript.
Goal of this afternoon is look at
a couple other JavaScript features
just to give some more exposure, show
you what kinds of things do exist,
and how you can use JavaScript
to build user interfaces.
And then we'll dive a little
more into user interfaces.
In particular, today,
looking at animation,
animation which we can create
using both CSS and JavaScript just
to liven up pages, make them
a little bit more interactive,
make them a little more
aesthetically pleasing.
And we'll get an
opportunity to play around
with the types of web
applications we can create
once we have the ability to draw
shapes and create animations
all across the screen.
So we'll start by looking at
one JavaScript feature, which
a couple of people were asking me
about earlier this morning, which
is the idea of doing
something repeatedly
and recurringly in
over a fixed interval.
And so if we take a look at inside
the interval.HTML, what we'll see
is inside the body we have an
H1 that has ID of counter that
initially is just set to zero.
And then we have, very similar to what
we had before, a counter variable that
equals zero and a function
called count that increments
the counter and then
just updates the counters
HTML to be whatever the new
value of the counter is.
But here's the interesting
part, when the DOM content
is loaded we run this function called
set interval, count, and 1,000.
So what this is basically saying
is every 1,000 milliseconds,
or every second, run the
count function again.
And the result of that is--
I can open up interval.HTML.
And then without doing
anything, every one second we're
just going to increment that
counter again and again and again.
So you could do this type of thing
to implement like a timer feature,
for instance.
So if you wanted to go back into the
quiz application you made this morning
and had a timer to see,
OK, how quickly can you
get through all of the questions?
You could do something like this
to keep track of a running timer
as you go through the game in order
to keep track of how long something
is taking you, for instance.
Or if you want for some
action to take place
every so often on your
web application, you
can use intervals to do that as well.
Now, one thing you may have noticed
is as you're working on your web pages
using JavaScript, anytime you
close the page and reopen it
it's as if everything
is starting afresh.
If I were to close this page and
reopen interval.HTML, for instance,
I go back to zero.
Or if you were doing
your quiz application
and you started on question
zero and maybe you were halfway
through your questions and you
closed the page and reopened it,
you'd be back at the very
first question again.
And so JavaScript, at least in later
versions and in more modern browsers,
also supports this
idea of local storage.
The idea that sometimes I want
to take information and just
store it in the browser such
that next time I reload the page
I can just draw any information
from that local storage.
And so I'll show you an example of that.
It's in storage.HTML.
And all of the examples
for this afternoon
are already on the course website,
if you want to take a look at those.
And here's what we're doing,
the body is exactly the same as
before, we just have
some counter variable
and a button that says click here.
And here's the interesting logic, the
first thing that I'm going to do is
say, all right, if local
storage.getitem counter--
so local storage you can think
of as just like a key value
store where I can store
something at a particular key
and then I can access the
value for a particular key.
So if I try and get the counter, but it
doesn't exist-- the exclamation point
just means not as in
not there, then I'll
go ahead and set the counter to zero.
Local storage.setitem,
set the counter to zero.
And so this is distinct from a
variable, whereas a variable will only
exist for this page while it is
open, while this function is running,
something in local storage
is going to persist.
You can close the page, you can quit
the browser, restart the browser,
and something in local storage
will continue to stay there.
And so now what's happening when the DOM
content is loaded, I take the counter
and I set it's inner HTML to be whatever
you get when you take local storage
and get whatever is inside the counter.
Which means that rather than
just set it to zero by default,
I'm saying check local storage, get
the counter out of local storage,
and make that the default
value of the counter.
Anytime the button is clicked, this
part at least should look very similar.
I take the counter, give
it a variable that's
set to whatever the counter
currently is-- call it counter.
Increase the value of the counter.
And then I'm going to do two things.
Thing number one, I update
whatever is inside the HTML page,
setting its value to be whatever
the counter variable is.
And then I update local storage as well.
I'm saving whatever the current value
of the counter is to local storage,
such that next time I open up the
page I can draw on that local storage
and those values will still be there.
And so the result of this is, if
I open up storage.HTML, I see--
OK.
I see the number zero there.
And I click one, two, three,
four, five, six, seven, eight.
And once it's there, normally if I
were to close the page, reopen it,
I'd be back to zero.
But now if I close the page and reopen
it, I'm still with the number eight.
It was able to save that
state inside of local storage,
such that the next time I open it up
I can actually access those values.
And so that could be a helpful tool
as you go about building applications
that maybe, for example,
in your quiz application
you want it such that it
remembers what question you're on
or it remembers your score, such
that even if you close your page
and reopen it later, you're
still at that same place.
And so you can consider
that as something you
may want to implement as
well later on this afternoon
when we get to project time.
Questions.
Yeah.
AUDIENCE: What is the scope [INAUDIBLE]
BRIAN YU: Sure.
What is the scope of local storage?
How wide does it go?
When you deploy applications to the
internet it's by the domain name.
So something .COM, for instance,
would have its own local storage.
In the case of files, your
file systems basically
are all going to share
the same local storage.
And you can actually see the contents
of what's inside of local storage
if you want to.
If I Control Click on Chrome,
at least, go into the inspector.
And if you go in to application,
on the left hand side
here you should see local storage.
And if I look at what's
there, I see, OK,
the key counter has a
value of eight, so that's
what's currently stored
inside my local storage.
So you could see that.
You could update it if I wanted.
I want to make the counter a little
bit higher, like 28, for example.
I can close the page, open the page
again, and, OK, my counter is updated.
I've changed what's
inside of local storage
and the result is that I've
changed what shows up on the page.
Other things?
OK.
So thus far, all of
our JavaScript programs
have only existed on the client
side and they've only involved
code running inside of the browser.
Yesterday, of course, we were
dealing with server side code,
like flask applications
whereby you could
talk to and interact with a server.
And so what we're
going to do now is just
show a brief example of trying to
combine these two ideas together,
of having a client side application that
can talk to some web server or some web
API.
We'll talk a little bit more about APIs,
or application programming interfaces,
tomorrow.
But let's do one brief
example, that maybe I
want to write a website in JavaScript
that allows me to get exchange rates.
I want to figure out, OK, one US
dollar, how many euros is that?
Or how many Japanese yen is that?
For example.
And I wanted to do that conversion.
Now, I could look up currently what
the conversion rate is and plug that
into my JavaScript code,
but, of course, that's
not totally accurate because tomorrow
the exchange rates are going to change
or even in a couple hours the
exchange rates might change.
I would like some way of knowing for
sure what the current exchange rate is.
And there happens to
be an API that actually
allows you to do this pretty easily.
It's called Exchange Rates API.
And you'd only know this by sort
of Googling and looking around.
And there are different APIs
that do different things.
And if I type in
API.exchangeratesapi.io/latest.
And I got this just by reading
the website's documentation.
What that does for me is it
gives me a big JavaScript object
that looks rather complicated,
but basically it's
giving me a whole bunch
of exchange rates.
And it's telling me, OK, here is
how many Canadian dollars 1.5117 is
equal to what base currency, one euro.
So it's giving me all
these exchange rates
that are potentially useful for me.
But, of course, I would rather
not compare against the euro.
I probably, in this case,
want to be able to say, OK,
how many of a certain
currency is one US dollar?
For example.
And so in this case, I'm
going to say, OK, I'm
going to provide a parameter to this
API route and say, base equals USD.
I want US dollars only.
Oh, sorry.
Not ampersand.
Question mark.
Base equals USD.
And what I get there is I get a
whole bunch of exchange rates,
but now the base--
the base currency is US dollars.
So I get all these exchange
rates in terms of US dollars.
And, again, this I would only know by
actually going to exchangeratesapi.io
and you can read the
documentation here for how
you would go about getting the exchange
rates for any particular thing.
And instead of getting
all the currencies,
if I just wanted one currency, I
would say, and symbols equals euros.
And so there we get, OK, one US dollar
is equal to 0.8801 euros, at least
as of today and as of right now.
So this is an API that's returning
to me some JavaScript object.
And I could use this information
to be able to implement something
like a currency conversion application.
And so I'll show you
an example of that now.
I'll open up currency.HTML.
So this is a very simple
application that all it does
is it has an input field where I can
type in a currency, a button that
says Get Exchange Rate.
And so if I type in something
like Euro, for example,
and click Get Exchange
Rate, it says, one US dollar
is equal to that number
of euros, for example.
Or if I type in Japanese yen.
And so Get Exchange Rate.
One US dollar is equal
to 109.66 Japanese yen.
If I type in something that doesn't
exist, like beyond is not a currency,
OK, there was an error.
So how does this work?
What is the code that
actually implements this?
We'll open up currency.HTML
to take a look.
Inside the body of the page, the
body is actually quite simple.
I have a form that has an input
field called currency where
I can type in the currency that I want.
And I have a button, a Submit
button for the form that
just says Get The Exchange Rate.
And I'm going to click on that button.
And then I have a line break.
That's what BR is.
And then a div that's currently
empty, where eventually I'm
going to put the result of
this calculation, whatever
the result of looking
up the exchange rate is.
Now, what is the JavaScript
that's making that work?
Well, when the form is submitted,
so on Submit for the form
I'm going to get the value of
the input field for the currency
and save that in a
variable called currency.
And then I'm going to use
this function called fetch.
And what fetch is going to do
it it's just going to request--
make an HTTP request, request some
URL and get me back the results.
And here I'm getting the results of
going to API.exchangeratesapi.io/latest
specifying the base being US
dollars, and what symbol do I want?
I want whatever currency I'm trying
to convert into as the currency.
So this is me making what's called an
AJAX request, an asynchronous request
where I'm requesting from some other
URL, some other website not my own
for some data.
And in particular, I'd like
data about the exchange rate,
and then I'm going to get that
back and do something with it.
Before I go on, questions about this?
I saw some yellow and red faces.
So I'll pause for
questions if there are any.
Yeah.
AUDIENCE: [INAUDIBLE].
BRIAN YU: So the currency
variable is going
to be equal to whatever it is that
I typed it, so like EUR for euros
is what I typed into the text field.
And then I'm taking that currency
variable and plugging it into the URL,
because if you look at the URL that I
was using on the exchange rates API,
up at the top I said, OK,
base is going to be US dollars
and the symbol is whatever
I want to convert into.
So I'm just plugging something
into that spot in the URL, such
that I can get a different exchange
rate based on whatever I type in.
Yeah.
SPEAKER 3: Do you need to worry
about escaping that string
that you're plugging in to the URL?
BRIAN YU: Do you need to worry
about escaping that string?
Sure.
Certainly there are
security considerations
you might add here to
check it to make sure.
This is something we'll talk a little
bit more about later in the week
when we start talking about security
in particular with regards to web
requests.
But, yeah, good thinking.
Other things.
Yeah.
AUDIENCE: [INAUDIBLE].
BRIAN YU: If you're using
JQuery and you do $.get,
that'll behave in a very similar way.
There are many ways of achieving
the same general effect.
Fetch just happens to be one of
the more modern ways of doing so.
But yeah, there are
many ways in JavaScript
to make an outgoing HTTP request.
This syntax of .then don't
worry about too much.
This has to do with JavaScript promises.
But the basic idea, or at least the
idea that you should be getting across
is, OK, I'm going to request
this information from the server,
then take the response and convert it
to JSON, JavaScript Object Notation,
until I get back a JavaScript object.
And then with the resulting data, where
is the actual exchange rate stored?
Well, it's in a key called rates,
and then this is the value.
So I have to go into
the key called rates
and then go into a key called
whatever the name of the currency
is, and the value there is
going to be the exchange
rate, at least for this particular API.
And so I'm going to set my--
the contents I'm going to fill
in to my page to be one
US dollar is equal to--
here is where I'm going to actually
plug-in the currency exchange rate.
So I go into the data, the object
that came back, go into the rates key
and then index into it and say,
OK, get me the currency key.
And that's going to get me the
number of the exchange rate.
And then just fill in
the currency there,
so it says this is equal to this
number of euros or this number of yen,
for example.
And then just fill that into
the result section of the page.
The catch here is very similar
to Python's Try Except syntax
of like, try something, and if
something goes wrong, do something.
Catch just means, if anywhere along
this path there was some sort of error,
then go ahead and just include in the
results section there was an error.
That'll happen if I
can't find the right key
or if the request doesn't
work for some reason.
That's what will end up happening.
Yeah.
AUDIENCE: So it's not
based on [INAUDIBLE]..
Based on [INAUDIBLE].
From the line above and fetch just
goes by the chain of [INAUDIBLE]..
BRIAN YU: Yeah.
JavaScript is not indentation
based, unlike Python.
So the indentation in
JavaScript is just aesthetic.
It helps to make things
clearer, but it's not necessary.
The way that these are linked
together is via these dots.
So in reality these are all
just being chained together.
And this is a common
syntax in JavaScript
that you'll often see, that
things get chained together
one function being called after
another function after another.
We'll see another
example of this when we
get to animation as well, of this
chaining of functions after each other.
Yeah.
AUDIENCE: [INAUDIBLE].
To have a constant content [INAUDIBLE].
BRIAN YU: You could certainly
eliminate the variable.
I did it this way just so
it would fit on one screen
so you all could see it more easily.
Yeah.
AUDIENCE: [INAUDIBLE] data [INAUDIBLE]?
BRIAN YU: Yes.
This word response and
this word data, these
are just arguments to the function.
And so they could be called
anything you want to call them.
Yeah.
AUDIENCE: Yeah.
I'm just a little confused about
what is response and what is data
and what exactly do they pull?
BRIAN YU: Yeah.
So response, in this case, is
a special JavaScript object
that represents an HTTP response
just to some web request.
And so an HTTP response happens
to have a function called .Json,
which takes that HTTP response,
converts it to a JavaScript object,
just keys and values like we were
doing with the questions this morning,
and returns that object.
Of course, not all HTTP responses
can be turned into objects,
so there's a chance that
something will go wrong there,
which is what the catch here is for
in case something happens to go wrong.
So we take the HTTP response,
convert it into an object,
and then data is just going
to be that JavaScript object.
It's just going to be literally
this, the curly brace rates and then
what the base is, for example.
AUDIENCE: And how does data know
that what it's taking in as input
is response.Json?
BRIAN YU: How does data know
that what it's taking in
is a result of response.Json?
That's what this chaining .then is.
So when you chain the .thens together,
it's one thing after another.
I wouldn't worry too much about
the specifics of the syntax here.
You can take a look at the example
later as well for more examples of that.
Yeah.
AUDIENCE: Just to make sure.
Does that have to be [? response and ?]
[? data? ?] Or we can just
[? take it in whatever? ?]
BRIAN YU: No.
Response and data are arbitrary names.
They could be anything.
OK.
So those are just some other JavaScript
features, the idea of intervals,
the idea of local storage, the idea of
AJAX requests to get additional data.
So now let's turn our attention a
little bit, change gears a little bit
to talking about user interfaces.
We'll talk about user interfaces,
how to make them more engaging,
the types of features you'll often
see in modern user interfaces.
And we'll start by a little bit
of discussion about a window.
And so here is what a browser
window might look like.
You've got the menu bar
along the top and then
you've got the entire
contents of the page.
And there are certain attributes you can
access about the window in JavaScript.
If you say window.innerwidth
what you'll get
is a number of pixels equal to
how wide the current page is.
So you shrink the page,
you grow the page,
that will change window.innerwidth.
And likewise, window.innerheight is
how many pixels tall the page is.
And so we saw this a little bit when we
were dealing with media queries in CSS
when we wanted to say,
OK, if the page is
smaller than a certain number of pixels,
then do something slightly differently.
But that's inner width and inner height.
Then there are also some
other variables that we
can access about the current state
of the user's experience on the page.
The entire page is probably bigger
than what's visible on the window,
because there might be
stuff above it, stuff below.
You would scroll up and
scroll down in order to see.
Window.scrollY is a value that
represents how far in the Y
direction, the vertical direction,
have you scrolled so far.
So if you're at the very top of
the page, window.scrollY is zero.
If you scroll down 50
pixels, window.scrollY is 50.
And finally, one other value that
might be interesting to know,
document.body.offsetheight just
refers to the entire height
of the document, not just the visible
area, but from top of the document
to the bottom of the web
document, how many pixels is it?
How many pixels would
you have to scroll to get
all the way from the top to the bottom?
So a couple of interesting values there.
And so now, interesting
question, what would you
write in code if you
wanted to check to see
if you were at the bottom of a page?
What would the expression
look like if you
wanted to see if you were
at the bottom of a page?
Take a few moments to think about it.
And then we'll see if
anyone has a guess.
AUDIENCE: [INAUDIBLE].
BRIAN YU:
Document.body.offsetheight refers
to the entire height of the web
page, not just the visible part
on the window, it's from
the very top of the page
all the way to the bottom of the
page, which you might theoretically
need to scroll through, but it's
the entire height of the document.
OK.
How would you find out if you're
at the bottom of the page?
Yeah.
AUDIENCE: Window.scrollY plus
window.innerheight [INAUDIBLE]
document.body.offsetheight.
BRIAN YU: Yeah.
So long is window.scrollY
and window.innerheight are
as tall as document.body.offsetheight.
That's how you would know if
you're at the bottom of the page,
because the amount that you scrolled
by plus the height of the window
would take you all the way
to the bottom of the page.
And so we could actually
use this in a brief example.
Let's open up scroll.HTML.
And whereby in the body
of scroll.HTML I just
have a lot of paragraphs,
paragraph one, two, three, four,
all the way down to paragraph 100.
So I just have 100 paragraphs
that just have numbers in them.
Nothing all that exciting.
But here inside my JavaScript
I've got some code.
Window.onscroll, so this
is another event handler.
Whenever the window is
scrolled, run some code.
And if window.innerheight
plus window.scrollY
is at least as tall as the
document.body.offsetheight,
then go ahead and change the
style of the body of the page
to green, and otherwise,
change it to white.
In other words, if I hit the bottom
of the page, turn the page green.
So I'll show you that code.
As soon as I hit the bottom of
the page, scrollY plus innerheight
is equal to the total
height of the document.
I'm going to change the background
of the page to be green.
And so open up scroll.HTML.
I see I have all these paragraphs.
And if I scroll down all the way to
the bottom, paragraph number 100,
the page is white right now.
And as soon as I hit the bottom,
OK, the page turns green.
I scroll up, it's white.
Hit the bottom, the page turns green.
So I'm able to detect when
I'm at the bottom of the page.
And now, why might that be useful?
In what context, in an
application would it
be good to know if you're
at the bottom of a web page?
Why do we care?
Yeah.
AUDIENCE: Well, a lot of
news sites nowadays when
you get to the bottom
it shows the next story.
BRIAN YU: Yeah.
A lot of news sites nowadays
when you scroll to the bottom
you get the next story or we'll
get sort of this dynamic loading
where when you get to the end of the
page, it'll load the next set of posts
or the next set of
articles, for instance,
so that you can keep scrolling
infinitely, this infinite scroll idea.
And so we can use this notion to
actually implement infinite scroll.
I won't show you all
of the code, but I'll
show you the relevant portions of it.
If we go in to the post zero example.
What I have here is a flask application
where in application.pi I basically
just have a route that's going to--
called slash post where you can specify
the start post that you want
and the end post that you want
and it will return to you a JSON object
that's containing all of those posts.
And in index.HTML, here's
the interesting code.
We're going to start with a body
that just has an empty set of posts.
And we're going to--
whenever we scroll the page--
so first, when DOM content loaded,
when we first load the page,
call the load function to load
the first 20 posts, for example.
And then when the window is scrolled,
if the inner height plus scrollY
is at least document.body.offsetheight,
same equation as we were using before.
In other words, if we've
hit the bottom of the page,
then go ahead and load
the next set of posts.
And all load is doing-- and you
can take a look at this later--
is it's calculating what the start
and end post number should be.
And then it's making a fetch request,
just fetching from the server
just like we saw a moment ago
trying to get the next set of posts.
But the relevant part,
at least for now, is just
to understand these
couple of lines here,
that when the window is scrolled,
if it is the case that we've
hit the bottom of the page, then go
ahead and load the next set of posts.
And so I'll go ahead
and go flask run here.
We'll load up this page.
We get a whole bunch of posts.
I notice I'm almost
about to hit the bottom.
And when I hit the
bottom, post number 20,
there's a moment's pause, but, OK,
then the next set of post loads.
I scroll to the bottom again, and,
OK, the next set of post loads.
And I can do this infinitely.
I can continue to scroll and
continue to get a new set of posts
because every time I hit the bottom
of the page, the next set loads.
And so this ability to
know where I am on the page
can allow for things
like infinite scroll
and the implementation
of features like it.
Questions.
Yeah.
AUDIENCE: [INAUDIBLE].
If it was on the top of the
page as well [INAUDIBLE]..
BRIAN YU: If I'm at the top of the page,
then the document.body.offsetheight,
the body of the document is
going to be the entire document,
but the window.innerheight,
the height of the window
is only going to be a
small portion of that.
And scrollY will be zero, because
I won't have scrolled at all.
And so the total height
is going to be much less
than the total height of the document.
So if you go back to this image,
if I'm at the top of the page,
if you add scrollY, which is
zero with the inner height,
it's going to be substantially
less than the offset height
if it's a tall document.
Other things.
Yeah.
AUDIENCE: Why [? is it ?] [? greater ?]
[? than ?] [? or equal to? ?]
BRIAN YU: Greater than or equal to just
to be able to handle browser case where
sometimes you can do a little bit of
scrolling past the bottom of the page,
for example.
Other things.
OK.
And with end, if you're curious about
what the load function is doing,
it's basically making a
request, and for each post
that comes back, running
this add post function.
All add post is doing is it's creating
a new div, giving it a class name,
and then adding it to the
DOM, just appending it
to the section of the page that
is dedicated to all the posts.
And the result of that is we get
this infinite scroll-like feature.
With a little bit of additional
work, we can actually
use it to allow users
to hide posts as well.
So I'll show you--
we'll go into post one.
And the only difference in
post one is in index.HTML,
if you look down at
the add post function,
in addition to creating a
div, I'm also just creating
a button called Hide that's
going to hide the post.
And when you click the Hide button it's
going to remove the post altogether.
And so I'll let you look
at that code in more detail
if it's something you're curious about.
It's online.
But now what we have is we
have infinite scrolling posts.
But if I want to, I can click
the Hide button next to post 16
and it goes away, just goes
straight from 15 to 17, for example.
Those are just more
examples of what it is
that you can do by taking advantage of
the features that JavaScript offers.
Questions about anything
we've talked about so far?
Yeah.
AUDIENCE: As far as--
would you mind going back to the code?
BRIAN YU: Which code?
AUDIENCE: The [INAUDIBLE].
BRIAN YU: Yeah.
AUDIENCE: As far as the
constant variables throughout,
is there any advantages
[INAUDIBLE] accidental changes?
Like, what if you just
didn't [INAUDIBLE]??
BRIAN YU: They could all be let
variables instead of constant variables
and it would work just
fine in this case.
Constant is just there
as a security measure
basically, to make sure
that nothing gets changed.
OK.
Let's do a bit of a change gears.
Still on the topic of user
interfaces and user experience.
And let's try creating a new HTML page.
I'll call it index.HTML.
It's going to have a
header, title, hello.
And in the body of the pager we're
just going to say, welcome, again.
Now what I'm going to do is I'm
going to add some style code.
But first let's look at the
page, make sure it looks OK.
Open up index.HTML.
All right.
Welcome looks fine.
But now what I'm going to do is
I'm going to add some style code.
And in particular, I'm going to
add some CSS animation, some CSS
code that is going to
allow me to animate
what it is that's on the screen.
And to do this I'm going to call--
use a special syntax
called At Key Frames.
So I'm going to define
the name of an animation.
And the name of this animation
I'm going to call Grow,
because we're going to grow the size of
our heading, is what we're going to do.
And to do this we define
two keys, from and to.
From is what the style
is like at the beginning,
and two is what the
style is like at the end.
And what I'd like to
say is, when something
grows it should go from having
a font size of 20 pixels
to having a font size of 100 pixels.
So here I've defined an animation.
At Key Frames Grow we're going to grow
from something with a font size of 20
to something with a font size of 100.
And now for any H1, any heading, I'm
going to say animation name is Grow.
In other words, you should
apply the Grow animation.
And I'll add a couple
other CSS properties.
Animation film mode
forwards is just going
to say, once you get to where you're
going, once you get to 100 pixels
at the end of the Grow animation,
stop there, and just retain
that style state.
And then finally, you say, OK, how
long should this animation take?
We'll say animation-duration,
two seconds.
So I've defined an
animation called Grow.
Could've been called anything.
What does the Grow animation do?
It goes from a font size of
20 to a font size of 100.
And then I said for
any heading, go ahead
and use the Grow animation
go forwards and it
should take two seconds to do so.
So now I refresh index.HTML
and you get that animation.
You refresh the page, it goes
from 20 pixels to 100 pixels.
I've been able to create something
a little bit more dynamic.
Questions about that
and what I just did?
Yeah.
AUDIENCE: Can you explain
what key frames is again?
BRIAN YU: Yeah.
Key frames is just defining what the--
we'll call, what the key
frames of the animation are.
In other words, what are the points
in the animation at which the element
should have a particular style?
And here I'm saying at the
beginning of the animation it should
have a font size of 20 and at
the end of the animation it
should have a font size of 100.
The beginning of the animation
and the end of the animation
are what we'll call the key frames.
And the browser is going to do
the heavy lifting of figuring out
how to actually change the element
from the from state to the to state.
Yeah.
AUDIENCE: [INAUDIBLE].
BRIAN YU: You could have
multiple properties inside of to.
So you could have multiple things that
are happening inside of this animation.
And font size is not the
only thing you could do.
I could say, for example,
left 0%, meaning start 0% away
from the left hand side and go to
50% away from the left hand side,
like 50% of the window
away from the left side.
And if I reload that, the effect
of that is, OK, we get-- well,
that didn't work.
From left 0%-- oh,
what I need to do is--
based on the way that
CSS lines things up,
I need to say that the heading has
a relative positioning, meaning
it can change relative
to the rest of the page.
And I think this should work.
OK.
Great.
So it started at the left hand side,
ended 50% of the way across the window.
Show you that again.
Starts on the left,
moves 50% across the way.
Questions.
Yeah.
AUDIENCE: Do you have
like a middle step though?
BRIAN YU: Yeah.
I can give a middle step.
Absolutely.
Instead of from and
to, I might say, when
you're 0% of the way done with
the animation be 0% from the left,
when I'm 50% of the way through
the animation be 50% from the left,
and when you're 100% of the way
through done with the animation,
let's go back to 0%.
So what's this going to look like?
Yeah.
OK.
Someone's-- people
are making the motion.
We'll show it.
Starts to the left, goes to the
right, goes back to the left.
Can refresh that.
Goes to the right,
goes back to the left.
If I want it to happen multiple times
there's animation iteration count.
I can say, animation iteration
count two, for example.
And now I refresh the page,
it goes there, it goes back,
and then it happens again.
Happens twice.
You can even say animation iteration--
you guys are having fun with this.
So we'll change it to infinite.
And now you know you can just
let it go and it will just
go back and forth forever.
So we've got these CSS
animations running.
Yeah.
AUDIENCE: Why is not jumping?
Because you're not
telling it like the why.
You're just specifying
the beginning and the end,
so why would it just not
start here and end there.
[INAUDIBLE] colors.
[INAUDIBLE]
BRIAN YU: Yeah.
Good question.
So why is it not jumping?
Why is it smoothly sliding from one
side to another when all I'm saying
is, at 0% do this, at 50%
do that, at 100% do that?
This is what CSS animation is all about.
You define the key frames, the
key points in the animation where
you want it to be doing
something, and then the browser
fills in the rest of it, figuring out
what the intermediate positions need
to be in order to get from the first
key frame to the next key frame.
You can certainly do this with color
if you wanted to change this to--
we'll change this to 100% left,
50% will go back to from and to,
though you don't necessarily need to.
I could say, OK, start with
a color of red and go to--
I should add semicolons here.
And go to a color of blue.
And let me get rid of
the iteration count.
We'll just do it once.
Now, if I refresh the page
it goes from red to blue.
From red to blue.
Yeah.
AUDIENCE: [INAUDIBLE] function.
You can change linear
versus exponential.
BRIAN YU: Yes.
You can change--
You can start to get fancier
about how you go about doing that.
AUDIENCE: One more question.
Which is faster, CSS
or jQuery animations?
BRIAN YU: Good question.
Which is faster, CSS
or jQuery animations?
jQuery is probably going to be
slower, though I'm not actually
100% sure about that.
Yeah.
AUDIENCE: How would you-- if you were
to do-- say you wanted to [INAUDIBLE]
and then do the color.
Would the formatting be
different than if you wanted
to [INAUDIBLE] and to do [INAUDIBLE]?
BRIAN YU: Yes.
So what I could do if I wanted to
do like, first move and then change
the color, is I'd say, OK, at 0% I
want it to be on the left hand side
and I want the color to be red,
at 50% I want it to be left 50%
and I want the color to
still be red, and at 100%
I want the color to
be blue, for example.
Where now it will move and
then it'll change color.
So you can define the intermediate
key frames however you like.
Questions about any of that.
AUDIENCE: Can you show the code again?
BRIAN YU: What?
The code?
Yeah.
So those are the key frames.
AUDIENCE: What happens if you
do 99% and then [INAUDIBLE]??
BRIAN YU: 99%?
Why do you want it 99%?
AUDIENCE: No.
I mean, [INAUDIBLE].
BRIAN YU: Oh, no.
That shouldn't.
You can experiment with this
all you'd like if you'd like to.
You just need to create
an HTML page and you
can do whatever key frames
you'd like to play around with.
Yeah.
AUDIENCE: [INAUDIBLE] left 50%.
BRIAN YU: No.
Some of this might be redundant
that you can take out, for instance.
Yeah.
AUDIENCE: What is the
meaning of the key frames?
BRIAN YU: The key frames
are just getting at the idea
that rather than specifying
what the state of the style
should be at every single point at
every single frame of the animation,
I'm just specifying it
at a couple of key frames
and then the browser is
going to fill in the rest
to figure out how it should
transition from one thing to the next.
Yeah.
AUDIENCE: So if you wanted
it to basically make
it appear and disappear and appear
[INAUDIBLE] in the middle, basically
no transition in between.
Would you basically show it,
hide it, show it on the middle,
and then hide it?
BRIAN YU: If you didn't
want the transition,
you probably don't need CSS animation.
You could probably just use
JavaScript to say, wait five seconds
and then change the color.
And then it would just
change color, for example.
Yeah.
AUDIENCE: Is the CSS [INAUDIBLE].
BRIAN YU: Yeah.
AUDIENCE: Is that referencing-- how
does it know that we have an animation?
[INAUDIBLE]
BRIAN YU: When you say
animation name Grow,
it's referencing this
grow, just some animation
that I've defined that is
called Grow, for example.
AUDIENCE: It just knows
that Grow is an animation.
BRIAN YU: Yes.
The at key frames basically
tells it what it is.
Yeah.
Good question.
So we can actually use this.
This is not just all for
just like fun and games.
We can see what we can
do with the heading
and get it to slide back
and forth and change color.
We can go in to--
let's look at post to now.
And the only difference I've made
in post two as opposed to post one,
remember this was our
auto-infinite scroll for posts--
if I go into index.HTML, I've
added this Hide key frame
that we can use to basically hide a
post if we don't want it to be there.
So remember before when we
were hitting hide on each post,
it would just sort of
go away immediately
and the next one would
immediately be in its place.
We can define a key frame
called hide that goes
from an opacity of one,
meaning totally visible,
to an opacity of zero, which
means totally invisible,
and we can give any post
an animation name of Hide,
and we can use JavaScript to trigger
when we want that animation to begin.
And so if I say flask run here.
Open up flask.
All right.
Great.
Here is our auto completing post.
And now if I wanted to hide
post three I click Hide.
And then over the course
of some time it fades out
and then the next post
jumps in to fill its place.
We hide.
It fades out.
And the next post jumps in.
And this user interface
still isn't amazing.
What would we like to change?
Yeah.
It would be nice if it would slide
up as opposed to just jumping up.
And so if we take a look at post three.
And if we look at index.HTML.
These key frames are a little
fancier, but the idea here
is at 0% we'll start at full opacity.
When we're 75% of the way done with
the animation the opacity will be zero,
will fade out completely.
And then will go from a
height of 100% to-- when
we're totally done with the
animation the height will be zero.
And when we go from a large
height to a small height,
when we fill in that transition, the
result will be the height will shrink.
And so if we say flask
run now, open up this.
We've got all of our posts.
And if I want to hide post
number three, I click Hide.
It fades out.
And then the next one slides
in as the first size shrinks.
Show you that again.
Fades out and then it shrinks.
So using CSS animation we're able
to create these interactive, nicer
and more aesthetically
pleasing user interfaces just
by taking advantage of these
key frames and deciding
when things are going to
start and stop and how things
transition from one thing to the other.
Questions.
What questions do you have?
Yeah.
AUDIENCE: Are those positions relative?
Or are they using [INAUDIBLE]?
BRIAN YU: This is relative positioning.
Yeah.
OK.
So that's CSS animation.
Yeah.
Question.
AUDIENCE: What if you wanted to
give a post multiple animations?
BRIAN YU: If you wanted to give a post
multiple animations, you can do that.
It'll be easier with
some more JavaScript.
And we're about to go to JavaScript
based animations in just a second.
Yeah.
AUDIENCE: So we just set the size
of where the document [INAUDIBLE]
zero [INAUDIBLE] run the animation
[INAUDIBLE] will that be [INAUDIBLE]
zero?
Or [INAUDIBLE] actually [INAUDIBLE]?
BRIAN YU: I believe
this code will actually
remove the element after
the animation is over,
so you wouldn't have
to worry about that.
OK.
Let's try something a
little bit different.
Yeah.
AUDIENCE: So this is just
all the visual stuff, right?
The existence of the animation
[INAUDIBLE] great accessibility?
BRIAN YU: So good question
about accessibility.
There are certain things that--
element-- attributes that
you should be adding to HTML
elements for accessibility reasons.
In particular on images
and such, but in general,
so long as you're
following those guidelines,
you can still have
animations on the page
and accessibility should still be OK.
We can chat about specific use
cases if you have them in mind too.
All right.
Let's go ahead and open up index.HTML.
And let me get rid of
the style code for now.
All right.
What I'm going to do now is
inside the body of the page
introduce SVGs, or
scalable vector graphics.
And vector graphics you can
think of as just graphics
that you can, at least in
the context of web pages, are
shapes that you can add
to your page in order
to create for some more
interactive user interfaces,
allow for some user experiences
that we weren't able to have before.
So here I'm going to say--
SVG is going to be an element--
its style is going to have a width
of 100% and a height of 800 pixels.
In other words, what I'm
doing here is creating
an SVG canvas, just an 800
pixel tall canvas on which
I can draw shapes, at least for now.
So inside of this canvas I'm going to
say, all right, let's create a circle.
And a circle has some attributes.
It has a center x-coordinate.
So where is it centered?
We'll say center x-coordinate
is going to be 200.
It has a center y-coordinate.
We'll say also 200.
It has a radius.
We'll say 50 pixels, at least for now.
And we can add styling to it.
Right?
I can say, all right, the fill
color of this circle should be blue.
So what I've done here is I've
created an SVG canvas, a place where
I can draw shapes, it's 800 pixels tall,
it fills up the full width of the page.
And I'm going to draw a circle at
location 200, 200 with a radius of 50
and it should be blue.
So I open up index.HTML.
And OK, I have a page and just a
blue circle, as you might expect.
So this is a vector graphic.
Questions about that
before we dive into more.
You could certainly do all these
vector graphics entirely by hand
just by specifying
where you want things,
but there are libraries that
are able to help with this.
A library we're going to
use at least for today
is called D3, something
you may be familiar with.
It's actually quite good,
especially for analyzing data
and for data visualization,
so it's quite powerful.
We're not even going to use most
of those capabilities today.
We're just going to use it for
interacting with vector graphics
in order to draw things
on the screen, but know
that it's far more powerful
than what we're actually
going to get a chance to look at today.
And so we'll go ahead and
go in to circleone.HTML,
if you're following along
with the source code examples.
And in circleone.HTML I first included a
script, not a script that I've written,
but I'm including D3's JavaScript.
This is just a JavaScript library
that's going to make it easier
for us to draw these shapes.
And inside the body of our
application here's an SVG canvas.
It has an ID called SVG and it's going
to take up the full width of the page.
It's going to be 800 pixels tall.
And then here is the JavaScript
code that makes this work.
This is the JavaScript equivalent
of what it is that we just did.
And we're first using a
function called D3.select,
which is just going to use D3
to select the SVG container,
storing it in a variable
called SVG, and then we're
going to programmatically
add a circle to it.
Instead of just writing it
hard-coded into the HTML,
we're going to say SVG.appendcircle.
And here we see that
chaining idea again.
This chaining of function
after function after function.
These dots are all just chained
functions being applied to each other.
So we're saying take that circle
and give it this attribute,
give it the center x attribute of 200.
Put it at x location 200.
Take the y attribute, put it at 200.
Give it a radius of 90 pixels.
Fill it with the color
green, for example.
And so you can add CSS.
Instead of using attribute, using
.style to add CSS properties,
like the fill color, for example.
And the result of this is
if I open up circleone.HTML,
I get a big green circle.
Basically the same as
before, but now I'm
using this D3 library that's going
to make things a little bit easier.
Questions about anything
so far before I go on?
Yeah?
AUDIENCE: [INAUDIBLE] circle is
supposed to be 100% [INAUDIBLE]
BRIAN YU: The SVG itself
has a width of 100.
So the canvas on which I'm
drawing takes up the entire width,
but the canvas is white, so it's
just in the background of the page.
The circle itself only
has a radius of 90.
And so it's going to have a radius of
90 pixels, is what I specified there.
Yeah.
AUDIENCE: [INAUDIBLE].
BRIAN YU: Yes.
You can do combinations of any of
the things that we're talking about.
OK.
Just to show you one other shape.
I'll show you rect.HTML for a rectangle.
It's very similar.
Instead of specifying CX and CY for
the center x-coordinate and the center
y-coordinate and an R for radius,
I specify an x-coordinate,
a y-coordinate, a width,
and a height, and that lets
you draw a rectangle wherever you want.
So open up rect.HTML.
And OK, we get a big blue rectangle.
Questions.
All right.
So so far these shapes don't
move, so let's go ahead
and add some animation to them.
Much as we did before
with CSS, but now using
D3 to be able to create transitions
as things move from one state
to another state.
So we'll open up circletwo.HTML.
And then circletwo.HTML, it
starts basically the same way.
I create a circle located at
200, 200 with a radius of 50.
And we're going to fill
it in with the color blue,
but then I'm going to
apply a transition to it.
I'm going to say c.transition.
C is the name of the circle.
I just saved it inside of a variable.
And this transition is going to have
a duration of 1,000 milliseconds,
or one second.
And what's going to happen?
I'm changing the x and the
y attributes of the circle,
moving it from 200, 200 to 500, 500.
And I'm also changing its style.
I'm changing its style from blue to red.
And much in the same way that CSS
allowed me to define key frames
and then CSS took care of the rest of
figuring out how to transition things
from one state to the other.
D3 is going to do the same
thing with the idea being
that we're going to apply
a transition and it's
going to smoothly move from one
position to another position,
from one color to another color.
Where by now I can
open up circletwo.HTML.
And OK, the blue circle moves
and it also changes color.
Refresh it again, so you can see it.
It moves and it changes color.
Questions about that.
Show you the code again.
This is in circletwo.HTML, if you're
following along with the examples.
Do one more simple example.
We'll open up circlethree.HTML.
And now we're going to add a transition.
And this transition is going
to change the x position.
So the duration is going
to be 1,000 milliseconds.
We're also going to
add a delay, which is
like how long it's going to take
before the transition actually starts.
But you can also add event listeners
to this, much in the same way
that you can add event
listeners to other elements.
So I can say, take this circle,
and on click, in other words,
when this circle is clicked on,
then go ahead and run this function.
D3.selectthis is just
a fancy way of saying,
get this object, this
circle in particular,
and apply another transition to
it that lasts three seconds that
changes its style to red.
So a lot of this, when you
see this chaining, just
think of it as do this thing, and then
do this thing, and then do this thing,
or think of it as chaining
these all things together
into one big transition.
We're doing a transition
on the circle that
is going to set the x attribute to 500.
And then when the circle
is clicked on we're
going to apply another
transition that's going to change
the fill color of the circle to be red.
So we open up circlethree.HTML.
We have a blue circle.
After one second it moves.
I didn't do anything.
But now if I go over
it and I click, then
over the course of a couple of
seconds the circle changes color.
Able to do animations in
response to particular events.
What questions do you have?
Yeah.
AUDIENCE: On the code
[INAUDIBLE] D3.selectthis,
why did you have to do that?
Couldn't you just do c.transition?
BRIAN YU: Good question.
Why did I need D3.selectthis
instead of just c.
I probably could have done
just c in this case-- actually,
let's try just to make sure.
Here and then click.
And then, yeah, that'll work just fine.
So in this case, you
can get away with that.
In some more complex examples
when they're not necessarily
referring to the same
variable name, maybe
when applying animations to
a list of potential things,
then D3.selectthis is
helpful for getting
the thing that triggered the event.
And so I'm showing it
to you for that sake,
so that you know how to
use it in future cases.
But yeah, in this case, c.transition
would've worked just fine.
Yeah.
AUDIENCE: So you [? divide ?]
[INAUDIBLE] demo and then [INAUDIBLE]
so are you [INAUDIBLE]?
BRIAN YU: Yes.
We are constrained to whatever
width and height the SVG canvas is.
And if we try and draw
something beyond it,
we're not going to see it because it's
outside the bounds of that container.
So using all these tools we can actually
begin to build some interesting user
interfaces.
I'll show you one that I built
that I thought was kind of fun.
It's called stoplight.HTML.
And it just looks something like this.
All this is so far is a black
rectangle and three gray circles,
something you could create just by
figuring out where the pixels go.
And when you click on the
circles the colors change.
Right?
You click on the different
circles and the colors change
much as a stoplight would, for example.
Yeah.
Question.
AUDIENCE: [INAUDIBLE].
You have a transition where it moves
out of the area and then back in.
Does it look like the circle [? was ?]
hiding and then it comes back?
BRIAN YU: Yes.
If it's outside and it moves
back in, it still exists,
it's just not in the visible
area of the content of the page.
That's correct.
So there are interesting things you
can do with that if you would like to.
Yeah.
AUDIENCE: If you were to shrink the
size of your browser window, what
would happen to your stoplight?
BRIAN YU: Good question.
What happens if I shrink the
size of the browser window?
Well, this browser window
doesn't happen to go--
let's see if I can simulate
this on a mobile device.
Oh, well, this is just
shrinking the viewport,
as we talked about two days ago.
Long story short, it's not going
to work great on this example,
but you might get a situation where
the animation does get cut off.
And so that might be a
situation where if you really
want to think about
mobile responsiveness,
you want to think about dynamically
computing where pixels should be based
upon the size of the screen, for
example, or at least assuming
that something will at least
always be of at least a fixed width
and then being able to add
positioning in that sense.
Other things.
So I'll show you the code for this.
We won't go into detail
in it, but just so you
can get a chance to see it and feel
free to look at it in more detail
if you'd like.
All that's happening
is we get the canvas,
we add a rectangle to it,
that's the big black rectangle,
we go ahead and add a
red circle to it, that
at first is going to be
styled as just gray, we
add a yellow circle to it that's also
gray, a green circle that's also gray.
And basically-- and there are
certainly better ways to design this.
When each of the buttons are clicked
we take the corresponding color,
go ahead and fill it in with
whatever color it should be,
and take the other circles and fill them
in as gray instead of whatever color
they were before.
And so this is all just
using the tools that we've
seen already in order to build some
more interesting user interfaces.
So OK.
Let's try and do something a
little more interesting now.
We'll go to the desktop.
I'm going to-- and this is the
part where if you'd like to,
feel free to try and follow along
by writing in the HTML yourself.
This is going to help lead into what's
eventually going to be this afternoon's
project, if you would like to.
So go ahead and create
a file called draw.HTML.
And inside of draw.HTML we're going to
start with just the basic HTML page.
The title is just going to be draw.
We're going to need to include D3.
So if you go into any of the
other source code examples
you can just copy the
script length for D3.
And go ahead and copy that
into the header of the page.
Doesn't matter where in the header
it is, so long as it's there.
Inside the body of the
page we'll go ahead
and create an SVG that has an ID of
SVG, so that we can refer to it later.
Its style is going to be width 100%.
It's going to take up the
full width of the window.
And it's going to have
a height of 800 pixels,
just sort of arbitrarily chosen
to most likely be tall enough,
but could be whatever you want.
And now let's go ahead
and write some JavaScript.
Const SVG equals D3.select SVG.
This is the same thing that we've
been doing in all of the SVG examples
thus far, whereby we're
basically selecting the canvas
and storing it inside of
a variable called SVG.
But now I'm going to define a function.
And this function is going
to be called draw point.
And what draw point is
going to do is it's just
going to draw a point on the screen.
And OK.
So first of all, I need to figure out--
I want to draw a point wherever the
mouse is-- wherever the mouse is,
for example.
So I need to know where
the mouse currently is.
And so in D3, the way to
get that is to say D3.mouse
and then in parentheses, this.
So take the event and figure out where
the mouse is for this particular event.
And we're going to save that in a
variable called cords, or coordinates,
for example.
And so that variable is going to
store wherever the mouse currently
is at this moment.
And now I'm going to
say SVG.appendcircle.
So add a circle to the canvas.
And the attribute cx, what is the
center x-coordinate of this circle?
Well, it's just going to be cords zero.
Coordinates [INAUDIBLE]
like an array of an xy pair.
So cords zero is just
going to say, what is
the x-position of the mouse right now?
And that should be the center
x-coordinate of this circle.
And likewise, cy, the center
y-coordinate should be what?
AUDIENCE: Cords one.
BRIAN YU: Cords one.
Great.
So I'm creating a new circle and
setting it's x and y coordinates
to be the x and y
coordinates of the mouse.
We'll go and give this a radius.
We'll give it a radius
of 5, for instance.
And we'll go ahead and give
it some style properties.
Fill, we'll just say, black for now.
All right.
So I've created a circle.
AUDIENCE: Close the SVG--
BRIAN YU: Close the SVG--
the slash here is self-closing.
I mean, you could do this and this,
which I guess helps the color scheming,
but technically we don't need to.
Circle.
We set the x and y coordinates
at the radius of the fill color.
And that's it for this
draw point function.
All we're going to do is figure
out where the mouse currently
is and then we're going to
add a circle to the screen
at that particular location.
Questions about what we did just then?
Yeah.
AUDIENCE: Can you just quickly say
again the .attribute [INAUDIBLE]..
Just go through--
BRIAN YU: Yep.
The .attribute section?
AUDIENCE: Yeah.
BRIAN YU: So SVG.appendcircle says take
the SVG canvas and add a circle to it.
And then I'm going to take that
circle and modify its attributes.
And so the circle needs to know
where on the canvas it should go.
And so we're saying, set the
x-coordinate of the circle
to be whatever cords zero, the
x-coordinate of wherever the mouse is.
Same thing goes for the
y-coordinate of the circle, wherever
the y-coordinate of the mouse is.
Set the radius of the circle to be five
and then fill the circle in all black.
And then, now here comes
the interesting part,
we're going to add an event listener.
SVG.on.
And the event that we're going to
listen for is the mouse move event.
Whenever the mouse moves,
we're going to run a function.
And the function we're going to
run is the draw point function.
So we have our SVG canvas.
Anytime the mouse moves, we're going
to call the draw point function.
And the draw point function is going
to figure out where the mouse currently
is, save it in a variable
called coordinates,
and then add a circle to the
screen that has those coordinates.
And so assuming we did everything
right, if we now open up draw.HTML,
we see a dot right
underneath where my mouse is.
And if I move the mouse we'll see
that little dots keep getting drawn.
Now, if I move the mouse quickly you'll
see that it's not a perfect line.
Reason for that is that
the browser only is
able to fire events every
so many milliseconds.
And so if I move my
mouse too quickly, it's
just not able to fire all the
intermediary events in between.
But the idea now is I
can move my mouse around,
and as I do so, the dots sort of follow.
So I'm able to trace out
whatever it is that I'm drawing.
So this is all the code that did that.
It's 24 lines of code
and we're able to create
that effect of drawing on the screen.
Yeah.
AUDIENCE: In the last statement you had
where you were moving the mouse around,
is there an overflow limit?
Like, if you create
too many dots, is that
going to crash the system or something?
BRIAN YU: If you create too many
dots, is it going to crash the system?
Certainly, the browser
does have a memory limit,
but these are pretty
small circles that don't
have a whole lot of data
associated with them,
and modern browsers can
handle pretty big web pages,
so probably not something that we have
to worry too much about at least now.
Yeah.
AUDIENCE: Yeah.
I'm confused about why you used const
instead of let, because, aren't you
changing that value every
time you [INAUDIBLE]??
BRIAN YU: Yeah.
Why const instead of let here?
Because the mouse is moving, so
the coordinates are changing,
because any one time I call
the draw point function,
the coordinates don't change.
And so I'm never resetting
coordinates later in the function.
And so it's fine to use
const here instead of let.
Other things.
Yeah.
AUDIENCE: [INAUDIBLE].
BRIAN YU: Is there a way to make the
dots actually complete each other?
Yes.
We'll talk about that
in a couple of minutes.
But yes, you can.
So all right.
Mouse move is an event that we
can use to say, all right, when
the mouse is moving, anytime the
mouse moves, let's do something.
There are other events too.
There is mouse down and mouse
up to mean when I'm clicking
and when I'm not clicking.
And maybe that's something I'd like
to do, because right now I'm drawing,
and I'm literally drawing
anytime the mouse is moving,
and so there's no way to
stop drawing, for example.
What I'd like to do is when the mouse
is down, then I should be drawing,
but when I lift up the mouse,
then don't worry about it.
So how would I do that?
What variable do I now need?
What type of variable should I add here?
Any thoughts as to how to
go about designing this?
Yeah.
AUDIENCE: [INAUDIBLE].
BRIAN YU: Yeah.
Some Boolean variable-- yes, no,
true, false, that's keeping track of,
should I actually be drawing right now?
And so we'll just call
it let drawing equal--
and we'll start off by false, because
by default, until you click down
for the first time, we
don't want to actually
be drawing on the screen
using let instead of const
because this is a
variable that I'm going
to be changing pretty frequently
as I click down and click up.
And now the idea here is going to be--
all right, SVG on mouse down.
In other words, when I
click, then let's go ahead
and run this function, whereby
I'll say drawing equals true.
I actually do want to start
drawing now when I click down.
And SVG on mouse up, let's go
ahead and say drawing equals false.
So I defined a variable called
drawing that's keeping track of,
should I be drawing right now?
When the mouse goes down, when I click
the mouse down, drawing is set to true.
As soon as I lift my mouse
up, drawing is set to false.
Questions about that.
What's the last step?
What am I missing?
Yeah.
AUDIENCE: [INAUDIBLE].
BRIAN YU: Great.
An if statement inside
of the function that's
actually doing the drawing
that basically says,
if not drawing, or in other
words, if drawing is false,
if I shouldn't be
drawing right now, well,
then just go ahead and return,
ignore the rest of the function,
just exit the function
now, because if I'm not
supposed to be drawing
right now, then I don't
want to actually calculate the
coordinates or add the circle
or do any of that.
So now, again, assuming we did
everything right, refresh the page.
I move the mouse around and,
OK, nothing's happening,
nothing's being drawn.
But if I hold down the mouse
and try and draw something,
OK, now I'm able to
actually draw on the screen.
Questions about that.
Yeah.
AUDIENCE: [INAUDIBLE] what is again that
you're doing on line 18 with D3 mouse?
BRIAN YU: D3.mousethis,
you can just think of--
this refers to like the current
event, the event of clicking.
And D3.mousethis is just
the special D3 function
that's going to say, for this
click event, where was the mouse?
In other words, what were the
coordinates of that position?
And so we can use that
to give us information
about where to actually
draw the circle, because we
want to draw the circle
wherever the mouse currently is.
Other things.
All right.
So you have a couple options
for the afternoon project.
I'll introduce it before
we all set you free.
One option is, if you
would like to, feel
free to keep working on
the quiz application.
If you didn't quite finish it, feel free
to keep working on it if you want to.
Feel free to think about
adding other features.
We talked about like saving where
you are in the game, for instance.
We talked about the
ability of adding a timer
to it, for instance, using some of
the things that we talked about today.
Or if you would like to,
expand upon this draw example.
You can either use what
you've just been working on.
If you look at draw--
I think it's drawone.HTML
in the source code examples,
you can find basically exactly this.
But here's some things that you could
try to add that you should potentially
try if you're interested.
Let's go ahead and go into draw--
draw.HTML.
Here's what a finished
product might look like.
And this is not all that much more
complicated than what we already have,
whereby you can specify a color.
Like, OK, let's draw on red.
And stroke width, OK,
let's draw on eight--
in stroke width of eight.
And you can draw--
you can draw whatever shapes you want.
Change the color.
Change the stroke width.
Draw more.
If you want to you can erase the screen.
Draw again.
And so think about the
types of features you might
want to add in order to support this.
Now, this does, in fact,
support the idea of, OK,
even if I move the mouse
quickly, we're still
able to get the idea of
things that are connected
instead of independent circles.
And the way that I'm doing this
currently that you can try to do,
it's the recommended way
to do this, is that when
you draw two points next to
each other in the same one,
just draw a line in between them.
Usually they'll be
pretty close together.
And if you draw a line in
between them, the result of it
is that you're going to
ultimately get something
that looks smooth instead
of something that just looks
like a whole bunch of independent dots.
So you can think about
adding that if you'd like to.
You can think about
adding a dropdown that
allows you to choose a
color, a dropdown that
allows you to choose a stroke width.
And ultimately you can
think about the components
that are actually making this up.
This is just a select menu
that you know how to create.
And you know how to, in JavaScript,
try and query for a particular element,
like a form input, get
it its value, and then
use its value inside of other code.
And the SVG code we've been
working with D3 is just JavaScript.
So any JavaScript code you were able to
write before you can use inside of D3
as well.
And so we'll go ahead and let
you work on your projects.
Feel free to work on either the
quiz or the drawing application
where you can support different
colors, different line weights,
clearing the board, connecting
the lines, and smooth lines,
or other features if you would like to.
And we'll go ahead and say, why don't--
I forget what we've been doing.
Why don't you all go to room
136, and you all go to room 212,
and you can stay in the middle?
All right.
And we'll reconvene tomorrow
at 10:00 AM in order
to talk more about SQL and databases.
And we'll pick up from there.
