2017-08-28 3 views
0

Also verwende ich GSAP TweenLite und Draggable, sowie KnockoutJS, um verschachtelte resizeable beobachtbare Elemente (A div mit einem image innerhalb) zu erstellen. Mein Ziel ist es, diese Elemente durch Zahleneingabe und Ziehen und Größenanpassung zu verändern und neu zu positionieren, wie es ein Layout-Generator für Java/Android tut. Mein Code ermöglicht es mir derzeit, Änderungen zu überwachen, die durch Ziehen- und Größenänderungsaktionen verursacht werden, reagiert jedoch nicht auf Aktualisierungen der Knockout-Bindungen oder Observables.Verschachtelte GSAP-Draggables aktualisieren nicht auf Knockout-Update

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> 

Wenn jemand einen anderen Vorschlag auf hat, wie mein Ziel zu erreichen, lassen Sie es mich wissen, der einzige Teil Ich mag halten würde, ist KnockoutJS , weil mein Lehrer es empfohlen hat.

Antwort

0

Ihr Code sieht nicht schlecht aus. Ich konnte es nicht unverändert ausführen - ich verpasste zum Beispiel die Funktion bis range. Also habe ich es auf das Wesentliche reduziert, um zu testen, wie das Observable die Position aktualisieren kann und umgekehrt. Sie müssen Ihren ursprünglichen Code erneut anwenden.

Das Problem, das Sie vielleicht einen Blick auf die Sie laufen über eine Menge Zeit, wenn Sie versuchen, eine neue Bindung in Knock-out zu tun, dass Updates Observablen in zwei Richtungen: - Sie ziehen Ihr Objekt, das Ihre beobachtbare ändert - Sie ändern Ihre Observable, die Ihr Objekt ändert

Es gibt Situationen, in denen Sie darauf achten müssen, dass die Ereignisse, die Ihre Observable verändern, nicht die Aktualisierung Ihrer Bindung auslösen. Aber das ist Spekulation, da ich den unmodifizierten Code nicht ausführen konnte.

Immer noch ein kleineres Beispiel aus Ihrem Code, Zwei-Wege-Update scheint gut zu funktionieren, auch ohne Zyklen zu berücksichtigen. Ich fand nur, dass ich innerhalb der update() - Funktion der Bindung überhaupt nicht die Draggable.update() aufrufen würde. Abgesehen davon sollte die Zwei-Wege-Bindung funktionieren.

Sehen Sie diese Geige: 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> 
Verwandte Themen