Reproducing A Clever Animation Product, Part 19

Today I finally finished handling adjustments to the starting time of events in the animation, using the same syntax as the Greensock product I’ve been emulating.

In order to do this cleanly I chose to build a separate list of timing events to which I could refer. This is an array of objects where each object is comprised of an element name (possibly with an extension, e.g., “:1”), an absolute starting time, and an absolute ending time. If a value is provided for the fifth (optional) parameter in the addTransformToList function then it may have two parts. One part would be a label used for a previous element, in which case the event would start at the end to the first transform event defined for that element. The other part could be a time offset, which modifies the start time based on the time just described or, by default, the end of the most recently defined transformation that extended the overall length of the animation.

The memory structures are defined like this:

The parsing of adjustments is accomplished like this:

The animation should look just the same as it has before, but using entirely new and, theoretically, more flexible notation.

Posted in Tools and methods | Tagged , , | Leave a comment

Post University CIS Advisory Board Meeting 2016

I serve as an industry representative for an advisory committee run by the chairman of the CIS Program at Post University in Waterbury, CT. In today’s annual meeting we discussed a number of issues regarding the department, its curriculum, and its future. Roughly eighty percent of the student body attends remotely and the average age is about 37.

There were a half-dozen or more participants and not nearly enough time for everyone to contribute very much, but the upshot of the observations were these:

  • Many employers would like new graduates to have better skills in working with clients and understanding how to provide value for customers. They want some insight into project management and an understanding of where requirements come from and how they’re managed. The University has a 100-level course on career and basic financial management but it was observed that a) people often get an MBA or PMP when they want to develop those skills and b) a 300-level course might be more appropriate for developing these skills at a reasonable level. By that time the students have some insight into what’s going on in the field through their coursework and since most of the students are older they may already have developed some of these skills. I’m all for giving students some context where appropriate, but mostly I wouldn’t expect a new graduate to have excellent customer skills. In my opinion, most of the problems companies have with not being able to get coders to think beyond code has to do with their own management and culture. If a worker just wants to write code and doesn’t want to think about larger problems then whose fault is that? Workers develop customer skills through education, direct work experience, mentoring, or natural personality. It seems to me that beyond some basic context it would be tough to impart much meaningful insight in a course. I say that because of my own experience in learning to work with customers and my exposure to several online courses I took as part of my PMP and Lean Six Sigma Black Belt.
  • Many areas of computing are tending towards greater abstraction. Languages and programming systems are becoming more automated and are set up to use pre-written components to the greatest degree possible with a minimum of custom code. There is a need for workers who have specific skills (e.g., Tableau) but the emphasis is increasingly on figuring out how to provide business value as opposed to figuring out how to write something intricate.
  • I observed that as a CIS program they already have a specialty. They aren’t doing pure, general purpose development like you might get at a pure computer science curriculum at MIT or Carnegie Mellon, their specialty is enterprise computing. It’s not that CIS isn’t a broad enough field on its own, but it has to know what it is and what it isn’t. They aren’t doing operating systems, compilers, device control, and so on. They are doing data management, analysis, and analytics. They might support some of the other areas on the back end, tying everything together.
  • I also observed that Post and similar institutions have to think very hard about where they’re going to be in five, ten, or twenty years. With the advent of widely available online education there are a lot of opportunities at all levels of commitment and complexity. Top flight universities make much or all of their curriculums online for free while Code Academy offers limited instruction for free while Udemy and similar providers offer tons of courses at nominal cost. A huge percentage of second- and third-tier universities are going to disappear in the next decade or two, particularly for curriculums that do not pay off for their students. Top-tier private universities and big state schools will be fine, but a lot of liberal arts and other programs are going to disappear. Technical subjects like computing provide a respectable value proposition for students and so there will be offerings in a range of niches.
Posted in Software | Tagged , , , , , | Leave a comment

Reproducing A Clever Animation Product, Part 18

Yesterday I wrote about how you’re supposed to be able to process conditional function parameters in JavaScript:

