【问题标题】:Multi polygon SVG selection (fill color) and mask export to an image多多边形 SVG 选择(填充颜色)和蒙版导出到图像
【发布时间】:2019-05-30 23:42:33
【问题描述】:

需要加载图片+SVGmask,选择SVG的多边形(填充颜色),导出SVG mask到图片。

我的初始 HTML 代码基于 @Praveen 对另一个 question 的回答,以便能够拥有背景图像并在其上放置我已经拥有的多多边形 SVG,以定义每个颜色边缘。

目标是能够选择所需的多边形,然后只保存蒙版。一个过程,一步一步将是用户选择下面的图像,例如红色和黑色,考虑到未选择黑色多边形(选择白色),保存 SVG 蒙版。

我在JSFiddle 上做了一个示例,以便更清楚地了解嵌入图像和 SVG 的 src 的 HTML 代码,但它们将在代码中注释的本地文件中。

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>TEST SVG</title>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!--
https://github.com/eligrey/Blob.js/
https://github.com/eligrey/FileSaver.js
-->
<script src="Blob.js"></script>
<script src="FileSaver.js"></script>
<script>
$(document).ready(function(e) {
        $('img.svg').each(function(){
                var $img = jQuery(this);
                var imgID = $img.attr('id');
                var imgClass = $img.attr('class');
                var imgURL = $img.attr('src');

                jQuery.get(imgURL, function(data) {
                    // Get the SVG tag, ignore the rest
                    var $svg = jQuery(data).find('svg');

                    // Add replaced image's ID to the new SVG
                    if(typeof imgID !== 'undefined') {
                        $svg = $svg.attr('id', imgID);
                    }
                    // Add replaced image's classes to the new SVG
                    if(typeof imgClass !== 'undefined') {
                        $svg = $svg.attr('class', imgClass+' replaced-svg');
                    }

                    // Remove any invalid XML tags as per http://validator.w3.org
                    $svg = $svg.removeAttr('xmlns:a');

                    // Replace image with new SVG
                    $img.replaceWith($svg);

                    $('path').click(function(){
                        if($(this).attr("class")=="selected"){
                            $(this).attr("class", "");
                        }
                        else{
                            $(this).attr("class","selected");
                        }
                    });

                }, 'xml');
        });
});


function writeDownloadLink(){
    try {
        var isFileSaverSupported = !!new Blob();
    } catch (e) {
        alert("blob not supported");
    }
    /*
    var blob = new Blob([mySVG], {type: "image/svg+xml"});
    saveAs(blob, "mySVG_selection.png");
    */
};

</script>
<style>
    #bg div{
        position:absolute;  
        top:0px;
        left:0px;
    }
    #bg .path{
        z-index:1;  
    }
    #bg .bg{
        z-index:0;  
    }
    path{
        fill:transparent;
    }
    path:hover{
        fill:rgba(255,255,255,0.6);
        cursor:pointer;
    }
    path.selected{
        fill:rgba(255,255,255,0.6); 
    }
    #savebutton {
        position:absolute;  
        top:0px;
        left:400px;
    }
</style>
</head>
<body>
    <div id="bg">
        <div class="path">
            <!--<img src="Sample_svg.svg" class="svg" />-->
            <img src='data:image/svg+xml;utf8,
                <svg width="1000" height="1000" xmlns="http://www.w3.org/2000/svg">
                    <path d="M0 0 0 200 200 200 200 0 "/>
                    <path d="M0 200 0 400 200 400 200 200 "/>
                    <path d="M200 0 200 200 400 200 400 0 "/>
                    <path d="M200 200 200 400 400 400 400 200 "/>
                </svg>
            ' class="svg" />
        </div>
        <div class="bg">
            <!--<img src="Sample_Bg.png" />-->
            <img src="https://imgur.com/olRQfPy.png" />
        </div>
    </div>
    <div id="savebutton">
        <button onclick="writeDownloadLink()">Save PNG</button>
    </div>
</body>
</html>

所以要解决的问题是提取/导出“SVG 蒙版”并将其保存在 PNG 文件中。 我有一个猜测(我不擅长 Web 服务、javascript 等),Blob JavaScript 可以使用类似于以下的代码来帮助做到这一点:

var blob = new Blob([mySVG], {type: "image/svg+xml"});
saveAs(blob, "mySVG_selection.png");

这是对示例的某种评论,但不知道如何仅采用“SVG 蒙版”并将其转换为图像。

编辑

基于@enxaneta cmets,我更新了一个工作代码,但无法取消选择选定的多边形:

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>TEST SVG</title>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<script>
function myFunction()
{

    let canv = document.createElement("canvas");
    canv.width = svg.getAttribute("width");
    canv.height = svg.getAttribute("height");
    //canv.width = $('svg').attr("width");
    //canv.height = $('svg').attr("height");
    let ctx = canv.getContext("2d");
    ctx.fillRect(0,0,canv.width,canv.height)

    let selectedRy = [];

    svg.addEventListener("click",(e)=>{
      if(e.target.nodeName == "path"){
        e.target.classList.add("selected");
        selectedRy.push(e.target.getAttribute("d"));
      } 
    })

    action.addEventListener("click",()=>{
      for(let i = 0; i < selectedRy.length; i++){
          let thisPath = new Path2D(selectedRy[i]);
          ctx.fillStyle = "white";
          ctx.fill(thisPath); 
      }
      img.setAttribute("src",canv.toDataURL("myImg.png"));
    })
}
</script>
<style>
    #bg div{
        position:absolute;  
        top:30px;
        left:0px;
    }
    #bg .path{
        z-index:1;  
    }
    #bg .bg{
        z-index:0;  
    }
    path{
        fill:transparent;
    }
    path:hover{
        fill:rgba(255,255,255,0.6);
        cursor:pointer;
    }
    img{
        border:0px solid
    }
