HTML5 Canvas kreslení

Vzhledem k tomu, že jsem v několika posledních projektech použil HTML5 Canvas pro kreslení, rozhodl jsem se napsat podrobný návod na tvorbu celkem jednoduché kreslící aplikace pomocí jQuery a právě HTML5 Canvas. Aplikace obsahuje základní nástroje pro kreslení od ruky a tvarů.
Návod bude rozdělen do 3 částí: HTML, CSS a JavaScript. V každém se pokusím vysvětlit podstatné části a zbytek si budete moci dočíst v poznámkách v kódu. Výsledná aplikace bude vypadat takto:

HTML

V HTML části nenajdeme nic zajímavého nebo zvláštního. Aplikace se skládá z uživatelského menu a samotného kreslícího plátna.
Položku menu vlevo máme definovánu jako <div> takto:

<div onclick="setTool('pen')" class="user_icon pen" title="Tužka"></div>

Rozevírací položky jako je barva a tloušťka jsou tvořeny takto:

<div class="user_icon color" title="Barva/Výplň">
  <div class="color_container" onclick="setFillType()"></div>
  <div class="open_target" style="width:203px;">
    <!-- Barvy -->
    <div onclick="setColor('#000000')" class="set_color" style="background-color:#000"></div>
    ...               
  </div>          
</div>

V pravé části poté máme umístěny 2 <canvas> elementy. Uvnitř prvního elementu máme text, který se vypíše v případě, že webový prohlížeč element <canvas> nepodporuje. Druhý HTML5 canvas nám bude sloužit k dočasnému vykreslování objektů, u jejichž kresby je nutné překreslování (čára, čtverec, elipsa, ...). Tento postup jsem použíl, jelikož Canvas nenabízí práci s vrstvami a objekty. Musíme vždy smazat celé plátno a vykreslit všechny objekty znova. Abychom toto urychlili, nově vznikající objekt vykreslíme do dočasného Canvasu samotný a po dokončení jej nakonec dokreslíme do našeho hlavního Canvasu.

<canvas id="draw_canvas" width="712px" height="457px">
  <b>Váš prohlížeč nepodporuje objekt Canvas!</b>
</canvas>
<!-- Dočasné kreslící plátno  -->
<canvas id="temp_draw_canvas" width="712px" height="457px"></canvas>