The teeeensy little problem is that neither browsers nor syntax checkers in certain development tools (WebStorm, in my case, I used it to check my code when editing in Notepad++ and running the Firefox debugger wasn’t getting me anywhere) will accept this configuration. The individual pieces are all fine, they just don’t actually work when you use them together.

Therefore I rewrote the code longhand and, voilĂ , it worked!

Obviously one should not believe everything you read on the internet–especially if you only read the first part of it. If you read just a little bit further down in the link you see that the following should work, at least in some browsers:

I can confirm that this works, at least in Firefox.

Addendum, February 17, 2017: This a) would have been better if I’d actually put the link data in the link (I’m guessing it’d be real hard to find again) and b) I’ve since learned that this behavior is one of the differences between ES5 and ES6, which I didn’t pick up on at the time. The version of WebStorm I was using was not processing ES6 constructs.

Posted in Tools and methods | Tagged , , , | Leave a comment

Reproducing A Clever Animation Product, Part 17

In the interest of making these writings fit with my schedule today and tomorrow I’m going to take a brief detour and describe the next change before completing the one that’s in progress. This will also cover something I’ll be making use of tomorrow. Looking at the current transform definitions in the addTransformToList calls:

..you can see a term for the type of transform as the fourth parameter in each call. In most cases the value is “linear,” which is supposed to mean that the transformation takes place in equal increments across its duration. The value doesn’t matter for transforms that are instantaneous, like those where the display property changes from, say, “block” to “none.” In other cases, which I haven’t developed in this series of posts but which I have implemented in parts, the transition may be nonlinear. It may move at a constant speed over most of the duration of the transform but them slow down towards the end, thus “easing” into place. The tool I’m emulating does this by default. In other cases the element may vibrate around a point, with the initial direction of movement being one way or another (left vs. right, up vs. down…). In other cases the vertical velocity may be modified by a form of “gravity” which slows the upward speed and then increases the downward speed. Other types are possible.

The Greensock demo I referenced yesterday doesn’t do anything special in this respect, so the function parameter can usually be omitted. “Linear” or nothing can be assumed, unless something special is needed, and then a string or object literal can be included that provides the necessary information. In the meantime I’m going to move the parameter to be the fifth (and currently last) parameter in the function call, so the updated code will look like this:

It turns out that if a given parameter in a function call is not provided in JavaScript that the interpreter will define the item’s type as “undefined” in a way that can be tested for as follows:

Here I’ve swapped the order of the method and adjustment parameters. I also now test the type of both parameters. If the parameter is present I interpret and use it as appropriate and if the parameter is not present I give it a default value that covers most of the cases. Here are how the resultant function calls might look:

At root some pretty complicated animation behaviors can be defined with minimal expression in user code. The code needed to support this in the background isn’t trivial, but the idea is for me to do as much work as possible so the user of the tool doesn’t have to. I do it once (in theory) and a bunch of people then get to save all their time.

Posted in Tools and methods | Tagged , , , | Leave a comment

Reproducing A Clever Animation Product, Part 16

Today I wanted to further rearrange the transition definitions so they more closely matched those used by the Greensock animation product I’ve been emulating. A screenshot from their demo video is shown here:

The next step is to move the duration parameter to be the second term in the addTransformToList function call(s) as shown here:

The next step is to get rid of the direct specification of the starting time in this call (currently the fourth parameter as shown above). In theory it would be a simple matter to track the cumulative starting times of the transforms from the delays (as they are specified in order) and use that information to replace the starting time parameter. I’m also going to add an adjustment factor that will allow the user to specify a bump forward or backward in time relative to where the starting time would have been. That’ll be handled with an optional item at the end of the parameter list.

The adjustment factor can be absolute, say, 0.25 seconds earlier than the default (the end of the previous transform), as shown in the second line of the Greensock demo image, above. Easy enough, right? Well, we also want to be able to specify a different basis for an offset, one that isn’t blindly based on the previous element but one that is referred to by its label. That should be simple enough–but what if the label is found in the list of transforms more than once? The Greensock demo doesn’t show a case where that happens but my scenario does. I think the tool should be able to handle that circumstance so I’m going to have to add in my own twist on things. I’m going to make the code handle labels with and additional specifier, separated from the label by a colon.

