web-dev-qa-db-fra.com

Uncaught TypeError: impossible de lire la propriété 'width' de null

Je ne sais pas vraiment ce qui est arrivé parce qu'il travaillait hier soir. Quoi qu'il en soit, j'essaie de faire une application de dessin avec HTML5 et javascript. C’est la première fois que j’examine correctement JS et que je crée quelque chose avec ce logiciel; j’ai donc le code de divers tutoriels et l’aide d’autres amis. A.k.a Je suis un n00b. J'ai utilisé ce qui suit:

  1. github.com/jaseemkp/Paint-app-with-save-facility
  2. codetheory.in/different-tools-for-our-sketching-application/
  3. Livre de recettes Canvas HTML5 - Chapitre 6: Interaction avec le canevas: Association d'écouteurs d'événement aux formes et aux régions - Création d'une application de dessin. (J'ai la fonction de sauvegarde de cela)

Quand je teste mon travail en chrome je reçois l'erreur

"TypeError non capturé: impossible de lire la propriété 'width' of null"

qui fait référence à la ligne 4 de mon fichier de script qui est

var b_width = canvas.width, b_height = canvas.height;

J'essayais de le manipuler pour ajouter une fonctionnalité de texte, mais je ne pouvais tout simplement pas le faire fonctionner. J'ai donc tout défait et maintenant, cela produit cette erreur.

Script complet:

var canvas = document.getElementById("realCanvas");
var tmp_board = document.getElementById("tempCanvas");
var b_width = canvas.width, b_height = canvas.height;
var ctx = canvas.getContext("2d");
var tmp_ctx = tmp_board.getContext("2d");
var x, y; 
var saved = false, hold = false, fill = false, stroke = true, tool = 'rectangle';

var data = {"rectangle": [], "circle": [], "line": []};


function curr_tool(selected){tool = selected;}

function attributes(){
    if (document.getElementById("fill").checked)
        fill = true;
    else
        fill = false;
    if (document.getElementById("outline").checked)
        stroke = true;
    else
        stroke = false;
}


function clears(){
    ctx.clearRect(0, 0, b_width, b_height);
    tmp_ctx.clearRect(0, 0, b_width, b_height);
    data = {"rectangle": [], "circle": [], "line": []};
}

//colour function
function color(scolor){  
    tmp_ctx.strokeStyle = scolor;
    if (document.getElementById("fill").checked)
        tmp_ctx.fillStyle =  scolor; 
}



//line

tmp_board.onmousedown = function(e) {
    attributes();
    hold = true;
    x = e.pageX - this.offsetLeft;
    y = e.pageY -this.offsetTop;
    begin_x = x;
    begin_y = y;
    tmp_ctx.beginPath();
    tmp_ctx.moveTo(begin_x, begin_y);    
}


tmp_board.onmousemove = function(e) {
    if (x == null || y == null) {
        return;
    }
    if(hold){
        x = e.pageX - this.offsetLeft;
        y = e.pageY - this.offsetTop;
        Draw();
    }
}

tmp_board.onmouseup = function(e) {
    ctx.drawImage(tmp_board,0, 0);
    tmp_ctx.clearRect(0, 0, tmp_board.width, tmp_board.height);
    end_x = x;
    end_y = y;
    x = null;
    y = null;
    Draw();
    hold = false;
}



//draw function
function Draw(){

//rectangle
if (tool == 'rectangle'){

    if(!x && !y){
    data.rectangle.Push({"x": begin_x, "y": begin_y, "width": end_x-begin_x, "height": end_y-begin_y, "stroke": stroke, "strk_clr": tmp_ctx.strokeStyle, "fill": fill, "fill_clr": tmp_ctx.fillStyle });
        return;
    }  
    tmp_ctx.clearRect(0, 0, b_width, b_height);
    tmp_ctx.beginPath();

    if(stroke)
        tmp_ctx.strokeRect(begin_x, begin_y, x-begin_x, y-begin_y);
        tmp_ctx.lineWidth = $('#selWidth').val();
    if(fill) 
        tmp_ctx.fillRect(begin_x, begin_y, x-begin_x, y-begin_y);
        tmp_ctx.closePath();

    }

//line

if (tool == 'line'){
    if(!x && !y){
        data.line.Push({"x": begin_x, "y": begin_y, "width": end_x-begin_x, "height": end_y-begin_y, "stroke": stroke, "strk_clr": tmp_ctx.strokeStyle,});
        return;
    }  
    tmp_ctx.beginPath();
    if(stroke)
    tmp_ctx.strokeRect(begin_x, begin_y, x-begin_x, y-begin_y);
    tmp_ctx.clearRect(0, 0, tmp_board.width, tmp_board.height);
    tmp_ctx.beginPath();
    tmp_ctx.moveTo(begin_x, begin_y);
    tmp_ctx.lineTo(x, y);
    tmp_ctx.lineWidth = $('#selWidth').val();
    tmp_ctx.stroke();
    tmp_ctx.closePath();

    }

//circle

else if (tool == 'circle'){   
    if(!x && !y){
        data.circle.Push({"x": begin_x, "y": begin_y, "radius": end_x-begin_x, "stroke": stroke, "strk_clr": tmp_ctx.strokeStyle, "fill": fill, "fill_clr": tmp_ctx.fillStyle });   
        return;
    }   
    tmp_ctx.clearRect(0, 0, b_width, b_height);
    tmp_ctx.beginPath();
    tmp_ctx.arc(begin_x, begin_y, Math.abs(x-begin_x), 0 , 2 * Math.PI, false);

    if(stroke) 
    tmp_ctx.stroke();
    tmp_ctx.lineWidth = $('#selWidth').val();
    if(fill) 
    tmp_ctx.fill();
    tmp_ctx.closePath();

    }

}

