2013-05-12 72 views
8

Tôi thực sự không biết điều gì đã xảy ra vì nó hoạt động tối qua. Dù sao, tôi đang cố gắng để làm cho một ứng dụng vẽ với html5 và javascript. Đây là lần đầu tiên tôi nhìn JS một cách chính xác và tạo ra một thứ gì đó với nó vì vậy tôi đã có mã của tôi từ các hướng dẫn khác nhau và sự giúp đỡ từ những người bạn khác a.k.a Tôi là một n00b. Tôi sử dụng như sau:Loại lỗi không được phép: Không thể đọc thuộc tính 'chiều rộng' của null

  1. github.com/jaseemkp/paint-app-with-save-facility
  2. codetheory.in/different-tools-for-our-sketching-application/
  3. HTML5 Canvas Sách dạy nấu ăn - Chương 6: Tương tác với Canvas: Đính kèm Trình nghe sự kiện vào các hình dạng và khu vực - Tạo một bản vẽ ứng dụng. (Tôi có tính năng tiết kiệm từ này)

Khi tôi kiểm tra công việc của tôi trong chrome tôi nhận được lỗi

"Uncaught TypeError: Cannot read property 'width' of null"

đó đề cập đến dòng 4 của tập tin kịch bản của tôi mà là

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

Tôi đã cố gắng để fiddle xung quanh với nó để thêm một tính năng văn bản nhưng chỉ không thể làm cho nó hoạt động vì vậy tôi chỉ hoàn tác tất cả mọi thứ và bây giờ nó sản xuất lỗi này.

Full kịch bản:

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); 

Full HTML

<!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; 
} 

Khi tôi đã tải lên nó vào một free server, tôi đã có lỗi khác nhau mặc dù. Ôi, tôi rất bối rối, tôi hy vọng có ai đó ngoài kia có thể hiểu được tất cả:/

Xin cảm ơn trước!

Trả lời

5

Bạn đang nhập tập lệnh trước trình duyệt đã có cơ hội phân tích cú pháp nội dung tài liệu. Như vậy, phần tử <canvas> không tồn tại tại thời điểm bạn tìm kiếm nó theo giá trị "id" của nó.

Vì bạn đang nhập jQuery dù sao, bạn có thể sử dụng trình xử lý "sẵn sàng", nhưng sau đó bạn sẽ gặp một số vấn đề với cách bạn đính kèm trình xử lý sự kiện. Trình xử lý sự kiện dựa trên thuộc tính của bạn dựa vào các hàm xử lý đó là toàn cục, chúng sẽ không được nếu bạn đặt chúng trong trình xử lý "sẵn sàng".

Đơn giản hơn nhiều, tuy nhiên, chỉ đơn giản là di chuyển thẻ <script> của bạn (hoặc cả hai thẻ) vào cuối của <body>. Bằng cách đó, DOM sẽ được phân tích cú pháp và các cuộc gọi getElementById() của bạn sẽ hoạt động. Rất nhiều người khuyên rằng việc đặt tập lệnh ở cuối số <body> sẽ được coi là phương pháp hay nhất.

Không đó, tôi cho rằng những gì bạn có thể làm là một cái gì đó như thế này, thay đổi khai báo ở trên cùng của kịch bản của bạn:

$(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": []} 
    }); 
}); 

Nó muốn được tốt hơn hoặc là áp dụng jQuery đầy đủ và sử dụng nó để gán xử lý sự kiện, hoặc người nào khác chỉ không bận tâm nhập khẩu nó.

+0

Cảm ơn bạn rất nhiều, đó là những gì tôi đã thay đổi, tôi đã chuyển các tập lệnh vào đầu. Cám ơn bạn một lần nữa! (Tôi đã dậy muộn vì vậy không thể nhớ hết những gì tôi đã làm haha) – swaistle

+0

OK cool - và bình luận của bạn chỉ khiến tôi nhận ra một giải pháp đơn giản hơn nhiều :-) – Pointy

+0

Ahhh yeah Tôi đã chơi với jquery để phát triển như một hình thức loại điều mà người dùng có thể nhập văn bản trong biểu mẫu và nó hiển thị trên canvas bất cứ nơi nào họ chọn. do đó, bước đầu tiên chỉ là tạo biểu mẫu để nó có thể hiển thị và ẩn từ một lần nhấp vào nút. :) – swaistle

Các vấn đề liên quan