Javascript 主干上的画布js视图仅渲染/重新加载一次
这是我的情况 我试图创建一个视图,其中只包含一个画布来捕获签名。 当我第一次运行代码时,我能够在画布上绘制。 但是,当我转到另一页并返回签名页时,画布是可见的,但绘图没有发生 我扫描了代码,问题似乎发生在线路上 rect=canvas.getBoundingClientRect() 我的rect.left、rect.top、rect.bottom、rect.right都返回0,而只有在第一次运行时才显示15、84、415、384 我已经将画布的宽度和高度设置为400和300 我已附上我的密码Javascript 主干上的画布js视图仅渲染/重新加载一次,javascript,jquery,html,backbone.js,canvas,Javascript,Jquery,Html,Backbone.js,Canvas,这是我的情况 我试图创建一个视图,其中只包含一个画布来捕获签名。 当我第一次运行代码时,我能够在画布上绘制。 但是,当我转到另一页并返回签名页时,画布是可见的,但绘图没有发生 我扫描了代码,问题似乎发生在线路上 rect=canvas.getBoundingClientRect() 我的rect.left、rect.top、rect.bottom、rect.right都返回0,而只有在第一次运行时才显示15、84、415、384 我已经将画布的宽度和高度设置为400和300 我已附上我的密码 v
var canvas;
var context;
var radius = 2;
var dragging = false;
var targetTouch;
var rect;
var SignatureView = Backbone.View.extend({
events: {
"touchstart #SignCanvas": "engage",
"touchmove #SignCanvas": "putPoint",
"touchend #SignCanvas": "disengage"
},
//Compile and assign the template
template: getTemplate("signature"),
initialize: function () {
this.render();
},
//Render the contents
render: function() {
this.$el.html(this.template());
this.delegateEvents();
var that = this;
setTimeout(function() {
that.prepSignPad()
}, 0);
return this;
},
prepSignPad: function() {
canvas = document.getElementById("SignCanvas");
context = canvas.getContext("2d");
context.lineWidth = radius * 2;
},
updateStatus: function() {
this.$("#divStatusbar").html("Canvas Loaded");
},
putPoint: function(e) {
e.preventDefault();
targetTouch = e.originalEvent.targetTouches[0];
rect = canvas.getBoundingClientRect();
var x = targetTouch.pageX - rect.left;
var y = targetTouch.pageY - rect.top;
if(dragging) {
context.lineTo(x, y);
context.stroke();
context.fillStyle = "black";
context.beginPath();
context.arc(x, y, radius, 0, Math.PI * 2);
context.fill();
context.beginPath();
context.moveTo(x, y);
}
},
engage: function(e) {
dragging = true;
putPoint(e);
},
disengage: function() {
dragging = false;
context.beginPath();
}
});
在下面提到的DOrderView中调用此SignatureView
var DOrderView = Backbone.View.extend({
//Compile and assign the template
template: getTemplate("DOrder"),
initialize: function () {
this.$el.attr('data-role', 'page');
this.render();
this.updateStatus();
},
//Render the contents
render: function() {
this.$el.html(this.template());
//if(!this.view) {
this.view = new SignatureView();
//}
this.$("#divSignature").append(this.view.el);
this.view.delegateEvents();
return this;
},
updateStatus: function() {
this.$("#divStatusbar").html("Delivered Order (DO)");
}
});
多谢各位。我试着按照你建议的方式编辑代码。我相信它应该会起作用,但由于某种原因它不起作用。这是我听了你的建议后第一次尝试的
var DOrderView = Backbone.View.extend({
//Compile and assign the template
template: getTemplate("DOrder"),
initialize: function () {
this.$el.attr('data-role', 'page');
this.render();
this.updateStatus();
},
//Render the contents
render: function() {
this.$el.html(this.template());
if(this.SignatureView) {
this.SignatureView.remove();
}
this.SignatureView = new SignatureView();
this.$("#divSignature").append(this.SignatureView.el);
this.SignatureView.delegateEvents();
},
updateStatus: function() {
this.$("#divStatusbar").html("Delivered Order (DO)");
}
这可能是因为父视图DOrderView可能没有被销毁吗
但后来我对代码进行了如下调整,现在它可以工作了
var DOrderView = Backbone.View.extend({
events: {
"click .back, #btnHome": "close"
},
//Compile and assign the template
template: getTemplate("DOrder"),
initialize: function () {
this.$el.attr('data-role', 'page');
this.render();
this.updateStatus();
},
//Render the contents
render: function() {
this.$el.html(this.template());
this.SignatureView = new SignatureView();
this.$("#divSignature").append(this.SignatureView.el);
},
updateStatus: function() {
this.$("#divStatusbar").html("Delivered Order (DO)");
},
close: function() {
this.SignatureView.unbind();
this.SignatureView.remove();
}
});
请让我知道,如果你认为这种方法可能会导致任何问题的线
非常感谢您抽出时间。谢谢你 正如我在评论中提到的,您需要确保在每次渲染之前销毁视图。因此,在您的
DOrderView
的渲染方法中,我们应该首先销毁旧视图,然后再创建新视图。你差一点就到了,只是漏掉了一行:
//Render the contents
render: function() {
this.$el.html(this.template());
// The following code block will check if there is already a SignatureView
// and if there is one, will call the View's `remove()` method. The `remove()`
// method call's BackboneView's native `stopListening()` method as well as
// jQuery's `remove()` method on the view element.
if(this.view) {
this.view.remove();
}
// Now we will create a fresh view on every render
this.view = new SignatureView();
this.$("#divSignature").append(this.view.el);
this.view.delegateEvents();
return this;
}
更新:
您偶然发现的方法正是我在主干视图中实现的方法。这有点固执己见,所以我不想马上就把你推向那个方向。很高兴你找到了去那里的路。对于添加的点,可以创建默认情况下包含close方法的基础视图,这样就不必将该方法添加到每个新视图中:
var myBaseView = Backbone.View.extend({
close: function () {
this.unbind();
this.remove();
}
});
然后你可以像这样使用它:
var myNewExtendedView = myBaseView.extend({
// Define custom view logic that extends off of base here. This view will come
// preloaded with the close method. Sweeeeeet.
});
上面的代码看起来不错。当你“离开页面并返回”时,你是否正在破坏视图并创建另一个视图?我相信相关代码在视图实现中,而不是视图本身。jsibales,感谢您回答我的问题。你能告诉我如何破坏和重新创建视图吗?我是否应该在视图中这样做(我第一次在视图中实例化它)?我很乐意向您展示一些示例代码。您当前是如何创建视图的?我将代码粘贴为应答选项卡,因为我不知道如何将代码粘贴到注释中。希望您能在下面看到。您应该在原始问题中添加代码作为编辑。在您的问题标签列表下有一个指向“编辑”的链接。把你的代码贴在那里。太棒了!这是一个极好的建议。现在(这是我第一次)让我看看我应该如何接受并投票支持这个答案。再次感谢!不允许我投票,因为我的声誉还没有达到15分:-(。但是你的答案肯定被接受,并且证明了我所面临的情况是正确的,不用担心…再问几个问题,也许你会回答一两个问题,你就可以开始与社区其他人一起投票了