Thursday 24 August 2017

Getting started with CSS3 Animations

CSS3 animations can give your web sites dynamic effects and visual queues for added user friendly navigation. Of course, such effects could quickly become noisy if exaggerated. I have added a sample demo of a Bookshelf with HTML and CSS3 below.

CSS3 Animated Bookshelf (Plunk)


The following HTML builds up the user interface - that is, the Bookshelf itself.


<!DOCTYPE html>
<html>

  <head>
    <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>
  </head>

  <body>
    <h1>CSS3 Animations - Bookshelf</h1>
    
    <div id="box1" class="box">
      <p>HTML 2.0 for beginners</p>
    </div>
    
     <div id="box2" class="box">
      <p>Internet Relay Chat Powertips</p></p>
    </div>
    
     <div id="box3" class="box">
      <p>MS-DOS 5.0 Masterclass</p>
    </div>
    
     <div id="box4" class="box">
      <p>QBasic Game Coding</p>
    </div>
    
  </body>

</html>

To animate these "Books", that is the < div > elements, CSS3 rules are added. The following CSS3 style sheet was added:


  /* Styles go here */

@keyframes FocusBook {
  0% { 
    transform: scale(1.1);
  }
100% {
    transform: scale(1.8) rotate(90deg);
    box-shadow: 8px 8px 8px #8080af;
    text-shadow: 1px 1px #102030;
    top: 50%;
    left: 50%;
    position: fixed;
    color: white;
    background:linear-gradient(90deg, peru, brown);
  }
}

.box {
    width:50px;
    height:250px;
    border:1px solid black;
    box-shadow: 2px 2px 2px #808080;
    background:linear-gradient(peru, burlywood);
    transform: rotate(0deg);
    transition: all 1s;
    float: left;
    opacity:0.9;
    margin: 2px;
    user-select: none;
}

.box:hover {
  transform: translate(2px, 0px) rotate(2deg) scale(1.1);
  cursor: pointer;
  box-shadow: 2px 2px 2px yellow;
  color:black;
  background:linear-gradient(45deg, peru, brown);
  z-index:20;
}

.box p {
  font-family: Verdana;
  color: charcoal;
  font-size:10pt;
  white-space: nowrap;
  transform: rotate(-90deg) translate(-190px, -10px);
}

.box:active {
  animation: FocusBook 1.0s infinite alternate;
}


To support transitions with CSS, you add the CSS attribute transition with a comma-separated list of css attributes to allow transitioning and the time the transition should take. We add first all here to allow transition all attribute changes:

.box {
    width:50px;
    height:250px;
    border:1px solid black;
    box-shadow: 2px 2px 2px #808080;
    background:linear-gradient(peru, burlywood);
    transform: rotate(0deg);
    transition: all 1s;
    float: left;
    opacity:0.9;
    margin: 2px;
    user-select: none;
}

The transition is then in effect for the hover transition.

.box:hover {
  transform: translate(2px, 0px) rotate(2deg) scale(1.1);
  cursor: pointer;
  box-shadow: 2px 2px 2px yellow;
  color:black;
  background:linear-gradient(45deg, peru, brown);
  z-index:20;
}

Now, let's take a look at the animation effect when the user clicks on one "Book". We define key frames first.
@keyframes FocusBook {
  0% { 
    transform: scale(1.1);
  }
100% {
    transform: scale(1.8) rotate(90deg);
    box-shadow: 8px 8px 8px #8080af;
    text-shadow: 1px 1px #102030;
    top: 50%;
    left: 50%;
    position: fixed;
    color: white;
    background:linear-gradient(90deg, peru, brown);
  }
}

Then we play the animation after defining the key frames (note the percentage to specify keys at a relative elapsed time of the animation):

.box:active {
   animation: FocusBook 1.0s infinite alternate; 
}

Note that the CSS attribute animation now points to the @keyframes defined. In addition, the animation uses the keywords infinite and alternate.

The best use of CSS3 animations is most likely subtle changes in color and size, and using CSS transforms. You can define many keys in @keyframes definition for complex animations.

Wednesday 23 August 2017

Getting started with web fonts in CSS

Now a simple topic in this article. We will look into how to use web fonts in CSS. Web fonts lets you add additional fonts that the users can view on your web site and offer a variation to the usual fonts that different systems support. The standard fonts or web safe fonts will become tedious and boring in the long run, web fonts will offer you variation on a grand scale! First off, we need a source for fonts where we can download fonts. You can for example download web fonts from the following site:

Font Squirrel (www.fontsquirrel.com)

Look for a web font to test out, for example Gooddog. Choose the pane Webfont kit and then hit the button Download @Font-Face kit after selecting formats to download. The format WOFF (.woff) is most compatible with different browsers. Then a .zip file is downloaded where you already can test out a demo page with the necessary CSS and HTML to get started.

