dongtigai3875
dongtigai3875
2016-04-08 15:47

SVG到画布的路径

I would like to know how to render SVG paths and div elements in one image.

Example:

<div class="objects ui-droppable ui-sortable">
        <div class="b_s _jsPlumb_endpoint_anchor _jsPlumb_connected" id="start_block">START</div> 

        <div class="b_1 block ui-draggable ui-draggable-handle _jsPlumb_endpoint_anchor _jsPlumb_connected" id="n_block4" title="test"><span>test</span></div>

        <div class="b_s _jsPlumb_endpoint_anchor _jsPlumb_connected" id="end_block">STOP</div><div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 530px; top: 52px; background: transparent;"></div>

        <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 529.5px; top: 82px; background: transparent;"></div>

        <svg style="position:absolute;left:519.5px;top:48px" width="20" height="38" pointer-events="none" position="absolute" version="1.1" xmlns="http://www.w3.org/1999/xhtml" class="_jsPlumb_connector"><path d="M 0.5 -1 L 0.5 31 M 1.5 30 L -0.75 30 M 0.25 31 L 0.25 -1 M 1.25 0 L -1 0 M 0 0 L 0 30 " transform="translate(9.999999999999998,4)" pointer-events="visibleStroke" version="1.1" xmlns="http://www.w3.org/1999/xhtml" fill="none" stroke="rgb(7,152,216)" style="" stroke-width="2"></path><path pointer-events="all" version="1.1" xmlns="http://www.w3.org/1999/xhtml" d="M4.684274006738627e-16,32.650000000000006 L10.000000000000002,7.650000000000007 L1.4221210955098638e-15,17.075000000000006 L-9.999999999999998,7.650000000000005 L4.684274006738627e-16,32.650000000000006" class="" stroke="rgb(7,152,216)" fill="rgb(7,152,216)" transform="translate(9.999999999999998,4)"></path></svg>

        <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 529.5px; top: 126px; background: transparent;"></div>

        <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 530px; top: 156px; background: transparent;"></div>

        <svg style="position:absolute;left:520px;top:122px" width="20" height="38" pointer-events="none" position="absolute" version="1.1" xmlns="http://www.w3.org/1999/xhtml" class="_jsPlumb_connector"><path d="M 0 -1 L 0 31 M -1 30 L 1.25 30 M 0.25 31 L 0.25 -1 M -0.75 0 L 1.5 0 M 0.5 0 L 0.5 30 " transform="translate(9.499999999999998,4)" pointer-events="visibleStroke" version="1.1" xmlns="http://www.w3.org/1999/xhtml" fill="none" stroke="rgb(7,152,216)" style="" stroke-width="2"></path><path pointer-events="all" version="1.1" xmlns="http://www.w3.org/1999/xhtml" d="M0.5000000000000004,32.650000000000006 L10.500000000000002,7.650000000000007 L0.5000000000000014,17.075000000000006 L-9.499999999999998,7.650000000000005 L0.5000000000000004,32.650000000000006" class="" stroke="rgb(7,152,216)" fill="rgb(7,152,216)" transform="translate(9.499999999999998,4)"></path></svg>
</div>

Current JS code:

$("#btnExp").click(function() {
    //Canvas Count
    var CCount = 1;

    //prekopiramo vse elemente v nov div. Vmes SVG pretvorimo v canvas.
    $("body").append("<div class='ghost_img'></div>");

    //Gremo cez vse elemente. Jih pripnemo v ghost_img, svg->canvas canvas pozicioniramo kot svg.
    $(".objects").find("*").each(function(index) {
        var object = $(this);
        //Ce je DIV ga kloniramo
        if(this.tagName=='DIV'){
            $(".ghost_img").append(object.clone());
        //Ce je SVG dobimo kordinate, ga transformiramo v canvas in pripnemo, canvasu dodamo -> style: position:absolute, top:y, left:x
        }else if(this instanceof SVGElement){
            $(".ghost_img").append("<canvas id='c"+CCount+'></canvas>');
            var position = $(this).position();
            //alert(position.left + ", top: "+ position.top);
            var oSerializer = new XMLSerializer();
            var sXML = oSerializer.serializeToString(object);

            canvg(document.getElementById('c'+CCount), sXML);
            $('#c'+CCount).css("position","absolute");
            $('#c'+CCount).css("top",position.top);
            $('#c'+CCount).css("left",position.left);
            CCount = CCount+1;

        }
    });

    //Renderamo celoten ghost_img
    html2canvas($(".ghost_img"), {
        onrendered: function(canvas) {
            theCanvas = canvas;
            document.body.appendChild(canvas);
        }
    });

});

