<rect...>
元素,但是我在为每个九宫格创建点击事件处理程序方面遇到了问题。以下是基本的SVG元素,它们存在于HTML文件中:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"
id="svgTTT" width="150" height="150" viewBox="0 0 300 300" >
<rect width="3" height="300" x="99" fill="#008d46" />
<rect width="3" height="300" x="199" fill="#000000" />
<rect width="300" height="3" y="99" fill="#008d46" />
<rect width="300" height="3" y="199" fill="#d2232c" />
</svg>
这些静态的<rect>
元素绘制出TicTacToe棋盘的交叉线。九个棋盘格子是在一个名为从窗口加载事件调用的javascript函数中创建的(下面是代码)。
以下是嵌入在HTML正文中<script>
元素内的javascript代码:
<script type="text/javascript">
function getEl(s) { return document.getElementById(s); }
var svg; // get the TTT svg
// execute after HTML has rendered
window.onload = function () {
svg = getEl("svgTTT");
tttSetupSquares(svg);
alert("click-squares are setup.");
}
var cells = new Array(3);
// setup the click squares
function tttSetupSquares(brd) {
for (var i = 0; i < 3; i++) {
cells[i] = new Array(3);
for (var j = 0; j < 3; j++) {
var x = 3 + (i * 100);
var y = 3 + (j * 100);
var newId = "svgTTTsqr" + i.toString() + j.toString();
// add in new rect with html
brd.innerHTML += "<rect id='"+newId+"' width='93' height='93' "
+ "fill='#00DD00' x='" + x.toString() + "' y ='" + y.toString() + "'"
+ " />";
//find it using the newId
var rect = document.getElementById(newId);
//make a cell object to contain all of this
var cell = {
col: i,
row: j,
pSvg: svg,
rect: rect,
handleClick: function (event) {
try {
// this line fails because `this` is the target, not the cell
var svgNS = this.pSvg.namespaceURI;
var line = document.createElementNS(svgNS, 'line');
this.pSvg.appendChild(line);
}
catch (err) {
alert("handlClick err: " + err);
}
}
}
//add a click handler for the rect/cell
cell.rect.addEventListener("click", cell.handleClick, false);
//(only seems to work the last time it is executed)
//save the cell object for later use
cells[i][j] = cell;
}
}
}
</script>
问题有两个方面:
只有最后一个
addEventListener
似乎起作用。点击其他所有方格都没有反应。点击最后一个方格(svgTTTsqr22)确实运行了cell.handleClick
,但会遇到问题2(下文)。 Chrome开发者工具(F12)显示除最后一个以外的所有<rect>
元素都没有事件侦听器。当
cell.handleClick
运行时,它在第一行失败(var svgNS = this.pSvg.namespaceURI;
),出现类似"未定义的对象没有名为"namespaceURI"的属性"的错误。 在Devleoper工具中检查发现,它失败是因为this
没有设置为cell
对象,而是被点击的SVG<rect>
元素所代替。
所以我的问题是:
A. 我在这里做错了什么,以及
B. 我应该如何做?
innerHtml
会有什么不利之处。我要试一下这个... - RBarryYoungthis
在事件处理程序中根本没有像我想象的那样工作。您的答案非常详细地解决了this
问题(所以我点了赞),但是忽略了InnerHtml问题,因此我选择了这篇文章作为答案。至于片段不起作用,我没有尝试它,而是修复了自己的代码。 - RBarryYoungthis
上下文仍然是矩形而不是抽象单元格对象。如果你想采用这种方法,所有需要的额外数据都必须存储在矩形本身上(例如,如果它被点击了,或者它在棋盘中的索引等)。这可以很容易地完成。推荐的做法是使用data-*属性。因此,至少要将单元格的索引存储在data-attributes中...cell.rect.setAttribute("data-col",i)
和cell.rect.setAttribute("data-row",j)
,所以在你的点击处理程序中,你可以这样做:this.getAttribute("data-index-i")
。 - Holger Will