First off, put the .woff file into a folder near the CSS of your web page. Now define the web font as a resource in CSS using @font-face like the following CSS rule:

@font-face {
    font-family: Good-dog;
    src: url(../fonts/GoodDog-webfont.woff) format('woff');
}

You have now defined the font resource and can use it with the friendly name you defined for font-family. For example, for the standard ASP.NET Mvc sample site for Visual Studio 2017, add this rule:
h1 {
    font-family: Good-dog;
}

.lead {
    font-family: Good-dog;
}


The result is then:
Note that you get excellent support in VS 2017 for defining such CSS rules! Also check out the license terms for the different web fonts you download. Some fonts is not free to use in commercial applications or other production. The WOFF format is not supported in IE browsers predating IE 8. Internet Explorer may also not work with uppercase letters in the url attribute of src. More info about @font-face on the following w3schools page:

@font-face CSS rule
Note that you should provide a fallback to the places in your CSS rules where you make use of the web font, such as fallback to Arial and so on. Mozilla Firefox might also deactivate web fonts intially as a security measure. Tip how to disable in Google Chrome and Mozilla Firefox:
Disable web fonts tip

Monday 21 August 2017

Trigonometric functions and integrals with Js and Canvas

This article will look into displaying trigonometric functions with Javascript and HTML5 Canvas.

A plunk is availble so you can test out different trigonometric functions in Javascript yourself. The following link gives you access to the demo:

Plunk Integral of functions using HTML 5 Canvas and Js
The form input of the demo first asks for an equation to display. Supported here is the format that the Math.Js library supports. You can use for example f(x) = sin(x). I have tested it out with 2D functions supporting one variable x. The drop down lets you choose some prefilled equations for you to test out. The different trigonometric functions supported are the usual ones, also the hyperbolic and arc hyperbolic ones can be tested out, plus some polynomial functions and so on. The Math.Js library will build up a function delegate that can be used in the calculation of the integral and the calculation of the function curve itself.



Method for drawing the equations

The javascript code below is used to draw the equations. We use Math.Js to draw the function, since Math.Js got an excellent parser to build functions that allow different plots of trigonometric functions. But also polynomial equations and so on is supported. Note the math.eval(..) line!

    Graph.prototype.drawEquation = function(polynomialequation, increment, 
     isIntegral, color, thickness, startx, endx){

        var totalArea = 0.0;

        var context = this.context;
        context.save();
        context.save();
        this.transformContext();
        
        //debugger;
        
        var parsedFunc = math.eval(polynomialequation);
        var cury = 0;

        context.beginPath();
     
        cury = parsedFunc(this.minX);
        
        context.moveTo(this.minX, cury);
        
        for(var x = this.minX + this.iteration; x <= this.maxX; x += this.iteration) {
   
          cury = parsedFunc(x);
          
          context.lineTo(x, cury);
        }

        context.restore();
        context.lineJoin = 'round';
        context.lineWidth = thickness;
        context.strokeStyle = color;
        context.stroke();
        context.restore();

        if (isIntegral){
            var context = this.context;
            context.save();
            this.transformContext();

            var currentY = 0.0;

            context.lineWidth = 0.1;
            context.strokeStyle = 'red';

            for(var x = startx; x < endx; x += increment) {
              context.beginPath();
              currentY = parsedFunc(x+increment/2.0);
              context.rect(x, 0, increment, currentY);
              totalArea += Math.abs(increment * currentY);
              context.stroke();
            }           
      
        }

        return totalArea.toFixed(2);

      };


Further issues around asymptotic behavior

One thing I have seen is that the calculation of the integral fails to detect asymptotic boundary conditions. For example, the tangens function $$ f(x) = tan(x) $$ has got several asymptotes vertically. These asymptotes occur at the following x-values: $$ \frac{\pi}{2} * (2n+1) $$ for the natural numbers $$ \mathbb{N} $$. Detecting such asymptotes can be very hard, since you have to first decide when a function becomes asymptotic, and you also have to test the function at specific intervals and narrow it down. The Riemann sum as an approximation of the integral will fail for such as asymptotic functions. I use the Midpoint rule in an easy manner here by using the average or middle point of the incrment and look at the function value right there. You could also calculate $$ f(x) $$ at the minimum and maximum part of the increment and average the two function values instead of calculating the function value at the middle point. One other way is to set the increment at a very low value.
You can also test this out yourself! Try setting the increment to a very low value, like 0.00001! You will see that the integral keeps growing as you lower the increment value. This is because small increments for the Riemann sum will more and more find the true integral of the tagens function in this case.
If you are a math student and have good tips here, I would be happy to know more about the strategy around integrals and Riemann sums to deal with asymptotes!