Category - Tutorials

Intro to Canvas

What is Canvas?

Canvas is an HTML5 element, that for all intents and purposes, allows you to draw your own dynamic pictures. It really is like creating an image on the screen. This can be at the base level of drawing lines, circles, and curves, OR you can go deeper and include images and videos.

Here is an example of using videos in canvas - HTML5 Video Destruction

I find that considering the canvas element an image that you get to draw on the fly, erase and redraw to your hearts delight really helps process how it works in regards to sizing and animation.

Many people think of games when they think of canvas, however, I think the possibilities go far beyond that. With canvas we can open up the doors to interactive menus that entice the user to explore, rather than give them a list that they skim and move along. Example http://www.infinityblade.com/. Canvas also gives us the ability to create fully immerse the user in an experience or storyline. Example http://www.gmc.com/incrediblethinking.

The possibilities are endless. Some things we can do with CSS3 animations, however, canvas goes far beyond that.

However, whenever you talk about having a lot of power and possibilities.. that usually means you got a lot of code...To understand how some of the above examples did their work, let's start with some ABC's of Canvas.

  1. Creating a Canvas Element

    In order to go through the basics of creating lines, rectangles and circles, I needed an goal that could be broken down into those fundamental bricks. I took inspiration from Chris Spooner's tutorial on creating vector ninjas Illustrator Tutorial - Creating a Gang of Vector Ninjas and we will create a similar ninja but with straight canvas.

    For this tutorial we will work with a basic html file. You can write this in any framework you utilize, this can be ASP.Net, ASP MVC, Wordpress, or even a plain html file.

    In the body of the page add the following html code:

    
    
    

    The default width and height I have defined above for the canvas element, is actually the default values of a canvas element. As noted in the comments, you really are creating a custom dynamic on the fly image! It even defaults to the display type of inline. In order to visually see where the canvas is, let's add a little bit of css. You can add this inline, internal or external:

            #ninja {
                display: block;
                margin: 2em auto;
                border:1px solid red;
            }
    

    Not quite ready... now we need to get somethings prepared with javascript... It is VERY important to give your canvas elements an ID, an easy way to target it. You can NOT use jQuery to select a canvas object, you must use straight up javascript. Which is easier with an ID. The reason for this is we will have to access a special method of a javascript object that jQuery objects do not expose for us. At the bottom of the page add a script tag and put the following code inside:

            //first retrieve the canvas element object using
            //straight javascript
            var canvas = document.getElementById('ninja');
            //create a reference to the context of the canvas object
            //the context will be used for all drawing operations
            var context = canvas.getContext('2d');//someday we will have 3d...
            //You can set a stroke (border) or fill (inside) style
            context.strokeStyle = '#000';//can use any css valid color
            context.lineWidth = 3;//or '3'
            context.fillStyle = 'grey';
    

    Finally! Canvas created! The strokeStyle is used for color of the border around a shape, the fillStyle is used for the color of the inside of a shape. There are a ton of options for gradients, shadows etc! Be wary of using shadow too much, it tends to be the heaviest on the processor. Okay.. so let's start drawing!

  2. Drawing a Rectangle

    Almost everything we do will utilize the context object we created above. The only time we reference the canvas is typically for equations with it's height and width. I'm going to contain our code in several different functions, really breaking the code out and hopefully making this tutorial easier to follow.

    Inside your script tag after setting the context's properties, add the following code:

            //Call draw ninja function created below!
            drawNinja();
            //**************************FUNCTIONS***************************
            function drawNinja() {
                
                //call methods for all the ninja parts!
                drawBody();
            }//end drawNinja()
            function drawBody() {
                context.beginPath();//declare we are about to start drawing
                //To draw a square rect use
                //rect(top left x, top left y, width of square, height of square)
                //the shape is drawn to the right and down from the x,y coords
                context.rect(130, 60, 40, 30);
                //call the stroke and fill methods as needed to apply styles
                context.stroke();
                context.fill();
            }//end drawBody()
    

    Refresh the page and you should now see a ninja body! The .rect() method takes the following arguments:

    Canvas Ninja Body
    1. The top left corner x coordinate
    2. The top left corner y coordinate
    3. The width of the rectangle to be drawn
    4. The height of the rectangle to be drawn

    After defining the path you then need to call fill() and/or stroke() to actually color them. Each time we draw a path it is really an invisible line that we then need to color in. So after defining the invisible path and applying some color we get a great ninja butt! Exciting right?? Okay.. so maybe we need some more..

  3. Drawing a Circle

    Next we need to draw the head. Let's start by adding a function call to our drawNinja() method. Change the code for the drawNinja() method to reflect below:

            function drawNinja() {
                //call methods for all the ninja parts!
                drawBody();
                drawHead();
            }//end drawNinja()
    

    Then scroll down after the //end drawBody() and add the following new function:

            function drawHead() {
                context.arc(150, 40, 30, 0, Math.PI * 2);
                //PI is only HALF of a circle!
                //.arc(center X, center Y, radius, starting angle (using pi), end angle)
                //optional argument for anticlockwise, default is false
                //apply colors
                context.fill();
                context.stroke();
            }//end drawHead()
    

    This will NOT produce the desired result. We will fix the ugliness below, but first, let's talk about the arc method. The picture below should help explain the start and end points. The arc method takes the following arguments:

    Math PI
    • The x coordinate for the center of the circle to be drawn.
    • The y coordinate for the center of the circle to be drawn.
    • The number of pixels to use for the radius (center to outside)
    • The starting point of the arc using PI
    • The ending point of the arc using PI
    • Optional argument to draw anticlockwise
    Canvas Ninja Ugly Body

    Everytime we draw a path with canvas we are placing the pencil on the paper and tracing all of these paths to various points on the canvas screen. Finally, we add stroke or fill effects. The pencil NEVER lifts off the paper. This is like the old game of trying to draw a 3d cube without lifting the pencil off the paper. Thankfully, we don't have to play that game... Anytime we want to lift the pencil off the paper and start in a new spot we can just call the beginPath() method.

    Change the drawHead() function's code to add the call to the beginPath() method per below:

            function drawHead() {
                context.beginPath();//begin a new path!
                //think of the beginPath() method as lifting your pencil off the paper
                //and placing it in a new location!
                context.arc(150, 40, 30, 0, Math.PI * 2);
                //PI is only HALF of a circle!
                //.arc(center X, center Y, radius, starting angle (using pi), end angle)
                //optional argument for anticlockwise, default is false
                //apply colors
                context.fill();
                context.stroke();
            }//end drawHead()
    
    Canvas Ninja Head and Body

    Finally, we got a decent head and body... however... we also need a face!! First, we need to talk about the NonZero winding rule!

  4. NonZero winding rule

    Update the drawHead() function to reflect the additional arc added to the code below:

            function drawHead() {
                context.beginPath();//begin a new path!
                //think of the beginPath() method as lifting your pencil off the paper
                //and placing it in a new location!
                context.arc(150, 40, 30, 0, Math.PI * 2);
                //PI is only HALF of a circle!
                //.arc(center X, center Y, radius, starting angle (using pi), end angle)
                //optional argument for anticlockwise, default is false
                //now for the face!
                context.arc(150, 45, 15, 0, Math.PI * 2);
                //apply colors
                context.stroke();
                context.fill();
            }//end drawHead()
    

    When you refresh the page you will see NO notable changes. I assure you a second circle was drawn...if you try to add a beginPath() before the second arc, you'll end up with a shrunken head, so don't do that!

    Change the second arc method to add a ", true" at the end of it's argument list and the following comment per below:

                //Nonzero winding rule for filling paths.
                //Draw a straight light from inside the area until it is completely
                //ouside of the shape. 
                //Start at 0
                //+1 for each clockwise path
                //-1 for each counterclockwise path
                //if the final count is zero, it is a cutout
                //now for the face!
                context.arc(150, 45, 15, 0, Math.PI * 2, true);
    

    When you run this now, you will see a head with a circle cutout of the middle. Eventually we will turn this into two partial arcs, BUT, let's explain why adding the anti-clockwise created the desired cutout effect.

    Canvas Ninja No Cutout

    I've created two quick images to help illustrate this rule. Starting from the center of a shape, draw a line to the outside of the outermost shape. Start counting at 0. For each clockwise drawn line you cross add 1. For each counter clockwise (anticlockwise) drawn line you cross minus 1.

    Canvas Ninja Cutout

    If both circles are drawn clockwise, then the center is evaluated to +2. Which means it is part of the overall shape. If the innermost is drawn counterclockwise, then the center is evaulated to 0 and it is considered to be a cutout shape.

  5. Cutouts and beginPath()

    For the face we really don't want a solid circle. The effect we are looking for is two partial circles combined to create a cutout for the face. And then two small circles for the eyes. Update the code below the comment for "now for the face" to the below code (note we are commenting out the arc from above):

                //now for the face!
                //context.arc(150, 45, 15, 0, Math.PI * 2, true);
                //However... we don't want a circular face....
                //so let's draw two arcs
                //make one counterclockwise so that it becomes a cutout
                context.arc(150, 45, 15, Math.PI * 1.1, Math.PI * 1.9, true);
                context.arc(150, 25, 20, Math.PI * .3, Math.PI * .75);
                //apply colors
                context.stroke();
                context.fill();
    
    Canvas Ninja Face

    Again, refer to the above diagram regarding Math.PI if this arc code is throwing you for a circle. (That's kinda punny). Because the top arc is counterclockwise the center has a path that evaluates to 0 from the inside, so it is considered a cutout.

    Now let's add an eye. Directly under the above code but still inside the drawHead() method add the following code:

                //need some eyes
                context.arc(144, 51, 1, 0, Math.PI * 2);
                context.stroke();
    
    Canvas Ninja Eye Patch

    This will not create the desired effect... You should see the small 1 radius full circle appear at 144,51 but there is a line connecting it to the inner face arc. I call this the EyePatch effect! Remember, without telling the context to start a new path the pencil stays on the paper!

    Add the beginPath() to the code per below:

                //need some eyes!
                context.beginPath();//begin a new path!
                //think of the beginPath() method as lifting your pencil off the paper
                //and placing it in a new location!
                context.arc(144, 51, 1, 0, Math.PI * 2);
                context.stroke();
    

    Yay! We have one eye! Now let's add a second. Change the code to the below and see if you can guess what it will look like BEFORE you refresh the page.

                //need some eyes!
                context.beginPath();//begin a new path!
                //think of the beginPath() method as lifting your pencil off the paper
                //and placing it in a new location!
                context.arc(144, 51, 1, 0, Math.PI * 2);
                context.stroke();
                //other eye
                context.arc(156, 51, 1, 0, Math.PI * 2);
                context.stroke();
    

    Were you right? If you guessed that your ninja would be wearing glasses or have a unibrow, well done! Now let's add one more beginPath() to fix the other eye. Your code for the other eye should now be as follows:

                //other eye
                context.beginPath();//separate the eyes!
                context.arc(156, 51, 1, 0, Math.PI * 2);
                context.stroke();
    
    Canvas Ninja The Eyes Have It

    Rock on. Super cute ninja on the way! Now to give them some arms and legs. Unless they are a super uber awesome ninja, they won't be able to do much without some limbs!

  6. Drawing a Rounded Rectangle

    For the limbs, I don't want them to be super boxy, I'd really like them to have some rounded corners. This was one of the best effects to come from CSS3. Back in the day we didn't have no border-radius, stinky programmer youngsters got it easy! Well, in canvas, you'll have to do some work to make the effect! We can create rounded rectangle corners with arc or arcTo. Let's start by creating a limb test so we can learn how to make the rounded rectangles.

    Because the order the items is drawn matters in regards to stacking, we will add the limbs BEFORE the body or head is created. This will ensure the limbs get drawn, then the body over the top, and then the head.

    Update the drawNinja() function to the code that follows:

            function drawNinja() {
                //call methods for all the ninja parts!
                drawLimbTest();
                drawBody();
                drawHead();
            }//end drawNinja()
    

    You should see a small square limb appear in the top corner of the canvas. Soon we will talk about ways to transform the canvas by using translate to move the 0,0 axis point and even rotate the canvas. So we will take one drawn limb, and iterate through the code moving the canvas around and spinning it to draw 4 identical limbs, in 4 different places.

    As you can see there is no method for rounding a rectangle. There are some methods others have created that you can paste in or they are pretty easy to make once you understand how it works.

    Instead, we have to manually draw each line. Let's start there. Change the drawLimbTest() method to the below code:

            function drawLimbTest() {
                //you can NOT create rounded corners with the rect() method
                //You have to draw each side.. and the corners..
                //First limb drawing at 20, 20
                //context.rect(20, 20, 10, 20);
                //context.stroke();
                //context.fill();
                //to create a rounded rectangle...first draw a box with lines
                context.beginPath();//lift the pencil!
                context.moveTo(10, 10);//starting point
                context.lineTo(20, 10);
                context.lineTo(20, 30);
                context.lineTo(10, 30);
                context.lineTo(10, 8.5);//line width is 3, so removed half of the line width
                context.stroke();
                context.fill();
            }//end drawLimbTest()
    

    Little tricky spot on the last line. Our line width is 3, so we had to go up an extra 1.5 (half of 3) pixels to get a solid rect. The effect isn't any different than just using context.rect. However, now at each corner we need to move the lines back a little bit to give us room for our rounded corners. There is a TON of different ways to get this effect. I'm going to use the arc() method because we have focused on that one a bit already. Change the code for the rounded rectangle to the below code:

                //to create a rounded rectangle...first draw a box with lines
                context.beginPath();//lift the pencil!
                context.moveTo(12, 10);//starting point
                context.lineTo(18, 10);
                context.arc(18, 12, 2, Math.PI * 1.5, Math.PI * 2);
                context.lineTo(20, 28);
                context.arc(18, 28, 2, Math.PI * 2, Math.PI * .5);
                context.lineTo(12, 30);
                context.arc(12, 28, 2, Math.PI * .5, Math.PI * 1);
                context.lineTo(10, 12);
                context.arc(12, 12, 2, Math.PI, Math.PI * 1.5);
                context.stroke();
                context.fill();
    
    Canvas Ninja Detached Limb

    If you refresh the page again you should now have the same result as me, with a lovely detached limb hanging off to the side. So, how are we going to move this around? I'm so glad you asked!

  7. Basics of Transform

    We are going to continue tweaking and playing with the drawLimbTest() function. I like created these "proof of concept" functions when I'm creating a new application so that I can easily chop it out of the end product after I have things figured out.

    At the beginning of the drawLimbTest() function add the following code:

            function drawLimbTest() {
                //Let's change the canvas context!
                context.scale(2, 2);
    

    Scale allows you to multiple the x and y coordinates separately. Here we have doubled the distance an x pixel and a y pixel over. This really starts to make canvas feel more like a "vector" image. However, you will notice that it changed ALL of the contexts. Since our drawNinja() function calls the drawLimbTest() before it calls the drawBody() and drawHead() we changed the context and it remained scaled up for the rest of the program.

    The context provides a save() and restore() method. The save() method allows you to save the current state of the context. Including, but not limited to, fillStyle, strokeStyle, scale, etc! Then after you have changed the context, sometimes drastically and used it, you can use the restore() method to return to the previously saved context state.

    Update the whole function drawLimbTest() code to look per below (note: I've added a context.save() at the start of the method and a context.restore() at the end.):

            function drawLimbTest() {
                //If you will be modifying the context and changing several properties
                //for a special method, you can save() the current state BEFORE drawing
                //then restore() it to the previous position
                context.save();
                //Let's change the canvas context!
                context.scale(2, 2);
                //you can NOT create rounded corners with the rect() method
                //You have to draw each side.. and the corners..
                //First limb drawing at 20, 20
                //context.rect(20, 20, 10, 20);
                //context.stroke();
                //context.fill();
                //to create a rounded rectangle...first draw a box with lines
                context.beginPath();//lift the pencil!
                context.moveTo(12, 10);//starting point
                context.lineTo(18, 10);
                context.arc(18, 12, 2, Math.PI * 1.5, Math.PI * 2);
                context.lineTo(20, 28);
                context.arc(18, 28, 2, Math.PI * 2, Math.PI * .5);
                context.lineTo(12, 30);
                context.arc(12, 28, 2, Math.PI * .5, Math.PI * 1);
                context.lineTo(10, 12);
                context.arc(12, 12, 2, Math.PI, Math.PI * 1.5);
                context.stroke();
                context.fill();
                
                context.restore();//restoring context properties to previous values
            }//end drawLimbTest()
    

    Now, when you refresh the page you will see that you saved the state of the context (unscaled) made the limb appear supersized, then restored the context to its previous state before continuing on with the program and drawing the ninja.

    scale() isn't a method we will need, but it quickly helps to illustrate the need for save() and restore(). Let's comment that out and instead playing with translate() and rotate().

    Change the code under the "Let's change the canvas context!" comment to reflect the changes below:

                //Let's change the canvas context!
                //context.scale(2, 2);
                //rotate by degrees equation
                //(Math.PI/180) * degrees
                //Canvas rotates on it's 0,0 axis by default
                context.rotate((Math.PI / 180) * -45);
    

    Rotate creates an interesting problem. You'll note that it definitely appears that the limb rotated -45 degrees, however, the limb is partially off the screen! This is because the rotation happens at the 0,0 axis of the canvas object. Typically we draw the shape we want to rotate at that same 0, 0 axis so that the top left corner of the canvas that will be rotating coincides with the top left corner of our shape.

    Let's see what happens when you translate the canvas and move the x and y coordinates in combination with a rotate and an object that is not drawn from the 0,0 coords.

    Update the code for "Let's change the canvas context!" to the following code:

                //Let's change the canvas context!
                context.translate(50, 50);
                //context.scale(2, 2);
                //rotate by degrees equation
                //(Math.PI/180) * degrees
                //Canvas rotates on it's 0,0 axis by default
                context.rotate((Math.PI / 180) * -45);
    

    You will notice that the limb shifts 50 pixels to the right and 50 pixels down. However, if you play with the degrees in the rotate the result becomes extremely unpredictable!

    This is the problem you have when mixing translate() with rotate(). If you will be using both be CERTAIN that your drawing is begun at 0,0 so that you can have a predictable result from rotating and translating.

    We will create the real limbs by using translate() to move the canvas to where we want and then rotate the canvas if it is for one of the arms, finally draw our limb focused on the 0,0 starting coordinates.

  8. Finishing the Ninja!

    Let's go clean up our drawNinja() method by removing the call for the test function and creating a call to a real function called drawAllLimbs(). Change the drawNinja() method to reflect the below code:

            function drawNinja() {
                //call methods for all the ninja parts!
                //drawLimbTest();//for testing and learning
                drawAllLimbs();
                drawBody();
                drawHead();
            }//end drawNinja()
    

    Here comes the coding part! Now that we have some foundation let's look at applying those concepts and work through the pieces. I'm also going to introduce a few javascript concepts such as creating arrays and javascript objects. Add the below code after your close of the drawNinja() function:

            function drawAllLimbs() {
                //create a new javascript array with []
                //you can immediately instantiate variables in the array.
                var limbs = [
                    { name: 'leftleg', x: 160, y: 88, angle: null },
                    { name: 'rightleft', x: 130, y: 88, angle: null }
                ];
                //javascript arrays are like C# stacks
                limbs.push({ name: 'leftarm', x: 164, y: 66, angle: -45 });
                limbs.push({ name: 'rightarm', x: 130, y: 58, angle: 45 });
                
                //foreach with javascript
                //(arrayvariable).forEach(function(nameOfEachItem) {
                //    //work to do
                //});
                limbs.forEach(function (limb) {
                    drawLimb(limb);
                });
            }//end drawAllLimbs()
    

    The code above creates an array of limbs with details about each. In an upcoming tutorial we will talk about animations and I'll utilize this ninja demo to make him wave. So some of this code is written to allow us to identify which limb is being drawn to conditionally change it later. That is why each object stores the name. It also has a list for the x,y coordinates of where the context will need to be translated to, as well as if it is an arm, the degrees the context will need to be rotated.

    I try to write tutorials for the assumption that you may not know how to do some things, so I err on the side of over explaining. Honestly, I didn't get far into javascript until I started working with canvas.

    After the array of limbs is created a foreach iterates through each and passes a reference to a drawLimb() method. I could have written all this code together, but I'm a big fan of self documenting code and refactoring. Most IDEs are advanced enough to allow you to jump to a definition of a method. So keeping the moving pieces to a minimum, in my opinion, makes it easier to absorb and make a desired change.

    Anyway, let's add the last major code section for the drawLimb() function. After the end of the drawAllLimbs() add the following code:

            function drawLimb(limb) {
                //saving the context is especially useful when transforming, translating,
                //scaling or rotating the canvas.
                context.save();
    
                //lets translate the context's x,y 0,0 coordinates
                //to the new desired location for the upper left corner of the limb
                context.translate(limb.x, limb.y);
    
                //rotate if needed
                if (limb.angle != null) {
                    //rotate by degrees equation
                    //degrees*Math.PI/180
                    context.rotate((Math.PI / 180) * limb.angle);
                }
    
                //let's create a rounded box, but focus on the 0, 0 coords
                //it'll be easier to handle with translating
                context.beginPath();
                var radius = 2;
                context.moveTo(2, 0);//tl
                context.lineTo(8, 0);//tr
                context.arc(8, 2, radius, Math.PI * 1.5, Math.PI * 2);
                context.lineTo(10, 18);//br
                context.arc(8, 18, 2, Math.PI * 2, Math.PI * .5);
                context.lineTo(2, 20);//bl
                context.arc(2, 18, 2, Math.PI * .5, Math.PI);
                context.lineTo(0, 2);//tl
                context.arc(2, 2, 2, Math.PI, Math.PI * 1.5);
    
                context.stroke();
                context.fill();
    
                context.restore();//restoring context properties to previous values
            }//end drawLimb()
    

    Pretty close!! Just one problem left...

    We are drawing all of the limbs, then the next function that gets called in drawNinja() calls the drawBody() method Before we start each limb, we are calling a beginPath(), however... if you look at the drawBody() method, it does have a beginPath() call at the beginning. So the last limb drawn (right arm) is counted as part of the body and the nonzero winding rule makes them a solid object...

    Updated the drawBody() method to include a beginPath() at the beginning. The entire drawBody() method should now look like:

            function drawBody() {
                context.beginPath();//separating the right arm from the body
                //To draw a square rect use
                //rect(top left x, top left y, width of square, height of square)
                //the shape is drawn to the right and down from the x,y coords
                context.rect(130, 60, 40, 30);
    
                //call the stroke and fill methods as needed to apply styles
                context.stroke();
                context.fill();
            }//end drawBody()
    
    Canvas Ninja

    Finally, you should have a ninja that looks like the picture to the side.

    There are certainly cleaner ways to do this and you could even argue that not using a lot of beginPath()'s to create a more solid ninja could make it look better.

  9. Summary

    My goal was to show you the fundamentals of:

    • Creating a canvas element
    • Accessing a canvas's context property
    • Using the context to draw:
      • Rectangles with rect()
      • Circles or arcs with arc()
      • Moving to a particular point with moveTo()
      • Lines with lineTo()
    • Modifying the context:
      • Starting a new path with beginPath()
      • Zooming in or out with scale()
      • Shifting the canvas with translate()
      • Rotating the canvas with rotate()

    You can download the completed version of this code here - Canvas Ninja Final Code .

    You can also view the demo at Demo - Canvas Ninja.

    In closing, canvas is definitely a code heavy affair. However, it truly allows you to accomplish anything you want. You dream it, and canvas can do it! Eventually as CSS3 animations get stronger and CSS effects in general, many of the effects we create with canvas, I anticipate will gravitate towards being able to use straight html or css. In the meantime, get a white board, a couple of aspirin or a strong drink and get ready for an mathematical assault when diving into canvas.

sverigapotek37@gmail.com

Comment

alternativ till, http://sverige-apotek.life/index-386.html , sälja säkert.

sverigapotek37@gmail.com

Comment

köpa i göteborg, http://sverige-apotek.life/lolergi.html , kostar Danmark.

fantasyfootballblog.co.uk@gmail.com

Comment

danmark, http://www.fantasyfootballblog.co.uk/wp-includes/pomo/apotek/anexa.html - kopiprodukter pris.

birchoverstone.co.uk@gmail.com

Comment

Frankrijk prijs, http://www.birchoverstone.co.uk/wp-includes/certificates/apotheek/unisom.html , prijzen online.

rhythmschinesemedicine.co.uk@gmail.com

Comment

online uk, http://www.rhythmschinesemedicine.co.uk/wp-content/uploads/2017/01/apotek/synflex.html - købe tabletter.

tattershallkartingcentre.co.uk@gmail.com

Comment

Kopen belgie duitsland, http://www.tattershallkartingcentre.co.uk/wp-content/languages/apotheek/glucocorticoid.html , pillen kopen in winkel kopen.

carolefrancissmith.co.uk@gmail.com

Comment

bedste sted at købe online, http://www.carolefrancissmith.co.uk/wp-content/languages/apotek/lotrisone.html - prisfald pris.

prefast.co.uk@gmail.com

Comment

Bestellen zonder recept nederland, http://www.prefast.co.uk/wp-includes/css/apotheek/ranitidina.html , nederland rotterdam.

enjoytheviews.co.uk@gmail.com

Comment

Generic online, http://www.enjoytheviews.co.uk/wp-includes/certificates/apotheek/letrozole.html , nederland kopen amsterdam.

dada2rara.com@gmail.com

Comment

priser europe, http://www.dada2rara.com/wp-includes/certificates/apotek/quetiapine.html - kapsler recept.

sjah.co.uk@gmail.com

Comment

håndkøb apotek københavn, http://www.sjah.co.uk/wp-includes/certificates/apotek/informet.html - uden recept recept.

hostinghints.co.uk@gmail.com

Comment

Kopen bij drogist amsterdam, http://hostinghints.co.uk/wp-includes/certificates/apotheek/olopatadine-hcl.html , online bestellen amsterdam.

paolofiorentini.com@gmail.com

Comment

bestille europe, http://www.paolofiorentini.com/pf/wp-includes/css/apotek/retin-a-gel.html - hvad koster europe.

ealesandbaker.co.uk@gmail.com

Comment

Kopen in frankrijk belgie, http://www.ealesandbaker.co.uk/wp-includes/css/apotheek/dectancyl.html , nederland online.

natalie.pierotti.org.uk@gmail.com

Comment

bestall priser, http://natalie.pierotti.org.uk/wp-content/uploads/apotek/bisacodilo.html , generic Sverige.

runenordahl.no@gmail.com

Comment

i Sverige uten resept jeg, http://runenordahl.no/wp-includes/certificates/apotek/zitromax.html , kan man kjøpe uten resept i Norge netthandel.

fletrebygg.no@gmail.com

Comment

uten resept Norge Oslo, http://fletrebygg.no/wp-includes/certificates/apotek/penegra.html , kjøpe i Norge Norge.

aqsgroup.co.uk@gmail.com

Comment

Danmark Stockholm, http://natalie.pierotti.org.uk/wp-content/uploads/apotek/ramipril.html , billigt Sverige.

oldvarieties.com@gmail.com

Comment

hvad koster danmark, http://oldvarieties.com/contents1a/wp-includes/certificates/apotek/letrozolo.html - kopiprodukter uden.

bobquatrello.com@gmail.com

Comment

Kopen amsterdam rotterdam, http://www.bobquatrello.com/wp-includes/certificates/apotheek/gladem.html , prijs apotheek rotterdam.

uthaugmarineservice.no@gmail.com

Comment

bestill billig pris uten resept nett, http://uthaugmarineservice.no/wp-includes/certificates/apotek/logat.html , Hvor kjøpe Danmark.

timedmg.com@gmail.com

Comment

sweden göteborg, http://natalie.pierotti.org.uk/wp-content/uploads/apotek/danazol.html , uk online.

allanboocock.co.uk@gmail.com

Comment

online hurtig levering danmark, http://www.allanboocock.co.uk/wp-includes/css/apotek/glucotrol-xl.html - tabletter apoteket.

jamiemarsland.co.uk@gmail.com

Comment

Bestellen belgie frankrijk, http://www.jamiemarsland.co.uk/wp-includes/certificates/apotheek/ventoline.html , pillen.

merrilljacobs.co.uk@gmail.com

Comment

bestille online Sverige, http://merrilljacobs.co.uk/css/apotek/provisacor.html , kan man kjøpe uten resept i Spania pris.

soundthief.com@gmail.com

Comment

recept apotek, http://natalie.pierotti.org.uk/wp-content/uploads/apotek/feldegel.html , köpa Sverige malmö.

beverley-fencing.co.uk@gmail.com

Comment

hvor kan jeg købe ægte nettet, http://www.beverley-fencing.co.uk/wp-includes/certificates/apotek/glimepirid.html - købe recept.

hanan.pk@gmail.com

Comment

Generieke kopen, http://www.hanan.pk/wp-includes/css/apotheek/oesclim.html , te koop den haag.

drainclearanceredhill.co.uk@gmail.com

Comment

i Sverige uten resept netto, http://www.drainclearanceredhill.co.uk/wp-includes/certificates/apotek/peroxido-de-benzoilo.html , apotek online.

salathong.co.uk@gmail.com

Comment

apoteket tabletter, http://natalie.pierotti.org.uk/wp-content/uploads/apotek/olanzapine.html , generisk Sverige online.

hanan.pk@gmail.com

Comment

bestilling, http://www.hanan.pk/wp-includes/certificates/apotek/metoprolol.html - hurtig levering recept.

8thburgesshillscouts.co.uk@gmail.com

Comment

Kopen marktplaats duitsland, http://8thburgesshillscouts.co.uk/random/apotheek/ibudolor.html , kopen zonder recept nederland kopen.

ferretcare.co.uk@gmail.com

Comment

Oslo online, http://www.ferretcare.co.uk/wp-includes/pomo/apotek/topiramato.html , kapsler Engelsk.

blog.anotherwebdesign.com@gmail.com

Comment

apoteket Sverige, http://natalie.pierotti.org.uk/wp-content/uploads/apotek/ketotifen.html , köpa i amsterdam.

renewyourlook.co.uk@gmail.com

Comment

Oslo København, http://www.renewyourlook.co.uk/wp-includes/css/apotek/climaval.html , kjøp uten resept Spania.

crawleyplumber.com@gmail.com

Comment

billigare alternativ till tabletter, http://natalie.pierotti.org.uk/wp-content/uploads/apotek/fluvoxamine.html , sälja apoteket.

cleanlivingfylde.co.uk@gmail.com

Comment

pris Oslo, http://www.cleanlivingfylde.co.uk/wp-includes/certificates/apotek/glimepirid.html , tabletter Danmark.

rahitbridalmakeupandhair.co.uk@gmail.com

Comment

köpa i Sverige, http://natalie.pierotti.org.uk/wp-content/uploads/apotek/levocarb.html , köpa receptfritt recept.

iespresso.co.uk@gmail.com

Comment

alternativ Danmark, http://www.iespresso.co.uk/wp-includes/pomo/apotek/oraycea.html , pris apoteket Oslo.

hiresounds.co.uk@gmail.com

Comment

köpa receptfritt, http://natalie.pierotti.org.uk/wp-content/uploads/apotek/aczone.html , köpa pa natet lagligt Sverige.

nordmaling.no@gmail.com

Comment

pris Sverige Norge, http://nordmaling.no/wp-content/uploads/js_composer/apotek/cyproheptadin.html , kjøpe pris.

drainclearancecrawley.co.uk@gmail.com

Comment

alternativ köpa, http://natalie.pierotti.org.uk/wp-content/uploads/apotek/salbutamolsulfat.html , snabb leverans av.

fideas.it@gmail.com

Comment

Dove acquistare http://www.fideas.it/wp-content/uploads/wp-migrate-db/farmacia/proventil.html vendita.

fideas.it@gmail.com

Comment

Quanto costa il in farmacia http://www.fideas.it/wp-content/uploads/wp-migrate-db/farmacia/meclizine.html prezzi migliori.

finefoodsbt.it@gmail.com

Comment

prezzo nelle farmacie Italiane http://www.finefoodsbt.it/citta-delle-stelle/wp-content/uploads/gk_nsp_cache/farmacia/septrin.html Dove comprare online.

finefoodsbt.it@gmail.com

Comment

acquisto generico on line http://www.finefoodsbt.it/citta-delle-stelle/wp-content/uploads/gk_nsp_cache/farmacia/benemid.html equivalente in america.

flagelladedonatis.it@gmail.com

Comment

dove comprare il http://flagelladedonatis.it/wp-content/uploads/2017/01/farmacia/solaraze.html vendita generico in Italia.

flagelladedonatis.it@gmail.com

Comment

generico consegna veloce http://flagelladedonatis.it/wp-content/uploads/2017/01/farmacia/cafergot.html prezzo di in farmacia.

gimafood.it@gmail.com

Comment

comprare online con paypal http://gimafood.it/css/farmacia/baclofeno.html Dove comprare generico.

gimafood.it@gmail.com

Comment

sicuro http://gimafood.it/css/farmacia/alendronate.html in farmacia.

hotelcasale.it@gmail.com

Comment

dove comprare sicuro http://www.hotelcasale.it/wp-includes/certificates/farmacia/yasmin.html Farmacia prezzo.

hotelcasale.it@gmail.com

Comment

Gine francia http://www.hotelcasale.it/wp-includes/certificates/farmacia/mefenamic-acid.html acquista on line.

maestridelgusto.eu@gmail.com

Comment

Italiaans http://maestridelgusto.eu/wp-includes/css/farmacia/flavoxate.html vendita.

iapnor.org@gmail.com

Comment

prezzo in spagna http://www.iapnor.org/wp-includes/css/farmacia/dramamine.html generico prezzo.

maglificiomatisse.it@gmail.com

Comment

generico online pagamento alla consegna http://www.maglificiomatisse.it/wp-includes/css/farmacia/ziagen.html Prezzo pillola.

iapnor.org@gmail.com

Comment

gold Italia http://www.iapnor.org/wp-includes/css/farmacia/aisoskin.html sito Italiano.

ime.srl@gmail.com

Comment

Online sito Italiano http://ime.srl/wp-includes/certificates/farmacia/estrofem.html acquistare online con paypal.

masserialavolpe.it@gmail.com

Comment

Generico di http://masserialavolpe.it/wp-includes/css/farmacia/roxithromycin.html on line sicuro.

ime.srl@gmail.com

Comment

prezzo in svizzera http://ime.srl/wp-includes/certificates/farmacia/abilify.html comprare generico in Italia.

italianproject.eu@gmail.com

Comment

farmaci senza ricetta http://italianproject.eu/wp-includes/pomo/farmacia/bupropione.html poco prezzo.

mcda.cocalosclub.it@gmail.com

Comment

comprare con bonifico bancario http://mcda.cocalosclub.it/wp-includes/css/farmacia/zomig.html acquisto on line senza ricetta.

italianproject.eu@gmail.com

Comment

Generico di http://italianproject.eu/wp-includes/pomo/farmacia/artrotec.html miglior sito acquisto generico.

lianconsul.it@gmail.com

Comment

Come acquistare generico http://lianconsul.it/cms/assets/farmacia/lotensin.html Prescrizione del.

hoppydays.org@gmail.com

Comment

Prezzo di listino http://hoppydays.org/wp-includes/Text/farmacia/dietil.html generico farmacia Italiana.

maccheroncinisbt.it@gmail.com

Comment

prezzo basso http://www.maccheroncinisbt.it/wp-content/uploads/2014/07/farmacia/ezetimibe.html Venta en farmacias.

lianconsul.it@gmail.com

Comment

Come acquistare in farmacia http://lianconsul.it/cms/assets/farmacia/capecitabine.html comprare il in svizzera.

olioangelini.it@gmail.com

Comment

comprare online con ricetta http://www.olioangelini.it/shop/Core/farmacia/tolexine.html farmacia precio.

maccheroncinisbt.it@gmail.com

Comment

dove acquistare generico http://www.maccheroncinisbt.it/wp-content/uploads/2014/07/farmacia/ladinin.html acquisto senza ricetta medica.

palazzobonaccorsi.it@gmail.com

Comment

generico prescrizione http://palazzobonaccorsi.it/wp-includes/pomo/farmacia/propecia.html prezzo farmacia Italia.

villacricri.it@gmail.com

Comment

farmacia Italia http://villacricri.it/wp-content/languages/themes/farmacia/ciloxan.html dove comprare a napoli.

saporidelgusto.it@gmail.com

Comment

prezzo di vendita in farmacia http://saporidelgusto.it/wp-includes/IXR/farmacia/chronadalate.html Senza prescrizione.

studiocatalini.it@gmail.com

Comment

acquisto generico online http://www.studiocatalini.it/wp-content/uploads/2016/01/farmacia/predni-h-tablinen.html acquistare online.

theotherperson.com@gmail.com

Comment

Non prescription online http://theotherperson.com/inc/css/pharmacy/sedron.html non prescription costs.

deserticecastle.com@gmail.com

Comment

Where can I buy online safely http://deserticecastle.com/wp-content/uploads/2014/01/pharmacy/risperidon.html Where can I get in the uk.

blog.hagephoto.com@gmail.com

Comment

buying in costa rica http://blog.hagephoto.com/wp-content/uploads/2017/01/pharmacy/fluticasone.html generic medication.

lma.org.au@gmail.com

Comment

order online canada http://www.lma.org.au/wp-includes/ID3/pharmacy/calsil.html cheapest place to buy online.

snowcitycafe.com@gmail.com

Comment

buying online cheap http://www.snowcitycafe.com/assets/6f9a137e/pharmacy/dorival.html where to purchase in canada.

dekom.com.pl@gmail.com

Comment

buy online best price http://www.dekom.com.pl/wp-includes/ID3/pharmacy/diflex.html can i order online.

ouzel.com@gmail.com

Comment

real pills for sale http://www.ouzel.com/sites/default/files/css/pharmacy/lenalidomide.html where can i buy over the counter in the us.

intranet.monumentalsports.com@gmail.com

Comment

generic pills for sale http://intranet.monumentalsports.com/wp-includes/fonts/pharmacy/abloom.html Buying pills new zealand.

spenardroadhouse.com@gmail.com

Comment

cheap pills for sale http://www.spenardroadhouse.com/assets/28115041/pharmacy/zondra.html how much does cost in america.

monumentalsports.com@gmail.com

Comment

buy pills australia http://www.monumentalsports.com/wp-includes/ID3/pharmacy/trinidazole.html cost of in us.

fiverows.com@gmail.com

Comment

Where can I buy online cheap http://fiverows.com/stewards/pharmacy/clobetasol-propionate.html Where can I get in canada.

verizoncenterpremium.com@gmail.com

Comment

for sale over the counter http://www.verizoncenterpremium.com/css/pharmacy/mavidol.html how to get in australia.

websiteribbon.com@gmail.com

Comment

Uk cheap http://www.websiteribbon.com/images/digg/pharmacy/ponstel.html buy tablets.

driveskills.com@gmail.com

Comment

pills online purchase http://www.driveskills.com/wp-includes/ID3/pharmacy/helpin.html pills australian.

margaretcardillo.com@gmail.com

Comment

canada for sale http://margaretcardillo.com/items/pharmacy/nuclosina.html can you buy online new zealand.

espacecarnot.com@gmail.com

Comment

order from canada http://www.espacecarnot.com/wp-includes/certificates/pharmacy/dicloreum.html best price generic.

ladisfida.com.au@gmail.com

Comment

how much does cost without insurance http://ladisfida.com.au/wp-includes/certificates/pharmacy/fosamax.html Buy online singapore.

f4dbshop.com@gmail.com

Comment

generic quick shipping http://www.f4dbshop.com/catalog/pharmacy/harison.html buy without doctor.

rainbow.yogafest.info@gmail.com

Comment

canada generic online http://rainbow.yogafest.info/wp-includes/css/pharmacy/retens.html canada where to buy.

hotproceed.com@gmail.com

Comment

where can i buy uk http://hotproceed.com/wordpress/wp-includes/certificates/pharmacy/rocin.html Is buying generic online safe.

dev.thedoorstore.ca@gmail.com

Comment

Order generic online overnight http://dev.thedoorstore.ca/wp-content/plugins/pharmacy/inflam.html where to buy australia.

dillons.ca@gmail.com

Comment

buy online cheap uk http://dillons.ca/news/img/pharmacy/aloprim.html tablets australian.

hinterbrook.com@gmail.com

Comment

getting privately uk http://hinterbrook.com/wp-content/languages/plugins/pharmacy/acarbose.html buying in canada.

insitedesign.ca@gmail.com

Comment

purchase online australia http://insitedesign.ca/clients/fgg/assets/pharmacy/acecat.html Generic pricing.

kewvineyards.com@gmail.com

Comment

Buy over the counter in canada http://kewvineyards.com/store/assets/1c72bbdc/pharmacy/cefalexin.html and over the counter drugs.

market.centrogarden.com@gmail.com

Comment

can you buy online in canada http://market.centrogarden.com/wp-content/uploads/2017/01/pharmacy/ibuprom.html available canada.

mkrsmrkt.ca@gmail.com

Comment

generic cost in canada http://mkrsmrkt.ca/wp-content/plugins/nivo-slider/pharmacy/niar.html non prescription generic.

irondames.ca@gmail.com

Comment

tablets uk online http://irondames.ca/wp-content/uploads/2016/12/pharmacy/unat.html overnight shipping usa.

itsawildthing.com@gmail.com

Comment

tablets price in south africa http://itsawildthing.com/wp-content/plugins/hide-title/pharmacy/prisma.html to buy cheap online.

orrhockey.com@gmail.com

Comment

medicine cost http://orrhockey.com/wp-content/uploads/2016/12/pharmacy/akarin.html generic cost.

You must be logged in to comment.

You must be logged in to comment.