Celý HTML kód poté máme zde:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link href="./files/styles/main.css" rel="stylesheet" type="text/css" title="styles" />
    <script type="text/javascript" language="javascript" src="./files/scripts/jquery.min.js"></script>    
    <script type="text/javascript" language="javascript" src="./files/scripts/main.js"></script>
    <title>HTML 5 Canvas draw | Tomáš Hubík Grafické studio</title>  
  </head>
  <body>
    <div id="canvas_draw_app">
      <div id="user_panel">
        <!-- Menu našeho editoru -->
        <!-- 
            V onclick máme funkci pro nastavení nástroje 
            class poté obsahuje hlavn třídu "user_icon" a třídu, která přiradí správnou ikonku
            Třída active poté určí, který prvek je aktivní
        -->
        <div onclick="setTool('pen')" class="user_icon pen active" title="Tužka"></div>
        <div onclick="setTool('line')" class="user_icon line" title="Čára"></div>
        <div onclick="setTool('squer')" class="user_icon squer" title="Čtverec"></div>
        <div onclick="setTool('elipse')" class="user_icon elipse" title="Elipsa"></div>
        <div onclick="setTool('triangle')" class="user_icon triangle" title="Trojúhelník"></div>            
        <div onclick="setTool('rubber')" class="user_icon rubber" title="Guma"></div>
        <div class="user_icon color" title="Barva/Výplň">
          <div class="color_container" onclick="setFillType()"></div>
          <div class="open_target" style="width:203px;">
            <!-- Barvy -->
            <div onclick="setColor('#000000')" class="set_color" style="background-color:#000"></div>
            <div onclick="setColor('#7f7f7f')" class="set_color" style="background-color:#7f7f7f"></div>
            <div onclick="setColor('#880015')" class="set_color" style="background-color:#880015"></div>
            <div onclick="setColor('#ed1c24')" class="set_color" style="background-color:#ed1c24"></div>
            <div onclick="setColor('#ff7f27')" class="set_color" style="background-color:#ff7f27"></div>
            <div onclick="setColor('#fff200')" class="set_color" style="background-color:#fff200"></div>
            <div onclick="setColor('#22b14c')" class="set_color" style="background-color:#22b14c"></div>
            <div onclick="setColor('#00a2e8')" class="set_color" style="background-color:#00a2e8"></div>
            <div onclick="setColor('#3f48cc')" class="set_color" style="background-color:#3f48cc"></div>
            <div onclick="setColor('#a349a4')" class="set_color" style="background-color:#a349a4"></div>
            <div onclick="setColor('#ffffff')" class="set_color" style="background-color:#ffffff"></div>
            <div onclick="setColor('#c3c3c3')" class="set_color" style="background-color:#c3c3c3"></div>
            <div onclick="setColor('#b97a57')" class="set_color" style="background-color:#b97a57"></div>
            <div onclick="setColor('#ffaec9')" class="set_color" style="background-color:#ffaec9"></div>
            <div onclick="setColor('#ffc90e')" class="set_color" style="background-color:#ffc90e"></div>
            <div onclick="setColor('#efe4b0')" class="set_color" style="background-color:#efe4b0"></div>
            <div onclick="setColor('#b5e61d')" class="set_color" style="background-color:#b5e61d"></div>
            <div onclick="setColor('#99d9ea')" class="set_color" style="background-color:#99d9ea"></div>
            <div onclick="setColor('#7092be')" class="set_color" style="background-color:#7092be"></div>
            <div onclick="setColor('#c8bfe7')" class="set_color" style="background-color:#c8bfe7"></div>                       
          </div>          
        </div>
        <div class="user_icon size" title="Tloušťka">    
          <div class="size_container show"></div>
          <div class="open_target" style="width:234px;">
            <!-- Tloušťky čar -->
            <div onclick="setSize(2)" class="user_icon">
              <div class="size_container" style="height:2px;"></div>
            </div>         
            <div onclick="setSize(4)" class="user_icon">
              <div class="size_container" style="height:4px;"></div>
            </div>    
            <div onclick="setSize(6)" class="user_icon">
              <div class="size_container" style="height:6px;"></div>
            </div>             
            <div onclick="setSize(8)" class="user_icon">
              <div class="size_container" style="height:8px;"></div>
            </div>   
            <div onclick="setSize(12)" class="user_icon">
              <div class="size_container" style="height:12px;"></div>
            </div>    
            <div onclick="setSize(15)" class="user_icon">
              <div class="size_container" style="height:15px;"></div>
            </div>                                                                
          </div> 
        </div>
        <div onclick="saveScene()" class="user_icon save" title="Uložit"></div>
      </div>     
      <!-- Náše hlavní kreslící plátno -->
      <canvas id="draw_canvas" width="712px" height="457px">
        <b>Váš prohlížeč nepodporuje objekt Canvas!</b>
      </canvas>
      <!-- Dočasné kreslící plátno  -->
      <canvas id="temp_draw_canvas" width="712px" height="457px"></canvas>    
    </div>
  </body>
</html>

CSS

Styl jsou rovněž poměrně jednoduché. Snažil jsem se pomocí CSS udělat co nejvíce práce, na které bych jinak využil obrázky nebo JavaScript.
Jednotlivé ikonky levého menu s třídou .user_icon mají nastaveno pozadí na střed bez kopírování a pomocí dalších tříd, jako je .pen nebo .line zobrazíme v divech patřičné ikonky.

/* Položka uživatelského menu */
#user_panel .user_icon{
  float:left;
  width:43px;       
  height:43px;
  margin:3px 0 0 3px;
  border-bottom:1px #6a777c solid;
  cursor:pointer;
  -moz-border-radius: 3px;
  border-radius: 3px;    
  /* Nastavení pozice pozadí na střed */
  background-repeat: no-repeat;
  background-position: center center;
  /* Opět nastavení relativního poziciování uvnitř kvůli vyjíždějící nabídce */
  position:relative;
  line-height:43px;
  text-align: center;
  font-size:0px;
}