With the code above, every element gets rendered, but the picture is not right. How elements get rendered , how they should render.

Edit of the code above #1: Okay so here's my idea. I would like to append all the elements to a ghost div, while appending them one by one i would convert the svgs to canvas. I would also set position(left,top) and position absolute to canvases i create. Then i would like to render the whole ghost div.

Demo link: Demo

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • drhanjuw56233 drhanjuw56233 5年前

    The main issue with your code is the absolute positioning of your svg elements.

    canvg will be able to redraw it on a canvas, but it won't set back the correct styling on the canvas element. Which is the why everything is going down in the page.

    html2canvas should be able to render these svg itself, at least in latest versions, but once again because of this inlined absolute positioning on the root <svg> itself, the image will get off of the <img> used to draw on the canvas.


    So the solution would be to do some work by yourself before calling canvg and to keep track of the positions of your svg elements and reapply these once converted, before calling html2canvas.

    var $svg = $('svg');
    var svgStyles = [];
    $svg.each(function() {
      svgStyles.push(this.getAttribute('style'))
    })
    canvg();
    $('canvas').each(function(e) {
      $(this).attr('style', svgStyles[e])
    })
    html2canvas(...
    

    Snippet using canvg after saving the styles :

    $("#Exp").click(function() {
       var $svg = $('svg');
       var svgStyles = [];
       $svg.each(function() {
         svgStyles.push(this.getAttribute('style'))
       })
       canvg();
       $('canvas').each(function(e) {
         $(this).attr('style', svgStyles[e])
       })
       html2canvas($(".objects"), {
         onrendered: function(canvas) {
           theCanvas = canvas;
           document.body.appendChild(canvas);
         }
       });
     });
    /****************** DEFAULT ***********************/
    
    html,
    body {
      font-family: 'Open Sans', sans-serif;
      margin: 0;
      height: 100%;
    }
    [id^="block"] {
      margin: 35px auto;
      border-width: 1px;
    }
    /****************** DIAGRAM POTEKA ****************/
    
    .objects {
      width: 520px;
      margin: 0 auto;
      position: relative;
      z-index: 100;
      border-radius: 30px;
      text-align: center;
    }
    /******************* GHOST-BLOCKS *****************/
    
    [class^="empty_block_l"] {
      height: 1px;
      width: 1px;
      margin-right: 20px;
    }
    [class^="empty_block_r"] {
      height: 1px;
      width: 1px;
      margin-left: 20px;
    }
    [class^="empty_block_c"] {
      height: 1px;
      width: 1px;
      margin: 10px auto;
    }
    /************ NASTAVI-OBJEKTE-NA-SREDINO *********/
    
    [id^="n_block"].b_2,
    [id^="n_block"].b_4 {
      margin: 25px auto;
    }
    /************ OBLIKUJE-OBJEKTE *******************/
    
    ._jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable,
    svg {
      z-index: 888;
    }
    .subdiv_loop {
      padding: 0 10px;
      border: 1px dotted black;
      min-height: 100px;
      min-width: 195px;
      height: auto;
      width: auto;
      background-color: white;
      background-image: url(../slike/loop.gif);
      background-position: center;
      background-repeat: no-repeat;
    }
    .true {
      margin-right: 13px;
      padding: 0 10px;
    }
    .false {
      margin-left: 21px;
      padding: 0 10px;
    }
    .true,
    .false {
      display: inline-block;
      border: 1px dotted black;
      min-height: 100px;
      min-width: 150px;
      height: auto;
      background-color: white;
      padding: 0 5px;
      background-position: center;
      background-repeat: no-repeat;
    }
    .b_s {
      background-color: rgb(167, 206, 73);
      z-index: 888;
      width: 100px;
      height: 50px;
      margin: 30px auto;
      border: 1px solid black;
      line-height: 50px;
      text-align: center;
      font-weight: bold;
      -webkit-border-radius: 50px / 25px;
      -moz-border-radius: 50px / 25px;
      border-radius: 50px / 25px;
    }
    .b_2,
    .b_4 {
      background-color: white;
      border: 2px solid rgb(7, 152, 216);
      z-index: 888;
      line-height: 80px;
      height: 80px;
      width: 82px;
      border-radius: 10px;
      -moz-transform: rotate(45deg);
      -webkit-transform: rotate(45deg);
      -o-transform: rotate(45deg);
      -ms-transform: rotate(45deg);
      transform: rotate(45deg);
    }
    .SpodnjaTocka {
      width: 1px;
      height: 1px;
      margin: 15px auto;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
    <script src="https://gabelerner.github.io/canvg/canvg.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.js"></script>
    <div class="objects ui-droppable ui-sortable">
      <div class="b_s _jsPlumb_endpoint_anchor _jsPlumb_connected" id="start_block">START</div>
      <div class="b_2 block ui-draggable ui-draggable-handle zanka _jsPlumb_endpoint_anchor _jsPlumb_connected" id="n_block2" title="" style="width: 82px; height: 80px;"><span id="rotate_2"></span>
      </div>
      <div id="ovoj" class="ovoj n_block2">
        <div class="true n_block2 ui-droppable _jsPlumb_endpoint_anchor _jsPlumb_connected" id="jsPlumb_1_28"></div>
        <div class="false n_block2 ui-droppable _jsPlumb_endpoint_anchor _jsPlumb_connected" id="jsPlumb_1_39"></div>
      </div>
      <div class="SpodnjaTocka n_block2 _jsPlumb_endpoint_anchor _jsPlumb_connected" id="jsPlumb_1_29"></div>
      <div class="b_s _jsPlumb_endpoint_anchor _jsPlumb_connected" id="end_block">STOP</div>
      <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 261px; top: 52px; background: transparent;"></div>
      <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 261px; top: 82px; background: transparent;"></div>
      <svg style="position:absolute;left:251px;top:48px" width="20" height="38" pointer-events="none" position="absolute" version="1.1" class="_jsPlumb_connector">
        <path d="M 0 -1 L 0 31 M 0 31 L 0 -1 M 0 0 L 0 30 " transform="translate(9.999999999999998,4)" pointer-events="visibleStroke" version="1.1" fill="none" stroke="rgb(7,152,216)" style="" stroke-width="2"></path>
        <path pointer-events="all" version="1.1" d="M4.959819536546782e-16,33.1 L10.000000000000002,8.100000000000001 L1.4496756484906794e-15,17.525000000000002 L-9.999999999999998,8.100000000000001 L4.959819536546782e-16,33.1" class="" stroke="rgb(7,152,216)"
        fill="rgb(7,152,216)" transform="translate(9.999999999999998,4)"></path>
      </svg>
      <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 163px; top: 303px; background: transparent;"></div>
      <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 261.5px; top: 328px; background: transparent;"></div>
      <svg style="position:absolute;left:159px;top:299px" width="115.55000000000001" height="32" pointer-events="none" position="absolute" version="1.1" class="_jsPlumb_connector">
        <path d="M 0 -1 L 0 13.5 M -1 12.5 L 50.25 12.5 M 48.25 12.5 L 99.5 12.5 M 98.5 12.5 L 98.5 25 " transform="translate(4,4)" pointer-events="visibleStroke" version="1.1" fill="none" stroke="rgb(7,152,216)" style="" stroke-width="2"></path>
        <path pointer-events="all" version="1.1" d="M111.55000000000001,12.5 L86.55000000000001,22.5 L95.97500000000001,12.5 L86.55000000000001,2.5 L111.55000000000001,12.5" class="" stroke="rgb(7,152,216)" fill="rgb(7,152,216)" transform="translate(4,4)"></path>
      </svg>
      <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 359px; top: 303px; background: transparent;"></div>
      <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 261.5px; top: 328px; background: transparent;"></div>
      <svg style="position:absolute;left:248.35px;top:299px" width="114.65" height="32" pointer-events="none" position="absolute" version="1.1" class="_jsPlumb_connector">
        <path d="M 97.5 -1 L 97.5 13.5 M 98.5 12.5 L 47.75 12.5 M 49.75 12.5 L -1 12.5 M 0 12.5 L 0 25 " transform="translate(13.150000000000013,4)" pointer-events="visibleStroke" version="1.1" fill="none" stroke="rgb(7,152,216)" style="" stroke-width="2"></path>
        <path pointer-events="all" version="1.1" d="M-13.150000000000013,12.5 L11.849999999999987,2.5 L2.4249999999999865,12.5 L11.849999999999987,22.5 L-13.150000000000013,12.5" class="" stroke="rgb(7,152,216)" fill="rgb(7,152,216)" transform="translate(13.150000000000013,4)"></path>
      </svg>
      <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 218px; top: 124px; background: transparent;"></div>
      <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 163px; top: 201px; background: transparent;"></div>
      <svg style="position:absolute;left:153px;top:120px" width="69" height="84" pointer-events="none" position="absolute" version="1.1" class="_jsPlumb_connector">
        <path d="M 56 0 L 24 0 M 26 0 L -1 0 M 0 -1 L 0 48 M 0 47 L 0 77 " transform="translate(9.999999999999998,4)" pointer-events="visibleStroke" version="1.1" fill="none" stroke="rgb(7,152,216)" style="" stroke-width="2"></path>
        <path pointer-events="all" version="1.1" d="M2.2655965784226036e-16,75.7 L10.000000000000002,50.7 L1.1802533526782616e-15,60.125 L-9.999999999999998,50.7 L2.2655965784226036e-16,75.7" class="" stroke="rgb(7,152,216)" fill="rgb(7,152,216)" transform="translate(9.999999999999998,4)"></path>
      </svg>
      <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 304px; top: 124px; background: transparent;"></div>
      <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 359px; top: 201px; background: transparent;"></div>
      <svg style="position:absolute;left:300px;top:120px" width="69" height="84" pointer-events="none" position="absolute" version="1.1" class="_jsPlumb_connector">
        <path d="M -1 0 L 31 0 M 29 0 L 56 0 M 55 -1 L 55 48 M 55 47 L 55 77 " transform="translate(4,4)" pointer-events="visibleStroke" version="1.1" fill="none" stroke="rgb(7,152,216)" style="" stroke-width="2"></path>
        <path pointer-events="all" version="1.1" d="M55,75.7 L65,50.7 L55,60.125 L45,50.7 L55,75.7" class="" stroke="rgb(7,152,216)" fill="rgb(7,152,216)" transform="translate(4,4)"></path>
      </svg>
      <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 261.5px; top: 329px; background: transparent;"></div>
      <div class="_jsPlumb_endpoint _jsPlumb_endpoint_anchor jsplumb-draggable jsplumb-droppable" style="display: block; width: 10px; height: 0px; position: absolute; left: 261px; top: 359px; background: transparent;"></div>
      <svg style="position:absolute;left:251px;top:325px" width="20" height="38" pointer-events="none" position="absolute" version="1.1" class="_jsPlumb_connector">
        <path d="M 0.5 -1 L 0.5 31 M 1.5 30 L -0.75 30 M 0.25 31 L 0.25 -1 M 1.25 0 L -1 0 M 0 0 L 0 30 " transform="translate(9.999999999999998,4)" pointer-events="visibleStroke" version="1.1" fill="none" stroke="rgb(7,152,216)" style="" stroke-width="2"></path>
        <path pointer-events="all" version="1.1" d="M4.684274006738627e-16,32.650000000000006 L10.000000000000002,7.650000000000007 L1.4221210955098638e-15,17.075000000000006 L-9.999999999999998,7.650000000000005 L4.684274006738627e-16,32.650000000000006" class=""
        stroke="rgb(7,152,216)" fill="rgb(7,152,216)" transform="translate(9.999999999999998,4)"></path>
      </svg>
    </div>
    
    <button type="submit" id="Exp">ExportAsImage</button>

    Ps: Note that your namespace attributes were wrongly set to "http://www.w3.org/1999/xhtml"instead of "http://www.w3.org/2000/svg"

    </div>
    
    点赞 评论 复制链接分享