//save function
//set up image of canvas
function getCanvasImg(canvas){
    var img = new Image();
    img.src = canvas.toDataURL();
    return img;
}
//get image of canvas
window.onload = function (){
    var events = new Events("tempCanvas");
    var canvas = events.getCanvas();
    var context = events.getContext();
}
//open image of canvas in new window in click of button
document.getElementById("saveButton").addEventListener("click", function(evt){
    //open new window with saved image, right click and save
    window.open(canvas.toDataURL());
}, false);

HTML intégral

<!doctype html>
<html>
<head>
    <title>LogoMakr</title>
    <link rel="stylesheet" href="style.css" type="text/css">
    <script src="jquery.min.js"></script>
    <script src="script.js"> </script>
</style>
</head>
<body>
    <div class="tools">
        <button type="button" id="saveButton" value="Save">Save</button>
        <button type="button" onclick="clears()">CLEAR</button>
        <button type="button" onclick="curr_tool('rectangle')">Rectangle</button>
        <button type="button" onclick="curr_tool('circle')">Circle</button>
        <button type="button" onclick="curr_tool('line')">Line</button>

    </div>

    <table id="table1" >
        <tr>
        <tr>
            <td><button onclick="color('black')" style="background-color: black; height: 20px; width: 20px;"></button></td>
            <td><button onclick="color('white')" style="background-color: white; height: 20px; width: 20px;"></button></td>
            <td><button onclick="color('green')" style="background-color: green; height: 20px; width: 20px;"></button></td>
            <td><button onclick="color('blue')" style="background-color: blue; height: 20px; width: 20px;"></button></td>
            <td><button onclick="color('yellow')" style="background-color: yellow; height: 20px; width: 20px;"></button></td>
            <td><button onclick="color('red')" style="background-color: red; height: 20px; width: 20px;"></button></td>
            <td><button onclick="color('#ff6600')" style="background-color: #ff6600; height: 20px; width: 20px;"></button></td>
            <td><button onclick="color('#663300')" style="background-color: #663300; height: 20px; width: 20px;"></button></td>
            <td><button onclick="color('grey')" style="background-color: grey; height: 20px; width: 20px;"></button></td>
            <td><button onclick="color('#FF6699')" style="background-color: #FF6699; height: 20px; width: 20px;"></button></td>
            <td><button onclick="color('#8b00ff')" style="background-color: #8b00ff; height: 20px; width: 20px;"></button></td>
            <td><input type="checkbox" id="fill"/>Fill</td>
            <td><input type="checkbox" id="outline" checked="checked"/>Outline</td>

            <td>Line Width:</td>
            <td><select id="selWidth">
                    <option value="1">1</option>
                    <option value="3">3</option>
                    <option value="5" selected="selected">5 </option>
                    <option value="7">7</option>
                    <option value="9" >9</option>
                    <option value="11">11</option>
                    </select>
            </td>
        </tr>
    </table>


    <div>
        <canvas id="realCanvas" width="680" height="460" style=" background-color: #ffffff; z-index: 0"  ></canvas>
        <canvas id="tempCanvas" width="680" height="460"  style="z-index: 1"></canvas>
    </div>  



</body>
</html>

CSS

#realCanvas, #tempCanvas {
    position: absolute;
    left:280px;
    top:50px;
    border: 5px solid;
    cursor: crosshair;
}



#table1{
    position: absolute;
    left:400px;
    top:5px; 
}

Lorsque je l'ai téléchargé sur un serveur libre , j'ai cependant des erreurs différentes. Oh je suis tellement confus, j'espère qu'il y a quelqu'un qui peut donner un sens à tout cela: /

Merci d'avance!

9
user2375124

Vous importez votre script avant le navigateur a eu l'occasion d'analyser le corps du document. En tant que tel, l'élément <canvas> n'existe pas au point où vous le recherchez par sa valeur "id".

Comme vous importez quand même jQuery, vous pouvez utiliser un gestionnaire "prêt", mais vous aurez quelques problèmes avec la manière dont vous attachez des gestionnaires d'événements. Vos gestionnaires d'événements basés sur des attributs reposent sur le fait que ces fonctions de gestionnaire sont globales, ce qui ne sera pas le cas si vous les mettez dans un gestionnaire "prêt".

Cependant, il serait beaucoup plus simple de déplacer simplement votre balise <script> (ou les deux) à la toute fin du <body>. De cette façon, le DOM sera analysé et vos appels getElementById() devraient fonctionner. De nombreuses personnes conseillent de toute façon de placer des scripts à la fin du <body>.

À défaut, je suppose que vous pourriez faire quelque chose comme ceci, en modifiant les déclarations en haut de votre script:

$(function() {
  $.extend(window, {
    canvas: document.getElementById("realCanvas"),
    tmp_board: document.getElementById("tempCanvas"),
    b_width: canvas.width, b_height = canvas.height,
    ctx: canvas.getContext("2d"),
    tmp_ctx: tmp_board.getContext("2d"),
    x: undefined,
    y: undefined,
    saved: false,
    hold: false,
    fill: false,
    stroke: true,
    tool: 'rectangle',
    data: {"rectangle": [], "circle": [], "line": []}
  });
});

Il serait préférable soit d’adopter pleinement jQuery et de l’utiliser pour assigner des gestionnaires d’événements, soit de ne pas le importer.

5
Pointy

Vous pouvez également ajouter un attribut différé aux éléments SCRIPT. Il indique au contenu de la balise de script de ne pas s'exécuter avant le chargement de la page.

Donc, vous aurez quelque chose comme ça:

<script src="myscript.js" defer></script>
0
Paulo Borba