/* Po najetí na položku nabídky, nebo pro všechny položky s třídou .active pridáme pozadí */
#user_panel .user_icon:hover, #user_panel .user_icon.active{
  background-color:#333d40;
}


/* Nastavení ikonek pro jednotlivé ikonkty. Právě k tomuto slouží pridavné třídy u divů */
#user_panel .user_icon.pen{background-image:url('../images/icons/ico_pen.png')}

V případě, že položka obsahuje vyjížděcí nabídku, zobrazí se nabídka po najetí na ikonku pomocí tohoto kódu:

/* Vyjíždějící nabídka*/
#user_panel .user_icon .open_target{
  float:left;
  width:156px;
  /* Poziciovana absolutně, aby vyjížděla vpravo od ikonky*/
  position:absolute;
  left:43px;
  top:0px;  
  height:42px;
  border:1px #525c60 solid;
  border-left:3px #525c60 solid;
  background-color:#687377;
  /* Zaoblené rohy v pravo */
  -moz-border-radius-topright: 3px;
  border-top-right-radius: 3px;
  -moz-border-radius-bottomright: 3px;
  border-bottom-right-radius: 3px; 
  /* Nabídka je defaultně zkryta */
  display:none;   
}

/* Pokud najedeme na položku, která má vyjíždějící nabídku, nastavením display:block se tato nabídka zobrazí */
#user_panel .user_icon:hover .open_target{
  display:block;
}

Kompletní CSS kód poté naleznete zde:

/* Hlavní obal naší aplikace*/
#canvas_draw_app{
  float:left;
  position:relative; /* Nastaví způsob počítání polohy na relativní, aby se nám korektně zobrazovaly absolutně poziciované divy uvnitř */
  width:auto;
  height:461px;
}

/* Hlavní obal uživatelského panelu*/
#user_panel{
  float:left;
  width:47px;
  height:100%;
  background-color:#525c60;
  /* Nastavení zaoblených rohů */
  -moz-border-radius-topleft: 3px;
  border-top-left-radius: 3px;
  -moz-border-radius-bottomleft: 3px;
  border-bottom-left-radius: 3px;     
}

/* Náš hlavní canvas*/
#draw_canvas{
  float:left;
  width:712px;
  height:457px;
  -moz-border-radius-topright: 3px;
  border-top-right-radius: 3px;
  -moz-border-radius-bottomright: 3px;
  border-bottom-right-radius: 3px;  
  background-color:white;
  /*Pozadí canvasu (kostičky) */
  background-image:url('../images/bg_canvas.png');
  border:2px #525c60 solid;    
  cursor: default;  
}      

/* Dočasný canvas, je poziciován absolutně přesně nad náš hlavní canvas */
#temp_draw_canvas{
  position:absolute;
  right:2px;
  top:2px;
  display:none;
}

/* Položka uživatelského menu */
#user_panel .user_icon{
  float:left;
  width:43px;       
  height:43px;
  margin:3px 0 0 3px;
  border-bottom:1px #6a777c solid;
  cursor:pointer;
  -moz-border-radius: 3px;
  border-radius: 3px;    
  /* Nastavení pozice pozadí na střed */
  background-repeat: no-repeat;
  background-position: center center;
  /* Opět nastavení relativního poziciování uvnitř kvůli vyjíždějící nabídce */
  position:relative;
  line-height:43px;
  text-align: center;
  font-size:0px;
}

/* Po najetí na položku nabídky, nebo pro všechny položky s třídou .active pridáme pozadí */
#user_panel .user_icon:hover, #user_panel .user_icon.active{
  background-color:#333d40;
}

/* Nastavení ikonek pro jednotlivé ikonkty. Právě k tomuto slouží pridavné třídy u divů */
#user_panel .user_icon.pen{background-image:url('../images/icons/ico_pen.png')}
#user_panel .user_icon.shapes{background-image:url('../images/icons/ico_shapes.png')}
  #user_panel .user_icon.squer{background-image:url('../images/icons/ico_squer.png')}
  #user_panel .user_icon.elipse{background-image:url('../images/icons/ico_circle.png')}
  #user_panel .user_icon.triangle{background-image:url('../images/icons/ico_triangle.png')}
  #user_panel .user_icon.line{background-image:url('../images/icons/ico_line.png')}
