画布的SVG路径

SVG path to canvas

本文关键字:路径 SVG      更新时间:2024-03-24

我想知道如何在一个图像中渲染SVG路径和div元素。

示例:

<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>

当前JS代码:

$("#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);
        }
    });
});

使用上面的代码,每个元素都会被渲染,但图片不正确。元素的渲染方式,它们应该如何渲染。

编辑上面的代码#1:好的,这是我的想法。我想把所有元素都附加到一个ghostdiv中,同时一个接一个地附加它们,我会把svg转换为画布。我也会为我创建的画布设置位置(左,上)和绝对位置。然后我想渲染整个鬼分区。

演示链接:演示

代码的主要问题是svg元素的绝对定位。

canvg将能够在画布上重新绘制它,但它不会在画布元素上设置正确的样式。这就是为什么所有的东西都在页面上。

html2canvas应该能够自己渲染这些svg,至少在最新版本中是这样,但再次因为根<svg>本身的内联绝对定位,图像将脱离用于在画布上绘制的<img>


因此,解决方案是在调用canvg之前自己做一些工作,并跟踪svg元素的位置,并在转换后重新应用这些元素,然后再调用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(...

保存样式后使用canvg的代码段:

$("#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:请注意,您的命名空间属性被错误地设置为"http://www.w3.org/1999/xhtml"而不是"http://www.w3.org/2000/svg"