Sieve of Eratosthenes in AngularJS with better but not perfect animation
Hi, I'm Chris Dawson a dad and writer from Portland, OR, now living in Florida. My book is Building Tools with GitHub from O'Reilly. I'm an inventor, have started several companies and worked for several non-startups like Apple and eBay. I am sometimes available for hire as a consultant or part time contributor.

In my last post I explored how to build the Sieve of Eratosthenes using AngularJS. The one issue I disliked was that my animation of the algorithm process did not really reflect the true timing if each step were slowed down to allow a human to watch it operate. You can do this if you use JS timeouts, but using timeouts with recursive algorithms leaves a bad taste in the mouth.

I have been thinking about this for a few days and I think I have a good solution. At each important step save the state of the process and then have a separate timeout looping over those states and displaying them. The user gets a true calculation without wrapping recursion inside a timeout callback, and the UI displays correctly.

For example, this code shows what I mean:

$scope.save = ( arr ) ->
        $scope.states.push {
                marking: arr?.marking,
                primes: angular.copy( $scope.primes ),
                looking : arr?.looking,
                found: arr?.found,
                p : $scope.p,
                numbers: angular.copy( $scope.numbers )
                }

I built a function called state which simply saves the state at any point. I know which variables are interesting inside my algorithm: in the case of the Sieve of Eratosthenes, they are the P value, the value of the current index when looking for the next prime (called looking here) and when a new prime has been found. I also have an array of the current primes, and the entire set of numbers. Also, if you need to copy an object like an array which is not a simple value you need to use angular.copy to do a deep copy. Otherwise you are just copying a reference and your data will be coming from the moment in time the variable is referenced, rather than the moment in time when the save() method was called.

Then, after I start my algorithm, I set a timeout to iterate over all the state objects, putting a new state into the current state.

$scope.startAnimation = () ->
        console.log "Jumping to next state"
        if $scope.states.length > 1
                $scope.the_state = $scope.states.shift()
                $timeout( $scope.startAnimation, $scope.stepInt )

I had to change the HTML code to use the_state.primes instead of referencing primes.

You can see all this in action on the gh-pages site or in the repository.

There is a problem which I have not hunted down yet: the CPU slowly gets to 100% with this code. I am unclear as to why: it seems like the intensive portion should be the place where I copy in the arrays and that timeout should simply be copying a reference. But, towards the end of the algorithm, my browser starts to crawl.

Also, the explosion animations are lost. This is because I am rebuilding the DOM with new data each time a new state is popped off the stack, instead of modifying some existing data such that AngularJS knows a change has occurred. The way to fix this is to do a diff of the state as rendered in the browser from the state popped off the stack. This would mean that AngularJS would notice a change in the $digest() cycle and add the proper CSS classes for the animations. This diffing operating looks pretty straightforward in this case, but not something I want to write now.

Subscribe to RSS by tags if you only want certain types of posts. Or, subscribe to all posts.
View source to this post
Other interesting things:
<
>
Webiphany.com
https://webiphany.com
1
2
3
4
5
6
7
8
9