Fol­low­ing on from part 2 where I wrote a sim­ple page with a can­vas area where you can scrib­ble, I thought I’d add a cou­ple of new features:

  • abil­ity to show the image as PNG image so user can save it
  • change the line cap
  • change the line join
  • change the shadow set­tings (colour, off­set, blur)

Show PNG

The <can­vas> ele­ment defines a rather use­ful toDataURL() method:

The toDataURL() method must, when called with no argu­ments, return a data: URL con­tain­ing a rep­re­sen­ta­tion of the image as a PNG file.”

To get the data in PNG for­mat and get the browser to ren­der it for the user:

// display the image
$("#btnShowPng").click(function () {
    window.location = element.toDataURL("image/png");
});

Couldn’t be sim­pler, right?!

Chang­ing the lineCap property

The 2D con­text defines a lineCap prop­erty which you can set to butt, round or square, it deter­mines the end­ing style of the line (default is butt):

image

So here’s a sim­ple set of radio buttons:

<article>
    Line cap:
    <input type="radio" name="linecap" value="butt" checked="checked"/>Butt
    <input type="radio" name="linecap" value="round"/>Round
    <input type="radio" name="linecap" value="square"/>Square
</article>

image

and an event han­dler for their change events:

// change the linecap when the "linecap" radio button changes
$("input[name=linecap]:radio").change(function (event) {
    context.lineCap = event.target.value;
});

Chang­ing the line­Join property

In addi­tion to the lineCap prop­erty, the 2D con­text also defines a line­Join prop­erty which can be set to miter, round or bevel, it deter­mines how the cor­ners look (default is miter):

image

Here’s the set of radio buttons:

<article>
    Line join:
    <input type="radio" name="linejoin" value="miter" checked="checked"/>Miter
    <input type="radio" name="linejoin" value="round"/>Round
    <input type="radio" name="linejoin" value="bevel"/>Bevel
</article>

image

and its cor­re­spond­ing event handler:

// change the linecap when the "linejoin" radio button changes
$("input[name=linejoin]:radio").change(function (event) {
    context.lineJoin = event.target.value;
});

Chang­ing the Shadow properties

The 2D con­text has a cou­ple of shadow related prop­er­ties:

  • shad­ow­Color
  • shad­owOff­setX
  • shad­owOff­setY
  • shad­ow­Blur

The shad­ow­Color prop­erty can take in a colour using the rgba func­tion (default value is “rgba(0, 0, 0, 0)”, i.e. a fully trans­par­ent black), whilst the other prop­er­ties require a numeric value greater than or equal to 0.

Here’s the HTML marker for con­fig­ur­ing the shadow properties:

<article>
    <section id="shadowColorSection">
        Shadow Colour:
        R
        <input type="text" id="txtColourR" value="0" class="narrow" />
        G
        <input type="text" id="txtColourG" value="0" class="narrow" />
        B
        <input type="text" id="txtColourB" value="0" class="narrow" />
        A
        <input type="text" id="txtColourA" value="0" class="narrow" />
    </section>

    <section>
        Shadow Offset:
        X
        <input type="text" id="txtOffsetX" value="0" class="narrow" />
        Y
        <input type="text" id="txtOffsetY" value="0" class="narrow" />
    </section>

    <section>
        Shadow Blur:
        <input type="text" id="txtBlur" value="0" class="narrow" />
    </section>
</article>

image

and the javascript to go along with them:

$("#shadowColorSection > input:text").change(function (event) {
    setShadowColour(context);
});

$("#txtOffsetX").change(function (event) {
    context.shadowOffsetX = event.target.value;
});

$("#txtOffsetY").change(function (event) {
    context.shadowOffsetY = event.target.value;
});

$("#txtBlur").change(function (event) {
    context.shadowBlur = event.target.value;
});

…

// set the shadow colour from the RBGA text boxes
function setShadowColour(context) {
    var r = $("#txtColourR").val(),
        g = $("#txtColourG").val(),
        b = $("#txtColourB").val(),
        a = $("#txtColourA").val();

    context.shadowColor = "rgba(" + r + "," + g + "," + b + "," + a + ")";
}

Updat­ing the Clear but­ton handler

Now that we can mod­ify a few more of 2D context’s prop­er­ties, it’d be nice if the changes are remem­bered after we clear the can­vas, so the Clear button’s event han­dler needs to be mod­i­fied too to keep track of the cur­rent val­ues and reap­ply­ing them:

// clear the content of the canvas by resizing the element
$("#btnClear").click(function () {
    // remember the current line width
    var currentWidth = context.lineWidth,
        currentLineCap = context.lineCap,
        currentLineJoin = context.lineJoin;
    var currentShadowColour = context.shadowColor,
        currentShadowOffsetX = context.shadowOffsetX,
        currentShadowOffsetY = context.shadowOffsetY,
        currentShadowBlur = context.shadowBlur;

    // set the element's width to erase canvas content
    element.width = element.width;

    context.lineWidth = currentWidth;
    context.lineCap = currentLineCap;
    context.lineJoin = currentLineJoin;

    context.shadowColor = currentShadowColour;
    context.shadowOffsetX = currentShadowOffsetX;
    context.shadowOffsetY = currentShadowOffsetY;
    context.shadowBlur = currentShadowBlur;
});

Demo

The demo can be found here.

Related posts:

Hav­ing fun with HTML5 — Can­vas, part 1

Hav­ing fun with HTML5 — Can­vas, part 2

Hav­ing fun with HTML5 — Can­vas, part 4

Hav­ing fun with HTML5 — Can­vas, part 5

Share

3 Responses to “Having fun with HTML5 — Canvas, part 3”

  1. […] on from part 3 where we basi­cally made a lit­tle app that lets you scrib­ble with HTML5’s canvas […]

  2. […] Hav­ing fun with HTML5 — Can­vas, part 3 […]

  3. […] Hav­ing fun with HTML5 — Can­vas, part 3 […]

Leave a Reply