Search code examples
javascriptjsonknockout.jskineticjs

How to use Knockout-Kinetic with knockout observables


I recently found this knockoutjs plugin for KineticJS

The wiki page includes an example, but I don't really understand what it does exactly:

<!DOCTYPE html>
<html>
  <head>
    <title>A Knockout/Kinetic example</title>
    <script type="text/javascript" src="kinetic-v3.9.8.min.js"></script>
    <script type="text/javascript" src="knockout-2.1.0.js"></script>
    <script type="text/javascript" src="../knockout-kinetic.js"></script>
  </head>
  <body>
    <!--
   This example is from the 'Rect' tutorial:
   http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-rect-tutorial/
   -->
    <div id="container">
      <!-- Look, ma! No JavaScript! -->
      <!-- ko Kinetic.Stage: { width: 578, height: 200 } -->
      <!--     ko Kinetic.Layer: { } -->
      <!--         ko Kinetic.Rect: { x: 239, y: 75, width: 100, height: 50, fill: "#00D2FF", stroke: "black", strokeWidth: 4 } -->
      <!--         /ko -->
      <!--     /ko -->
      <!-- /ko -->
    </div>
    <script type="text/javascript">
        // Ok, a *little* JavaScript...
        ko.applyBindings();
    </script>
</html>

Aside from not getting the "no javascript" joke (at least I think that's what it is?) I don't see how this plugin might help me to bind to a list of knockout observables that defines a number or rectangles.

For example, let's say I get the following json as a result of an ajax call:

{"rectangles":[{"id":1,"x":0,"y":0,"width":200,"height":30},{"id":2,"x":0,"y":40,"width":200,"height":30}]}

I could then use this data to populate an observable array in my ViewModel but how do I use the plugin to bind Kinetic to it so that the rectangles are automatically displayed and updated?


Solution

  • This can be built up in pieces. Given a JavaScript object with your rectangle data, you create your view model:

    var viewModel = ko.observable(data);
    ko.applyBindings(viewModel);
    

    And render it using an HTML file that implements your view:

    <div id="container"> <!-- The container is optional but good practice -->
      <!-- ko Kinetic.Stage: { width: 800, height: 600 } -->
      <!--     ko Kinetic.Layer: { } -->
      <!--         ko foreach: rectangles -->
      <!--             ko Kinetic.Rect: $data -->
      <!--             /ko --> 
      <!--         /ko -->
      <!--     /ko -->
      <!-- /ko -->
    </div>
    

    You always need to declare your Stage, and at least one Layer. You can use knockout bindings to organize your shapes in that one layer, or distribute them among many layers, as is appropriate for your application.

    Once you have it working with JavaScript objects, you can use your JSON data directly by using the knockout mapping plugin:

    var viewModel = ko.mapping.fromJS(data);
    ko.applyBindings(viewModel);
    

    The "no JavaScript" refers to eliminating the need to setup your Kinetic Stage contents using JavaScript calls, replacing it with a declarative definition of your user interface.

    Also, be aware that the syntax is still under development. I haven't worked with it for a while so change hasn't happened quickly, but I'd be eager to hear feedback from your experiences.