dongtigai3875 2016-04-08 15:47
浏览 265
已采纳

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 2016-04-11 15:05
    关注

    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>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 想咨询点问题,与算法转换,负荷预测,数字孪生有关
  • ¥15 C#中的编译平台的区别影响
  • ¥15 软件供应链安全是跟可靠性有关还是跟安全性有关?
  • ¥15 电脑蓝屏logfilessrtsrttrail问题
  • ¥20 关于wordpress建站遇到的问题!(语言-php)(相关搜索:云服务器)
  • ¥15 【求职】怎么找到一个周围人素质都很高不会欺负他人,并且未来月薪能够达到一万以上(技术岗)的工作?希望可以收到写有具体,可靠,已经实践过了的路径的回答?
  • ¥15 Java+vue部署版本反编译
  • ¥100 对反编译和ai熟悉的开发者。
  • ¥15 带序列特征的多输出预测模型
  • ¥15 Python 如何安装 distutils模块