Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

animating a circle with Canvas - how to expand to fill entire viewport?

Codepen

http://codepen.io/tconroy/pen/RPzxgz

Basic setup:

I am trying to create a page structured with 2 columns inside of a centered container, max 1600px wide.

The left column contains the page content. The right column contains an ad unit (say, 640x480 px wide).

At 768px or lower media breakpoint, the 2 columns should stack ( so that the content is on top, and the ad is below it ).

The problem

When the page loads, there should be a 400x400px canvas element containing a white circle in the center of the screen (absolute center -- vertical and horizontal).

The Circle animates to a position directly behind the left column content.

After this, the circle should "expand" to fill the entire user's viewport, without covering the content or causing scrollbars to appear.

As shown in my below fiddle, I have gotten the initial circle / movement animation to work, however I am running into issues trying to figure out the expand portion. I need the circle to appear to grow/expand until it covers the entire viewport, but all text content / ad unit should not be obscured and no scrollbars should appear as a result of the animation.

I'm incredibly unfamiliar with canvas, so if anyone could give me a hand with without breaking the initial animation this it would be much appreciated. :)

http://codepen.io/tconroy/pen/RPzxgz

HTML:

<div class="container">
  <div class="navigation row">
    <h1 style="float:right;"><a href="#">Continue</a></h1>
  </div>
  <div class="content row">
    <div class="circle-wrap">

      <canvas class="circle" width="400" height="400"></canvas>

      <div class="template-output">
        <h1 class="title">
              <span class="upper">Title TopLine</span>
              <span class="lower">Title Bottom</span>
            </h1>
        <div class="body">
          <p class="description">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolorum distinctio nesciunt nostrum magni neque. Iusto et delectus iure distinctio cupiditate, a sint doloremque ratione saepe sunt quisquam assumenda, eaque velit?</p>
          <p class="byline">- Author Name</p>
        </div>
      </div>

    </div>
  </div>


  <div class="ads row">
    <figure class="ad">
      <figcaption>Advertisement</figcaption>
      <div id="welcome"></div>
    </figure>
  </div>


</div>
</div>

CSS:

/* BASE STYLES */
* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

html, body {
  width: 100%;
  height: 100%;
  background: gray;
  overflow: hidden;
}

/* END BASE STYLES */
/* LAYOUT */
.container {
  width: 100%;
  height: 100%;
  max-width: 1600px;
  margin: 0 auto;
  outline: 1px solid black;
}

.row {
  width: 50%;
  height: 100%;
  float: left;
  display: block;
}
.row.content {
  border: 1px solid blue;
}
.row.ads {
  border: 1px solid red;
}
.row.navigation {
  width: 100%;
  height: auto;
}
@media screen and (max-width: 768px) {
  .row {
    width: 100%;
    height: auto;
  }
}

/* END LAYOUT STYLES */
/* ADVERTISEMENT */
.ad {
  display: table;
  margin: 0 auto;
}
.ad figcaption {
  text-align: center;
  margin: 0 auto;
}
.ad #welcome {
  outline: 1px solid black;
  background: darkgray;
  width: 640px;
  height: 480px;
  margin: 0 auto;
}

/* END ADVERTISEMENT STYLES */
/* CONTENT */
.content {
  min-height: 400px;
}
.content .template-output {
  width: 400px;
  position: relative;
}
.content .template-output .title {
  font-size: 4em;
}
.content .template-output .title span {
  display: block;
  text-transform: uppercase;
}
.content .template-output .title .upper {
  text-align: left;
}
.content .template-output .title .lower {
  text-align: right;
}
.content .template-output .body {
  position: relative;
}
.content .circle-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  margin: 0 auto;
}
.content .circle-wrap .circle {
  width: 400px;
  height: 400px;
  outline: 1px solid black;
  position: absolute;
  left: 0;
  top: 0;
  transform: translate(0%, 0%);
}
.content .circle-2 {
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
}

/* END CONTENT STYLES */