</style>
</head>
<body onload="myFunction()">
   <button id="action">click</button>
   <div id="bg">
      <div class="path">
         <!--<img src="Sample_svg.svg" class="svg" />-->
         <svg id="svg" xmlns="http://www.w3.org/2000/svg" width="400" height="400" class="svg replaced-svg">
            <path d="M0 0 0 200 200 200 200 0"></path>
            <path d="M0 200 0 400 200 400 200 200"></path>
            <path d="M200 0 200 200 400 200 400 0"></path>
            <path d="M200 200 200 400 400 400 400 200 " ></path>
         </svg>
         <img id="img" width="400" height="400"/> 
      </div>
      <div class="bg">
         <!--<img src="Sample_Bg.png" />-->
         <img src="https://imgur.com/olRQfPy.png" />
      </div>
   </div>
</body>
</html>

【问题讨论】:

    标签: javascript jquery html image svg


    【解决方案1】:

    我了解用户会点击一些 svg 矩形,然后您需要将其保存到所选矩形为黑色背景上的白色的图像中。我是这种情况,这是我的解决方案:

    1. 用户点击矩形。
    2. 您选择这些矩形并将d 属性保存在selectedRy
    3. 当用户单击按钮(或其他事件)时,您将这些矩形复制到画布(在这种情况下未附加到 DOM),然后使用 toDataURL() 将其保存为数据 uri 图像。

    let canv = document.createElement("canvas");
    canv.width = svg.getAttribute("width");
    canv.height = svg.getAttribute("height");
    let ctx = canv.getContext("2d");
    ctx.fillRect(0,0,canv.width,canv.height)
    
    let selectedRy = [];
    
    svg.addEventListener("click",(e)=>{
      if(e.target.nodeName == "path"){
        e.target.classList.add("selected");
        selectedRy.push(e.target.getAttribute("d"));
      } 
    })
    
    
    action.addEventListener("click",()=>{
      for(let i = 0; i < selectedRy.length; i++){
      let thisPath = new Path2D(selectedRy[i]);
      ctx.fillStyle = "white";
      ctx.fill(thisPath); 
      }
      img.setAttribute("src",canv.toDataURL());
    })
    path:hover{opacity:.5}
    img{border:1px solid}
    <button id="action">click</button>
    <div class="path">
    	<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="400" height="400" class="svg replaced-svg">
    		<path d="M0 0 0 200 200 200 200 0" fill="red"></path>
    		<path d="M0 200 0 400 200 400 200 200" fill="blue"></path>
    		<path d="M200 0 200 200 400 200 400 0" fill="lightgreen"></path>
    		<path d="M200 200 200 400 400 400 400 200 " ></path>
        </svg>
      
    <img id="img" width="400" height="400"/>  
    </div>

    我希望这是你需要的。

    更新

    OP 正在评论:

    您的代码在推送时不允许“删除选择”。有什么方法可以取消选择之前选择的多边形?

    此更新是对他们评论的这一部分的回答。

    您可以切换该类,而不是在单击时添加一个类。选定的矩形是所有具有.selected 类的矩形:sel = svg.querySelectorAll(".selected")。然后,当您单击每个选定路径的按钮时,您会在画布上绘制一条路径。

    为了知道选择了哪些 svg rects,我在 css 中添加了.selected{opacity:.25}

    let canv = document.createElement("canvas");
    canv.width = svg.getAttribute("width");
    canv.height = svg.getAttribute("height");
    let ctx = canv.getContext("2d");
    
    let sel = [];
    svg.addEventListener("click",(e)=>{
      if(e.target.nodeName == "path"){
        e.target.classList.toggle("selected");
        sel = svg.querySelectorAll(".selected")
      } 
    })
    
    
    action.addEventListener("click",()=>{
      //painting a black rect
      ctx.fillStyle = "black";
      ctx.fillRect(0,0,canv.width,canv.height);
      //for every selected element in the SVG is painting a white rect on the canvas
      for(let i = 0; i < sel.length; i++){
      let thisPath = new Path2D(sel[i].getAttribute("d"));
      ctx.fillStyle = "white";
      ctx.fill(thisPath); 
      }
      //paint the image
      img.setAttribute("src",canv.toDataURL());
    })
    path:hover{opacity:.75}
    img{border:1px solid}
    .selected{opacity:.25}
    <button id="action">click</button>
    <div class="path">
    	<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="400" height="400" class="svg replaced-svg">
    		<path d="M0 0 0 200 200 200 200 0" fill="red"></path>
    		<path d="M0 200 0 400 200 400 200 200" fill="blue"></path>
    		<path d="M200 0 200 200 400 200 400 0" fill="lightgreen"></path>
    		<path d="M200 200 200 400 400 400 400 200 " ></path>
        </svg>
      
    <img id="img" width="400" height="400"/>  
    </div>

    【讨论】:

    • 您在 SVG 定义中定义填充颜色,但事实并非如此,因为我不能使用这种定义。我更新了我的代码以满足这个要求。但是,您的代码在推送时不允许“删除选择”。有什么方法可以取消选择之前选择的多边形?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-03
    • 2013-02-21
    • 2020-07-26
    相关资源
    最近更新 更多