2017-08-28 17 views
0

したがって、GSAP TweenLiteとDraggable、KnockoutJSを使用してネストされたサイズ変更可能な観測可能な要素(imageを持つdiv)を作成しています。私の目標は、Java/Android用のレイアウトジェネレータのように、数値入力やドラッグ、サイズ変更などで要素のサイズを変更し、位置を変更することです。私のコードでは現在、ドラッグ・アンド・サイズ変更のアクションによって引き起こされた変更を監視することができますが、Knockoutのバインディングやオブザーバブルの更新には反応しません。ノックアウト更新でネストされたGSAP draggablesが更新されない

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関数が欠けていました。だから私は裸の必需品に観察可能な位置を更新する方法とその逆をテストするためにそれを取り除いた。元のコードに再適用する必要があります。

あなたは多分直面する問題は、あなたがノックアウトで新しいバインディングを実行しようとするときに、二つの方向での更新の観測という、時間の多くを渡って実行される1つである: - あなたは あなたに観察を修正し、あなたのオブジェクトをドラッグ - あなたが変更オブジェクトを変更するオブザーバブル

オブザーバブルを変更するイベントがバインディングの更新をトリガしないよう注意する必要がある状況があります。しかし、私は修正されていないコードを実行することができなかったので、これは推測です。

あなたのコードから小さなサンプルを作成することから、サイクルを考慮しなくても、双方向の更新がうまくいくようです。バインディングの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> 

このフィドルを参照してください。

関連する問題