JAVASCRIPT (included: jQuery and GSAP TweenMax libraries)

/*
  I have successfully created the canvas element in the center 
  of the screen and animate it to the left column. Now, I want the circle to "expand" behind the content, and fill the entire viewport.
  It should not cause scrollbars to appear or cover the text content.
*/
(function () {

    var tl = new TimelineMax();

    var $canvas = $('.circle'),
        $canvas_wrap = $('.circle-wrap'),
        canvas = $canvas[0],
        context = canvas.getContext('2d'),
        canvas_width = canvas.width,
        canvas_height = canvas.height;
        context.globalCompositeOperation='destination-over';
    draw(context);


    /* TIMELINE STUFF */
    var canvas_opts = {
        'center-to-destination': {
            xPercent: -50,
            yPercent: -50,
            top: '50%',
            left: '100%',
            delay: 1.5
        }
    };
    tl.from(canvas, 1, canvas_opts['center-to-destination']);


})();
like image 646
tdc Avatar asked Aug 20 '15 23:08

tdc


People also ask

How do I make my canvas full screen?

Code to make canvas occupy full page :width = window. innerWidth; canvas. height = window. innerHeight; //Done!

What is HTMLCanvasElement?

The HTMLCanvasElement interface provides properties and methods for manipulating the layout and presentation of <canvas> elements. The HTMLCanvasElement interface also inherits the properties and methods of the HTMLElement interface.

Can you animate on canvas?

You can create animations with HTML5 by combining HTML, CSS, and JavaScript (JS), with which you can build shapes. Also, you can control animations and edit images, video, and audio by means of JS or CSS elements, all of which you then add to a drawing board, which you set up with the <canvas> element.

How do you animate in JavaScript?

To make an animation possible, the animated element must be animated relative to a "parent container". The container element should be created with style = "position: relative". The animation element should be created with style = "position: absolute".


1 Answers

This is what I have been able to produce based on my understanding, I could be wrong.

Here is what has changed from your code:

  • canvas HTML element has been promoted and moved out, put just before opening of container HTML element.
  • Both canvas and container have been given a position: absolute with z-index values of 0 and 1 respectively, through the use of .set() methods of TweenMax in JavaScript.
  • canvas's width and height are also set to innerWidth and innerHeight of window object respectively.
  • A continuous running render method is created which is hooked into tick event which is fired by ticker object present inside TweenLite object.
  • Initial properties for the animation are set in canvasProps object.
  • This canvasProps object is then animated using three calls to .to() method of TweenMax.
  • Finally, the render method keeps refreshing the canvas and draws a circle based on the continuously changing values found within canvasProps method.

JavaScript:

(function() {
  var container = $('.container');
  var canvas = $('.circle')[0];
  var context = canvas.getContext('2d');
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  TweenMax.set(container, { position: 'absolute', zIndex: 1 });
  TweenMax.set(canvas, { position: 'absolute', zIndex: 0 });

  var canvasProps = {
    currX: window.innerWidth * 0.5,
    currY: window.innerHeight * 0.5,
    currRadius: 0
  };

  TweenLite.ticker.addEventListener('tick', render, false);
  TweenMax.to(canvasProps, 1, { currRadius: 200, ease: Expo.easeInOut });
  TweenMax.to(canvasProps, 1, { delay: 1, currX: 200, ease: Expo.easeInOut });
  TweenMax.to(canvasProps, 1, { delay: 2, currRadius: window.innerWidth, ease: Expo.easeInOut });

  function render() {
    context.clearRect(0, 0, window.innerWidth, window.innerHeight);
    context.beginPath();
    context.arc(canvasProps.currX, canvasProps.currY, canvasProps.currRadius, 0, Math.PI * 2, true);
    context.fillStyle = 'white';
    context.fill();
  }
})();

Hope this helps.

like image 81
Tahir Ahmed Avatar answered Oct 18 '22 22:10

Tahir Ahmed