Let’s start by reviewing what we have so far.

Since the first four items are specified in order they could probably be left alone. However, transform 5, the first transform for the second element, starts before the end of transform 1, the first transform for the first element. Similarly, transform 7, the first transform for the third element, also happens before several of the other transforms complete. Indeed, there are three transforms that all end at the same time. We therefore need a way not only to refer to a transform by name, but also by which occurrence of that name.

There’s one more bit of complexity: how do we handle the cumulative starting time of transforms if they are specified in unexpected ways? The first four items in the above example are straightforward. They go in order, without delays, and each advances the accumulated start timer. Transform 5 has to be offset from the end of transform 1, and it won’t advance the timer. Transform 6 has to be based on transform 4 (or the end of transform 3, in theory). Transform 7 could be based on transforms 3, 4, or 6. Transform 8, finally, could be based on transforms 3, 4, 6, or 7.

Leave it to me to make things complicated, right?

I think what I’m going to do, since it would be most comprehensible to the user, is to base everything on transform 3, with the exception of transform 5, which has to be based on transform 1. That code would, in theory, look like this:

I originally saw that this case doesn’t allow for specifying a simple offset from the previous element (like the second transform in the Greensock demo), so I changed transform 8 to start with an offset directly from transform 7. What I have to decide now is whether to maintain a single, global start time accumulator or allow items with like handles to maintain their own, local start time accumulator. I think the former, but we shall see.

So what do I have here? Again, the first four are easy, as is transform 6. Transform 8 is now easy-ish because we are least have a straightforward place to start from. Transforms 5 and 7 combine both a reference to not only a label, but a complex label, and also an offset.

This completes the analysis, tomorrow we’ll tackle the code.

Posted in Tools and methods | Tagged , , | Leave a comment

Reproducing A Clever Animation Product, Part 15

After completing yesterday’s post I started digging into combining multiple CSS transforms for individual elements. I was inspired to do this because I realized that if multiple transforms were applied to an element then the string returned by referencing element.style.transform might contain specifications for multiple transforms. If that is the case then I’d have to parse the whole string to find any particular transform (e.g., if I was looking for a scale(X,Y) spec) rather than assume it was the only one supplied and therefore started at the beginning of the string.

Alas, things got complicated. It turns out that you can specify multiple transforms using CSS directly by including all the transforms on a single line in quotes like this:

What you cannot do, however, is specify multiple transformations in an equivalent way in JavaScript. It would work like this in theory:

…but the assignment doesn’t have the expected effect. I could apply the scale and rotate transforms independently in this way but if I try to assign both then only the scale transform is applied. And, that is true no matter which transform is listed first. You can still use animations to modify a transform set in this way (since only one is applied) but if you apply both using CSS and then try to use the techniques I’ve been describing then the mechanism will choke and what gets displayed will be unpredictable. I haven’t tested every combination but when I set scale and rotation using CSS and tried to animate the scale, the element simply disappeared. Goodness knows what happened to it!

If you want to apply multiple transforms and use the techniques I’ve been describing then in theory they could be applied in combination by setting the elements of the transform matrix directly. If you dereference and break apart the six matrix values (the specific example is for Chrome but the same technique applies in general) that actually describe the concatenated matrices that apply the specified combination of transforms you could do some things to back out the ones that must be applied. (Documentation of getComputedStyle function here) If only a single transform is applied then figuring out what’s going on would be pretty straightforward but things get very tricky if there are combinations of skew, scale, and rotate transforms. You can make some inferences about the likely drivers but it would be messy (and I’m not going into that in this post, though I can take a look if anyone asks).

So, we can either get crazy and try to support entirely arbitrary combinations of transforms using the style property, or we can say that our techniques work if we use only a single type of transform at a time (for any given element). Since the point of my explorations here is my own learning rather than creating a finished product (Greensock’s licensing terms are so mellow that you’d be almost foolish not to use their stuff to begin with; I embarked on this exercise because I wanted the animations on my site to use my own code) I’m inclined to keep things simple.

