2017-08-28 39 views
0

所以我使用GSAP TweenLite的和可拖动,以及KnockoutJS创建嵌套的可调整大小的可观察到的元素(A divimage内侧)。我的目标是通过数字输入和拖动以及调整大小来调整和重新定位这些元素,就像Java/Android的布局生成器一样。我的代码目前允许我监视由拖动和调整大小操作引起的更改,但它不会对Knockout绑定或可观察对象的更新作出反应。嵌套GSAP拖拽元素不更新上敲除更新

的Javascript:

function object(id) { 
      var self = this; 
      self.id = ko.observable(id); 
      self.parent = ko.observable(); 
      self.childNodes = ko.observableArray([]); 
      self.x = ko.observable(100); 
      self.y = ko.observable(50); 
      self.w = ko.observable(100); 
      self.h = ko.observable(100); 
      } 


      function EditorViewModel() { 
      this.self = this; 
      self.Objects = ko.observableArray([new object("1")]); 
      self.Objects().push(new object("2")); 
      self.Objects()[0].childNodes.push(new object("1.1")); 
      self.Objects()[0].childNodes()[0].childNodes.push(new object("1.1.1")); 
      self.chosenObject = ko.observable(); 


ko.bindingHandlers.dragResize = { 
      init: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 
      var val = ko.unwrap(valueAccessor()); 
      var drag = element; 
      if (element.parentNode.parentNode == $(document.body)) { 
      parent = element.parentNode; 
      } else { 
      var parent = element.parentNode.parentNode; 
      } 
      var handle = $("<div class='resize-handle'></div>").appendTo(drag); 
      TweenLite.set(handle, {bottom: 0, right: 0}); 
      Draggable.create(drag, 
      { 
      type: 'top left', bounds: parent, 
        onDragStart: function() 
        { 
        if (typeof Draggable.get(parent) !== 'undefined') { 
        untilRange(element, false); //sets all parent Dragagbles to disabled to prevent quirks when dragging child 
        } 
        }, 
        onDragEnd: function() 
        { 
        if (typeof Draggable.get(parent) !== 'undefined') { 
        untilRange(element, true); //same as above, but re-enables them after drag 
        } 
        }, 
        onDrag:function (e){ 
        val.x(this.x); 
        val.y(this.y); 
        } 
      }); 
      Draggable.create(handle, { 
      type: "top,left", 
        onPress: function (e) { 
        e.stopPropagation(); // cancel drag 
        }, 
        onDrag: function (e) { 
        val.w(this.x); 
        val.h(this.y); 
        TweenLite.set(drag,{width:val.w(),height:val.h()}); 
        }, 
      }); 
      }, 
        update: function (element, valueAccessor, allBindings, viewModel, bindingContext) { 
        var val = ko.unwrap(valueAccessor()); 
        var drag = Draggable.get(element); 
        element.x=val.x(); 
        drag.update(); 
        } 
      } 

HTML:

<div id="range" data-bind="template:{name: 'elementTemplate',foreach:Objects()}"> 

     </div> 


     <!--Templates--> 
     <script type="text/html" id="elementTemplate"> 
      <!--<pre style="position:relative;width: 100px" data-bind="text: ko.toJSON($data, null, 2)"></pre>--> 
      <div class="draggable" data-bind="attr:{id:id}, dragResize:{x:x,y:y,h:h,w:w}"> 

       <div data-bind="template:{name: 'elementTemplate',foreach:childNodes()}"> 
       </div> 
       <img src="res/Download.jpg" class="mapClass" alt="If you see this we haven't done well"/> 
      </div> 
     </script> 

如果有人对如何达到我的目标,不同的建议,请让我知道,我想保持唯一的部分是KnockoutJS ,因为我的老师推荐它。

回答

0

你的代码看起来不错。我无法运行它未经修改 - 我错过了例如untilRange函数。所以我把它分解到最基本的东西来测试如何让可观察的更新位置,反之亦然。你将不得不重新申请你的原始代码。

你可能面临的问题是一个你跨越了很多的时间运行,当你尝试做基因敲除一个新的绑定,该更新可观察两个方向: - 您拖动对象,它会修改你的观察到的 - 你修改你的可观察点,它修改你的对象

有些情况下你需要注意,修改你的observable的事件不会触发绑定的更新。但这是猜测,因为我无法运行未修改的代码。

仍然从您的代码中创建一个较小的示例,双向更新似乎工作正常,即使没有考虑周期。我发现绑定的update()函数内部根本不会调用Draggable.update()。除此之外,双向绑定应该起作用。

看到这个小提琴: https://jsfiddle.net/domoran/1dk1hc4v/5/

的Javascript:

function object(id) { 
    var self = this; 
    self.id = ko.observable(id); 
    self.x = ko.observable(0); 
    self.y = ko.observable(0); 
} 

ko.bindingHandlers.dragResize = { 
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
    var val = ko.unwrap(valueAccessor()); 
    var lastSelected = val.last; 

    Draggable.create(element, { 
     type: "x,y", 
     onDrag: function(e) { 
     lastSelected(ko.dataFor(element)); 
     val.x(this.x); 
     val.y(this.y); 
     } 
    }); 
    }, 

    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
    var updateCoords = function() { 
     // since this is invoked inside a computed, it will be invoked, 
     // whenever the observables x and y change 
       TweenLite.set(element,{x:val.x(),y:val.y()}); 
    }; 

    var val = ko.unwrap(valueAccessor()); 
    // make the updateCoors function call whenever one of its observables 
    // changes 
    updateCoords(); 
    } 
}; 

function EditorViewModel() { 
    var self = this; 

    self.Objects = ko.observableArray([new object("1"), new object("2")]); 
    self.lastSelected = ko.observable(); 
} 

ko.applyBindings(new EditorViewModel()); 

HTML:

<body> 
    <div id="range" data-bind="template:{name: 'elementTemplate',foreach:Objects }"> 
    </div> 

    <!--Templates--> 
    <script type="text/html" id="elementTemplate"> 
    <div data-bind="attr:{id:id}, dragResize:{x:x,y:y,last:$root.lastSelected}"> 
     <img width=80 src="https://upload.wikimedia.org/wikipedia/commons/4/4c/World_borders_lamb_azi.png" class="mapClass" alt="If you see this we haven't done well" /><span data-bind="text: x() + '/' + y()"></span> 
    </div> 
    </script> 

    <div data-bind="with:lastSelected"> 
    <label>x</label><input type="text" data-bind="value: x" /> 
    <label>y</label><input type="text" data-bind="value: y" /> 
    </div> 
</body>