Html 未捕获的类型错误:无法读取 null 的属性“宽度”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16509020/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Uncaught TypeError: Cannot read property 'width' of null
提问by
I actually don't know what's happened because it was working last night. Anyway, I'm trying to make a drawing application with html5 and javascript. This is the first time I've properly looked at JS and created something with it so I've got my code from various tutorials and help from other friends a.k.a I'm a n00b. I used the following:
我实际上不知道发生了什么,因为它昨晚在工作。无论如何,我正在尝试使用 html5 和 javascript 制作绘图应用程序。这是我第一次正确地查看 JS 并用它创建了一些东西,所以我从各种教程中获得了我的代码,并从其他朋友那里得到了帮助,也就是我是 n00b。我使用了以下内容:
- github.com/jaseemkp/paint-app-with-save-facility
- codetheory.in/different-tools-for-our-sketching-application/
- HTML5 Canvas Cookbook - Chapter 6: Interacting with the Canvas: Attaching Event Listeners to Shapes and Regions - Creating a drawing application. (I got the save feature from this)
- github.com/jaseemkp/paint-app-with-save-facility
- codetheory.in/different-tools-for-our-sketching-application/
- HTML5 Canvas Cookbook - 第 6 章:与 Canvas 交互:将事件侦听器附加到形状和区域 - 创建绘图应用程序。(我从中得到了保存功能)
When I test my work in chrome I get the error
当我在 chrome 中测试我的工作时,出现错误
"Uncaught TypeError: Cannot read property 'width' of null"
“未捕获的类型错误:无法读取 null 的属性‘宽度’”
which refers to line 4 of my script file which is
它指的是我的脚本文件的第 4 行
var b_width = canvas.width, b_height = canvas.height;
I was trying to fiddle around with it to add a text feature but just couldn't get it to work so I just undone everything and now it's producing this error.
我试图摆弄它以添加文本功能,但无法使其正常工作,所以我只是撤消了所有操作,现在它正在产生此错误。
Full script:
完整脚本:
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
完整的 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
CSS
#realCanvas, #tempCanvas {
position: absolute;
left:280px;
top:50px;
border: 5px solid;
cursor: crosshair;
}
#table1{
position: absolute;
left:400px;
top:5px;
}
When I've uploaded it to a free server, I've got different errors though. Oh I'm so confused, I hope there's someone out there that can make sense of it all :/
当我将它上传到免费服务器时,我遇到了不同的错误。哦,我很困惑,我希望有人能理解这一切:/
Thanks in advance!
提前致谢!
采纳答案by Pointy
You're importing your script beforethe browser has had a chance to parse the document body. As such, the <canvas>
element doesn't exist at the point you seek it by its "id" value.
您在浏览器有机会解析文档正文之前导入脚本。因此,该<canvas>
元素在您通过其“id”值查找时不存在。
Since you're importing jQuery anyway, you can employ a "ready" handler, but then you'll have some issues with the way you're attaching event handlers. Your attribute-based event handlers rely on those handler functions being global, which they won't be if you put them in a "ready" handler.
由于您无论如何都在导入 jQuery,因此您可以使用“就绪”处理程序,但是您在附加事件处理程序的方式上会遇到一些问题。您的基于属性的事件处理程序依赖于这些处理程序函数是全局的,如果您将它们放在“就绪”处理程序中,它们就不会如此。
Much simpler, however, would be to simply move your <script>
tag (or both of them) to the very end of the <body>
. That way the DOM will be parsed and your getElementById()
calls should work. Lots of people advise that putting scripts at the end of the <body>
should be considered a best practice anyway.
然而,更简单的方法是简单地将您的<script>
标签(或两者)移动到<body>
. 这样 DOM 将被解析并且您的getElementById()
调用应该可以工作。很多人建议将脚本放在末尾<body>
应该被认为是最佳实践。
Failing that, I suppose what you could do is something like this, changing the declarations at the top of your 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": []}
});
});
It'd be better to either adopt jQuery fully and use it to assign event handlers, or else just don't bother importing it.
最好完全采用 jQuery 并使用它来分配事件处理程序,否则就不要费心导入它。
回答by Paulo Borba
You can also add defer attribute on SCRIPT elements. It instructs the contents of the script tag to not execute until the page has loaded.
您还可以在 SCRIPT 元素上添加 defer 属性。它指示脚本标记的内容在页面加载之前不执行。
So you'll have something like this:
所以你会有这样的事情:
<script src="myscript.js" defer></script>