主干js上的画布仅查看渲染/重新加载一次

时间:2013-12-18 23:05:25

标签: javascript jquery html5 backbone.js canvas

这是我的情况 我正在尝试创建一个仅包含捕获签名的画布的视图。 当我第一次运行代码时,我可以在画布上绘图。 但是当我转到另一个页面并回到签名页面时,画布是可见的,但绘图没有发生。

我扫描了代码,问题似乎发生在

rect = canvas.getBoundingClientRect();

我的rect.left,rect.top,rect.bottom,rect.right都返回0,而只在第一次运行时它们显示15,84,415,384

我将画布宽度和高度设置为400和300

我附上了我的代码

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

});

如果您认为这种方法可能导致任何问题,请告诉我们?

非常感谢你的时间。欣赏它!

1 个答案:

答案 0 :(得分:1)

就像我在评论中提到的那样,你需要确保在每次渲染之前销毁视图。因此,在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;
}

更新

您偶然发现的方法是我在Backbone Views中实现的方式。它有点自以为是,所以我不想让你直接朝着那个方向投掷。很高兴你找到了自己的方式。对于添加的点,您可以创建一个默认包含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.

});