【问题标题】:SVG path to canvas画布的 SVG 路径
【发布时间】:2016-07-29 23:23:34
【问题描述】:

我想知道如何在一张图片中渲染 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);
        }
    });

});

使用上面的代码,每个元素都被渲染,但图片不正确。 How elements get renderedhow they should render

编辑上面#1 的代码:好的,这就是我的想法。我想将所有元素附加到一个幽灵 div,同时将它们一一附加我会将 svgs 转换为画布。我还将为我创建的画布设置位置(左,上)和绝对位置。然后我想渲染整个ghost div。

演示链接:Demo

【问题讨论】:

  • 您能否提供一个包含css的工作示例。
  • 我在上面添加了演示链接。
  • 看来你的问题来自你的svgs的绝对定位。 canvg 和 html2canvas 都不能渲染这些。我认为将您带到某些库不是一个好习惯,所以我现在将其作为评论留下,但使用SVG2Bitmap.js免责声明:我写了它)我能够让您的 svg 呈现:jsfiddle.net/ubtycqg4/1 主要问题但是,画布现在将在 IE 中受到污染
  • 演示不适合我。我收到此错误:无法导出 svg,请检查传递的 svgElement 是否为有效的 svg 文档。

标签: javascript php jquery canvas svg


【解决方案1】:

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

canvg 将能够在画布上重新绘制它,但它不会在画布元素上设置正确的样式。这就是页面中所有内容都在下降的原因。

html2canvas 应该能够自己渲染这些 svg,至少在最新版本中是这样,但再次由于根 &lt;svg&gt; 本身的这种内联绝对定位,图像将脱离用于绘制的 &lt;img&gt;画布。


因此,解决方案是在调用 canvg 之前自己做一些工作,并在调用 html2canvas 之前跟踪 svg 元素的位置并在转换后重新应用这些元素。

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>

附: 请注意,您的命名空间属性被错误地设置为"http://www.w3.org/1999/xhtml"而不是"http://www.w3.org/2000/svg"

【讨论】:

  • 嗯..奇怪,svg 是由一个名为 JsPlumb 的库生成的。这是 svg 箭头。
  • 请问xmln是什么意思?
  • xmlns 是可扩展标记语言名称空间的首字母缩写词。该属性定义了浏览器将如何解析标记,因为 XML、XHTML、SVG 和可能的其他一些,可以混合在同一个文档中,并且它们可能共享相同的元素或属性名称,它们的行为应该不同。 developer.mozilla.org/en/docs/Namespaces
  • 对我来说,不幸的是,库产生不正确的标记并不奇怪?图书馆是人写的。此外,它仅在少数情况下成为问题,例如呈现为 标记或作为独立文档。
  • 如何将 xmnl 更改为 svg 元素上的“.../2000/svg”?
猜你喜欢
  • 2017-03-24
  • 2014-11-18
  • 1970-01-01
  • 1970-01-01
  • 2020-11-19
  • 2016-02-14
  • 2016-01-06
  • 2021-06-25
  • 2022-01-10
相关资源
最近更新 更多