#user_panel .user_icon.rubber{background-image:url('../images/icons/ico_rubber.png')}
#user_panel .user_icon.size{background-image:url('../images/icons/ico_size.png')}
#user_panel .user_icon.save{background-image:url('../images/icons/ico_save.png')}

/* Vyjíždějící nabídka*/
#user_panel .user_icon .open_target{
  float:left;
  width:156px;
  /* Poziciovana absolutně, aby vyjížděla vpravo od ikonky*/
  position:absolute;
  left:43px;
  top:0px;  
  height:42px;
  border:1px #525c60 solid;
  border-left:3px #525c60 solid;
  background-color:#687377;
  /* Zaoblené rohy v pravo */
  -moz-border-radius-topright: 3px;
  border-top-right-radius: 3px;
  -moz-border-radius-bottomright: 3px;
  border-bottom-right-radius: 3px; 
  /* Nabídka je defaultně zkryta */
  display:none;   
}

/* Pokud najedeme na položku, která má vyjíždějící nabídku, nastavením display:block se tato nabídka zobrazí */
#user_panel .user_icon:hover .open_target{
  display:block;
}

/* Nastavení ikonek uvnitř vyjíždějících nabídek*/
#user_panel .user_icon .open_target .user_icon{
  width:35px;
  height:36px;
  border-bottom:none;
  border-right:1px #7c8a8f solid;
  line-height:36px;
}

/* Ikonka, ve které se bude zobrazovat vybraná barva */
.color_container{
  float:left;
  width:25px;
  height:25px;
  margin:9px 0 0 9px;
  /* PNG obrázek přes naši ikonku, ve kterém jsou oba dva stayv ikonek */
  background-image:url('../images/icons/ico_color.png');
}

/* Ikonka s třídou no_fill má nastavenou pozici pozadí na left bottom, čímž využijeme druhou část obrázku*/
.color_container.no_fill{
  background-position: left bottom;
}

/* Ikonka nastavení velikost čáry */
.size_container{
  /* Díky display: inline-block a vertical-align:middle se zobrazí ikonka uprostřed řádku */
  display: inline-block;
  vertical-align:middle;
  height:4px;
  width:23px;
  background-color: white;    
}

/* Malé ikonky pro zobrazení výběru barvy */
#user_panel .user_icon .open_target .set_color{
  float:left;
  width:15px;
  height:15px;
  border:1px white solid;
  margin:2px 0 0 3px;
  /* Zaoblené rohy */
  -moz-border-radius: 2px;
  border-radius: 2px;    
}

/* Po najetí na výběr barvy */
#user_panel .user_icon .open_target .set_color:hover{
  border:1px black solid;
}

JavaScript

Nyní přichází na řadu hlavní část, a tou je část JavaScriptu. Pokud jste jště nikdy nepracovali s HTML5 Canvasem, doporučuji Vám přečíst si můj první tutoriál na HTML5 Canvas.
Můžeme se tedy vrhnout na náši aplikaci. Nejdříve vytvoříme pomocné proměnné, které budeme využívat:

//Globální proměnné
var G_Color = "#00a2e8"; // Počáteční barva
var G_Size = 4; // Počáteční tloušťka ohraničení
var G_Tool = "pen"; // Nástroj
var G_Fill = true; // Zda li vykreslovat výplň 
var G_Canvas; // Hlavní canvas DOM objekt
var G_Context; // Kreslící prostředí našeho hlavního canvasu 
var G_CanvasTemp; // Pomocný canvas
var G_ContextTemp; // A jeho prostředí
var G_DrawingNow = false; // Informace, zda li se zrovna kreslí
var G_StartValues = new Array; // Pomocná proměnná pro uložení počátečních pozic

Další na řadě jsou funkce. Začneme funkcí LoadDefault, která nám slouží pro výběr našich Canvasů, a nastavení počátečních parametrů canvasu. Tuto funkci voláme jakmile je document připraven.

