locked
Keeping Layered Graphics in Position for Snapped...

    Question

  • I'm working on a dress up game, and having some trouble getting my graphics to stay in place when I do snapped view - I've tried all kinds of combinations, grids, ViewBox, etc - and I can't seem to get the items to stay placed on the primary graphic (in this case a pig :)

    These are really rough graphics but it shoes the problem I'm having - when I snap, the rock (which would be a HAT in the app) - repositions much higher than the pig.

    My html

    <div data-win-control="WinJS.UI.ViewBox" style="width:100%; height:100%;">
                
                   <div id="characterGrid" class="gridy" >
                    <embed id="thePig" class="pig"  src="/images/pig.svg"/>
                    <embed id="theImage" class="hat-item"  src="/images/rock.svg"/>
                  
    </div>
        </div> 

    My CSS

    .gridy {
      display: -ms-grid;
      height:100%;
      width:100%;
      -ms-grid-columns: (5%)[20];
      -ms-grid-rows: (5%)[20];
      border:dashed;
      border-color: red;
    }

    .hat-item {
    width:20%;
    height:20%; 
    z-index:1000; 
    position:absolute;
    left:65%;
    top:15%;
    }

    .pig {
    width:100%;
    height:100%; 
    z-index:0; 
    position:absolute;
    left:10%;
    top:15%;
    }

    As you see I'm no longer trying to use the grid rows/columns for the pig and hat as they were producing the same result as you see here.  Any ideas about how to fix this would be awesome!!

    Monday, September 24, 2012 9:10 PM

Answers

  • Hi Stacey,

    You need to understand what data-win-bind does.

    http://msdn.microsoft.com/en-us/library/windows/apps/hh700358.aspx

    in your case you are in a <div> element.  Your statement says "Take the 'innerText' property of this <div> and set it to the field called 'Image' in the data.

    So... what ever text is contained in the field 'Image' of your datasource would be plopped into the DIV.

    What you probably want is to have a field inside your <svg> </svg> definition and databind the href parameter of that <image> to your value.

    Alternatively you could add the image via code, you can get the pigSVG element and use javascript to set the image href property (might be better in your case).

    -Jeff


    Jeff Sanders (MSFT)

    Thursday, September 27, 2012 1:54 PM
    Moderator

All replies

  • Oops looks like the first graphic didn't upload

    Monday, September 24, 2012 9:11 PM
  • Hi Stacey,

    You should draw the SVG all inside an SVG canvas and not as separate images.  That way when the canvas changes everything inside will still be in the correct position.

    -Jeff


    Jeff Sanders (MSFT)

    Tuesday, September 25, 2012 12:33 PM
    Moderator
  • Hi Jeff - not an option, these are dynamically loaded from a listview control, and I'll have around 500 of them in my app.

    But I have found a way to get things "sticky" - if I get to where I understand why what I'm doing now works, I'll post it here!

    Thursday, September 27, 2012 1:02 AM
  • Ah let me clarify; they are loaded when the app begins - but the template loads each file from an array (not at runtime, which is more problematic). Then when the user clicks, that SVG graphic  is visible.
    Thursday, September 27, 2012 1:03 AM
  • Hi Jeff I used a bit of your advice - and found a way that the graphics seem to stay nicely stuck -

    <svg id="pigSVG" height="100%" width="100%"
    xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <g transform="scale(1)">
      <image x="0" y="0" height="700px" width="900px"  xlink:href="/images/pig.svg"/>
    </g>
    </svg>
    <svg id="theImage2" height="100%" width="100%"
    xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <g transform="scale(1)">
      <image x="400" y="0" height="200px" width="200px"  xlink:href="/images/hats/hatzy55.svg"/>
    </g>
    </svg>
    <div id="hatValue2" style="height:0px;visibility:hidden"  data-win-bind="innerText:Image;"></div>
    </div>

    My only problem now is that I need to use that data-win-bind="innerText:Image;" value instead of the static value I'm using for the 2nd SVG (id Image2) - where you see xlink:href="/images/hats/hatzy55.svg, I need to use the dynamic value pulled from my array instead.

    Any ideas? Thanks in advance!

    Thursday, September 27, 2012 2:33 AM
  • Hi Stacey,

    You need to understand what data-win-bind does.

    http://msdn.microsoft.com/en-us/library/windows/apps/hh700358.aspx

    in your case you are in a <div> element.  Your statement says "Take the 'innerText' property of this <div> and set it to the field called 'Image' in the data.

    So... what ever text is contained in the field 'Image' of your datasource would be plopped into the DIV.

    What you probably want is to have a field inside your <svg> </svg> definition and databind the href parameter of that <image> to your value.

    Alternatively you could add the image via code, you can get the pigSVG element and use javascript to set the image href property (might be better in your case).

    -Jeff


    Jeff Sanders (MSFT)

    Thursday, September 27, 2012 1:54 PM
    Moderator
  • Hi Jeff - yeah I've been working on trying to do just that - but I don't quite have the syntax right for the SVG. I'll keep working on it until I solve this today however, doing it via code might be the easiest, something like this maybe:

    var theImage2Var = document.getElementById("theImage2");    
    theImage2Var.setAttribute("xlink:href", $theUrl);
     
    Ah I'm using jQuery :) - then I just pass that $theUrl for each image in my function...

    Boy finding good tutorials on dynamically using SVG is really skinny right now - coming from a Flash background, it's kind of mind boggling because manipulating vector graphics has always sort been at the heart of Flash. But I've been surprised at how much I've been able to do with these SVG files (which were all originally SWFs, I batch converted them w/ a couple of nice command line tools) in just a couple of weeks.

    Thanks again, will try to post my final solution here!

    Thursday, September 27, 2012 5:13 PM
  • Ok all done! Geez what a long day of trying to get all the different ways to append to SVG, add variables in there, work with win-data-bind, etc - and in the end a 3rd part library called D3.js is what saved the day. I'm going to remove this from templating altogether, and just add each image as the user clicks on the icon in the listview, or add them in a for loop via JS.  But here is what works perfectly to keep my graphics glued in position no matter what resolution or screen view is present:

    function getHats() {

    $('#statusMessage').html('trying to add hats...');

    var $theUrl = "/images/hats/hatzy55.svg";

     var w = 900,
      h = 700;

    var MyCanvas = d3.select("#hatGraphicsDiv")
    .append("svg")
    .attr("width", w)
    .attr("height", h)
    .style("background-color", "gray");

    var MyRect = MyCanvas.append("image")
    .attr("id", "pigImage2")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 900)
    .attr("height", 700)
    .attr('xlink:href', "/images/pig.svg");

    var MyRect = MyCanvas.append("image")
    .attr("id", "hatImage2")
    .attr("x", 100)
    .attr("y", 100)
    .attr("width", 250)
    .attr("height", 250)
    .attr('xlink:href', $theUrl);

    // end getHats() function
    }

    Anybody tearing their hair out with SVG should really look at the D3.js project - it's got a lot of different things that seem to just plain work, whereas if you spend all day cutting and pasting from StackOverflow you will go crazy and end up w/ nada! Thanks again Jeff, your suggestion to use SVG inside my HTML proved to be the winner compared to going with <embed>.

     

    Thursday, September 27, 2012 9:50 PM