If I’m not going to go all the way down the multiple CSS transforms rabbit hole there are still a few more things to explore in this project, and those will be the subject of next week’s explorations.

Posted in Tools and methods | Tagged , , , | Leave a comment

Reproducing A Clever Animation Product, Part 14

Today I shortened up the way transforms are specified. Rather than specify the type of transform and its explicit starting and ending values I combined the information using object literals. Here are the new specifications, each listed after the old way, which are commented out.

The starting value in this method is determined by the current value of the relevant property for each element. Getting the starting value can be straightforward in some cases and more complex in others. You can obtain the left edge location of an element by looking at element.style.left. However, the return value for element.style.transform will be more complex. The code I’ve written so far works only for the scale property and only if that is the only property specified. If multiple transforms are to be applied to an element they all have to be specified on the same line, otherwise only the last transform specified will have any effect. I’ll work on improving that tomorrow.

The ending value is determined directly from the supplied parameter in some cases (display and scale, for now), but indirectly for the left, top, and opacity properties (again, for now). In the latter cases the specified parameter is treated as an increment rather than a target value. This is admittedly a bit quirky and I’m going to have to think about it some.

If several transformations are defined that modify the same property over time the starting value for transitions after the first one is based on the ending value of the previous transition in time. It is assumed that the user has specified subsequent transitions that don’t start until the previous ones have finished, so I haven’t taken much effort to prevent someone from specifying something that might not work as expected.

Even more interestingly, multiple transforms can be combined into a single object literal as follows, though of course they will occur over the same time span.

The animation should look exactly the same as it has previously, so that means that I haven’t broken anything obvious. I’ll go into more details about the parts of the code I changed tomorrow.

Posted in Tools and methods | Tagged , , , | Leave a comment

Reproducing A Clever Animation Product, Part 13

Today I made sure the left and right arrows could be used to advance the animation forwards or backwards by the current increment. I also highlighted the increment on the buttons used to set it.

I also learned that the slider’s oninput method calls the associated function after every change while its onchange method calls the associated function only after the mouse move is complete. Even using the slider’s oninput method, however, the added keypress processing is needed to make moving the slider with the arrow keys do anything.

Also, the arrow keys work to update the slider position and animation whether the slider has focus or not. That could turn out to be a problem is multiple items might be affected by the arrow keys, or if elements that might themselves respond to the arrow keys fail to absorb them when they have focus.

This code processes the arrow keys.

This noodleage updates the highlighting on the speed buttons.

Here is the relevant HTML. Note that using the span allows the border to be placed around the button text and not the entire button.

Just for kicks and giggles, I’ve placed the same animation in twice (in separate frames) to get an idea of the scope of processing arrow key inputs. It turns out that processing of keys is limited to each frame individually, so a) the state of each frame is independent and b) a frame has to have focus in order to process keystrokes. The animations also pause and continue independently depending on whether they are visible or have been scrolled out of view.

Posted in Tools and methods | Tagged , , , , | Leave a comment

Reproducing A Clever Animation Product, Part 12

If we have the full animation state specified for every animation step then one of the easiest things we can do is to change the speed of the animation by changing the increment, which is shown below.

Clicking on any of the speed buttons sets the animation increment by calling the setSpeed(speed) function at the bottom of the listing. Note that the current direction of animation, forwards or backwards, has to be preserved as well.

Posted in Tools and methods | Tagged , , | Leave a comment

Reproducing A Clever Animation Product, Part 11

Here is the updated version that uses the information in the bcTransformList to build the cleanest possible stream of transformation events in the bcActivitiesList. The need for a separate structure to hold the initial and final states of the animation has been eliminated and the unique state of every property type for every element is now fully specified for every property animation step. This makes some very powerful capabilities available that can be explored next week.

Here is the process that populates the bcActivitiesList from the bcTransformList.

And here are some of the functions that write out the appropriate streams of activities.

Moving the slider with the mouse demonstrates how every step of the animation is now properly displayed. A few things still need to be cleaned up, including being able to use the animation updates when the slider is moved using the arrow keys.

Posted in Tools and methods | Tagged , , | Leave a comment