function LoadDefault(){ // Funkce pro načtení prvotních hodnot
  G_Canvas = document.getElementById('draw_canvas'); // Vybere element Canvas, který chceme používat
  G_Context = G_Canvas.getContext('2d'); // Vybereme kreslící prostředí
  G_CanvasTemp = document.getElementById('temp_draw_canvas'); // Canvas, který chceme používat pro dačasné vykreslování
  G_ContextTemp = G_CanvasTemp.getContext('2d'); // Vybereme kreslící prostředí dočasného Canvasu
  setColor(G_Color); // Nastavení počáteční barvy
  setSize(G_Size); // Nastavení počáteční tloušťky      
}

$(document).ready(function(){ // Jakmile je náš dokument připraven, začneme naslouchat událostem.
  LoadDefault(); // Načtení hodnost při startu
...

Následují pomocné funkce pro nastavení barvy, tloušťky, výplně, nástroje a funkce pro výpočet pozice myši:

function setTool(aTool){ // Nastavení nástroje 
  G_Tool = aTool; // Nastaví globální nástroj
  $(".user_icon.active").removeClass("active"); // Odebrání třídy active předchozímu aktivnímu prvku 
  $(event.target).addClass("active"); // Přidání třídy active vybranému prvku    
}

function setColor(aColor){ // Nastavení barvy
  G_Color = aColor; // Nastaví globální barvu
  $(".color_container").css("background-color", aColor); // Nastaví barvu v panelu nástrojů 
  InitCanvases(); // Initializace canvasu
}

function setSize(aSize){ // Nastavení Tloušťky
  G_Size = aSize; // Nastavení glovální tloušťky  
  $(".size_container.show").css("height", aSize); // Nastaví tloušťku v panelu nástrojů
  InitCanvases() // Initializace canvasu
}

// Funkce pro nastavení, zda li se má vykreslovat výplň nebo ne
function setFillType(){
  G_Fill = !G_Fill; // Nastavíme opačnou hodnotu než byla
  if (G_Fill){
    $(".color_container").removeClass("no_fill"); // Nastavení zobrazení ikonky v menu
  }else{
    $(".color_container").addClass("no_fill"); // Nastavení zobrazení ikonky v menu přidáním třídy
  } 
}

// Funkce pro vypočtení relativní pozice myši vůči našemu canvasu
function mouseX(e){ 
  var offset = $(G_Canvas).offset();
  return (parseInt(e.pageX) - parseInt(offset.left))
}
// Funkce pro vypočtení relativní pozice myši
function mouseY(e){ 
  var offset = $(G_Canvas).offset();
  return (parseInt(e.pageY) - parseInt(offset.top))
}

Jelikož při každém překreslení (vymazání) canvasu, se nastaví defaultní hodnoty (barva, tloušťka, ...) vytvořili jsme funkci InitCanvases, ve které po jejím zavolání nastavíme všechny potřebné vlastnosti zpět na ty, které máme nastaveny v panelu. Funkce vypadá takto:

function InitCanvases(){ // Funkce pro nastavení vlastností obou našich Canvasů
  // Nastavení spoju a zakončení čar
  G_Context.lineCap = "round";
  G_Context.lineJoin = "round";   
  G_ContextTemp.lineCap = "round";
  G_ContextTemp.lineJoin = "round";  
  
  // Nastavení barvy
  G_Context.fillStyle = G_Color;
  G_ContextTemp.fillStyle = G_Color;
  G_Context.strokeStyle = G_Color;
  G_ContextTemp.strokeStyle = G_Color;  
  
  // Nastavení tloušťky čar  
  G_Context.lineWidth = G_Size;
  G_ContextTemp.lineWidth = G_Size;  
}

Nyní můžeme přejít na samotné kreslení. Základem kreslení je zachytit 3 události, mouseDown, mouseMove a mouseUp.
Začneme událostí mouseDown. V této události nejdříve nastaveníme proměnnou G_DrawingNow na true, čímž řekneme, že práve teď se kreslí. Poté záleží, zda-li chceme kreslit čádu od ruky, nebo nějaký z našich tvarů, pro který je zapotřebí dočasný canvas. Funkce mouseDown vypadá takto:

$(G_Canvas).mousedown(function(e){ // Událost kliknutí na plátno
  if (G_Tool == "pen"){
    G_Context.moveTo(mouseX(e), mouseY(e)); // Nastavení pozice kreslení na pozici kliku  
  }else{
    $("#temp_draw_canvas").css("display", "block"); // Zobrazí dočasný Canvas
    G_StartValues = [mouseX(e), mouseY(e)]; // Uloží startovní souřadnice
  }
  G_DrawingNow = true; // Kreslení je zapnuto
});

Další na řadě je událost mouseMove, která zachycuje pohyb myši po obrazovce. V této části voláme samotné vykreslovací funkce:

$(document).mousemove(function(e){ // Událost pohybu myši na dokumentu
  if (G_DrawingNow){ // Pokud kreslíme  
    if (G_Tool == "pen"){ // Pero
      G_Context.lineTo(mouseX(e), mouseY(e)); // Kreslíme čáru od posledního bodu ke curzoru myši 
      G_Context.stroke(); // Vykreslíme čáru      
    }else if (G_Tool == "rubber"){ // Guma
      // Gumujeme čtverec o 5x velikosti tloušťky čáry
      G_Context.clearRect(mouseX(e)-(3*G_Size), mouseY(e)-(3*G_Size), (5*G_Size), (5*G_Size)); 
    }else{ // Pokud kreslíme nějaký tvar, u kterého je nutno překreslovat 
      G_CanvasTemp.width = G_CanvasTemp.width; // Smažeme dočasný canvas    
      InitCanvases(); // Nastavíme správné vlastnosti
      var endPoint = [mouseX(e), mouseY(e)]; // Uložíme si pozici cursoru
      if (G_Tool == "line"){ // Kreslíme čáru   
        drawLine(G_StartValues, endPoint, G_ContextTemp);    // Kreslíme čáru
      }else if (G_Tool == "squer"){
        drawSquer(G_StartValues, endPoint, G_ContextTemp);  // Kreslíme Čtverec
      }else if (G_Tool == "elipse"){
        drawElipse(G_StartValues, endPoint, G_ContextTemp);  // Kreslíme elipsu / kruh
      }else if (G_Tool == "triangle"){
        drawTriangle(G_StartValues, endPoint, G_ContextTemp);  // Kreslíme trojúhelník
      }
    }
  }    
});

Poslední událostí je mouseUp, která nám ukončí kreslení. Vypadá takto:

$(window).mouseup(function(e){ // Událost puštění myši      
  if (G_DrawingNow){     
    G_Context.beginPath(); // Začínáme novou cestu        
    $("#temp_draw_canvas").css("display", "none"); // Skryje dočasný Canvas
    endPoint = [mouseX(e), mouseY(e)];
    if (G_Tool == "line"){  
      drawLine(G_StartValues, endPoint, G_Context);      
    }else if (G_Tool == "squer"){
      drawSquer(G_StartValues, endPoint, G_Context);
    }else if (G_Tool == "elipse"){
      drawElipse(G_StartValues, endPoint, G_Context);
    }else if (G_Tool == "triangle"){
      drawTriangle(G_StartValues, endPoint, G_Context);
    }
    G_CanvasTemp.width = G_CanvasTemp.width; // Vymaže dočasný Canvas      
  }
  G_DrawingNow = false; // Kreslení vypnuto
});

Vykreslovací funkce pro jednotlivé objekty. Kvůli redundanci kódu a přehlednost jsem se rozhodl vytvořit pro tvary vlastní funkce vykreslení, které voláme při mouseMove a mouseUp. Těchto funkcí si můžeme naprogramovat kolik chceme a tím vytvořit další tvary.

// Funkce pro nakreslení čáry. Jako parametry máme počáteční bod a koncový bod + cíl vykreslení (Canvas Content)
function drawLine(aStartPoint, aEndPoint, aTarget){
  aTarget.moveTo(aStartPoint[0], aStartPoint[1]); // Posun bodu odkud kreslit
  aTarget.lineTo(aEndPoint[0], aEndPoint[1]); // Čára do koncového bodu 
  aTarget.stroke();    
}

function drawSquer(aStartPoint, aEndPoint, aTarget){ // Funkce pro nakreslení čtverce.
  aTarget.moveTo(aStartPoint[0], aStartPoint[1]);
  aTarget.beginPath();            
  // Funkce pro vykreslení čtverce. tato funkce by se dala nahradit také 4mi funkcemi lineTo
  aTarget.rect(aStartPoint[0], aStartPoint[1], aEndPoint[0]-aStartPoint[0], aEndPoint[1]-aStartPoint[1]);
  if (G_Fill){        
    // V případě, že chceme výplň
    aTarget.fill(); // Funkce pro vyplnění tvaru
  }
  aTarget.closePath(); // Uzavření cesty
  aTarget.stroke(); // Vytažení hran objektu       
}

function drawTriangle(aStartPoint, aEndPoint, aTarget){ // Funkce pro nakreslení trojúhelníku.  
  w = aEndPoint[0]-aStartPoint[0]; // Šířka
  h = aEndPoint[1]-aStartPoint[1]; // Výška 
  cx = aStartPoint[0]+w/2;  // Středový bod X
  cy = aStartPoint[1]+h/2;  // Středový bod Y                   
  aTarget.beginPath();                                                
  aTarget.moveTo(aStartPoint[0], aEndPoint[1]); 
  // Naše tři hrany trojúhelníku           
  aTarget.lineTo(cx, aStartPoint[1]);
  aTarget.lineTo(aEndPoint[0], aEndPoint[1]);
  aTarget.lineTo(aStartPoint[0], aEndPoint[1]);        
  if (G_Fill){        
    // Výplň
    aTarget.fill();
  }
  aTarget.closePath();
  aTarget.stroke();         
}

function drawElipse(aStartPoint, aEndPoint, aTarget){ // Funkce pro nakreslení kruhu.
  // Abychom mohli vykreslit elipsu nemůžeme použít funkc ARC, ale použijeme 4 bezierovy křivky.
  w = aEndPoint[0] - aStartPoint[0]; // Šířka
  h = aEndPoint[1] - aStartPoint[1]; // Výška
  var k = 0.5522848; // konstanta kappa
  ox = (w/2) * k, // Horizontální kontrólní bod pro křivku
  oy = (h/2) * k, // Vertikální kontrólní bod pro křivku
  xe = aEndPoint[0],           // Konec X
  ye = aEndPoint[1],           // Konec Y
  xm = aStartPoint[0]+w / 2,       // Střed X
  ym = aStartPoint[1]+h / 2;       // Střed Y
  aTarget.beginPath();
  aTarget.moveTo(aStartPoint[0], ym);
  // Naše čtyři bezierovy křivky
  aTarget.bezierCurveTo(aStartPoint[0], ym - oy, xm - ox, aStartPoint[1], xm, aStartPoint[1]); // Vykreslí první bezierovou křivku
  aTarget.bezierCurveTo(xm + ox, aStartPoint[1], xe, ym - oy, xe, ym);  // Vykreslí druhou bezierovou křivku
  aTarget.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);  // Vykreslí třetí bezierovou křivku
  aTarget.bezierCurveTo(xm - ox, ye, aStartPoint[0], ym + oy, aStartPoint[0], ym);  // Vykreslí čtvrtou bezierovou křivku
  if (G_Fill){        
    // Výplň 
    aTarget.fill();
  }
  aTarget.closePath();
  aTarget.stroke();   
}

Závěr

A máme hotovo! Doufám, že jsem zmínil všechny podstatné části a na nic nezapomněl. I když se jedná o Návod, script je možné použít, krom nauky práce s Canvasem, pouze pro nekomerční projekty. V případě, že budete chtít script využít v komerčním projektu, neváhejte mne kontaktovat.

Pokud se Vám článek líbí, podpořte další tím, že dáte "Like" na Facebook nebo +1 na Google+ nebo nasdílíte tento článek dál. Jen na základně vaší zpětné vazby budu moci zjistit, zda-li mám psát dál, nebo ne.

Kontakt

Tomáš Hubík
Telefon+420 774 510 211
E-mailTomas.Hubik1@gmail.com
BydlištěOkres Opava
SkypeTomasHubik
74864131
SpolupracujiÚčetní Opava
Napište nám
Odeslat dotaz
Odeslat dotaz