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 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图