...


http://www.h2.dion.ne.jp/~defghi/svgMemo/svgMemo_03.htm

SVG to Canvas to PNG

SVGをCanvasに変換描画、さらにCanvasからPNGに変換

図形・模様・文様・幾何学模様のタイル背景画像素材生成

画像をダブルクリックで背景画像のレビュー可能

svg-path-builder

Paths

線を描く操作を表す.大文字は絶対位置指定,小文字は現在位置からの相対位置指定に対応する.
M,m
初期位置,位置のスキップ.
L,l
直線を引く
H,h
水平線を引く
V,v
垂直線を引く
C,c,S,s,Q,q,T,t
曲線を引く.端点と制御点とで曲線を指定する.
A,a
円弧を引く
Z,z
直近のM位置まで直線を引いて線を閉じる.なお,座標を重ねただけでは線が閉じられた事にはならない.
B,b
x軸の方向を設定する(他のコマンドによる描画に影響を及ぼす)†
R,r
Catmull-Romスプライン曲線を引く†

JavaScript

$(function(){
  var e = {};
  var i = 0;
  e.lis = $('#SVGs li');

/*
each内で全部toDataURLすると時間かかるため、
クリック(必要時)だけ生成する方法もある
*/

  //色変更のフォーム
  e.svgs = e.lis.find('svg');
  e.paths =e.svgs.find('*');
  e.paths_fill =e.paths.filter('[fill]');
  e.paths_stroke = e.paths.filter('[stroke]');

  var clickReset = function(){
    e.lis.removeClass('clicked');
    e.lis.find('.dl').remove();
    e.lis.find('canvas').remove();
  }
  $('#fill').on('change', function(){
    var val = $(this).val();
    e.paths.css({fill:val});
    clickReset();
  });
  $('#stroke').on('change', function(){
    var val = $(this).val();
    e.paths_stroke.css({stroke:val});
    clickReset();
  });
  $('#zoom').on('change', function(){
    var val = $(this).val();
    e.svgs.attr({zoom:val});
    clickReset();
  });

  $('#background').on('change', function(){
    //なぜかjQueryのままだと新規タグを挿入できない
    var val = $(this).val();
    var ns = 'http://www.w3.org/2000/svg';
    var ele = document.createElementNS(ns, 'svg:rect');
    var $e = $(ele);
    $e.attr({
      x:-1000,
      y:-1000,
      width:2000,
      height:2000,
      fill:val,
      class:'background',
    });
    e.svgs.each(function(){
      var svg = $(this);
      var eleC = $e.clone()[0];
      svg.find('.background').remove();
      var svg = $(this);
      svg.prepend(eleC);
    });
    clickReset();
  });

  $('#transform').on('change', function(){
    //なぜかjQueryのままだと新規タグを挿入できない
    var val = $(this).val();
    var ns = 'http://www.w3.org/2000/svg';
    var ele = document.createElementNS(ns, 'svg:g');
    var $e = $(ele);
    $e.attr({
      transform:val,
      class:'transform',
    });
    console.log($e);
    e.svgs.each(function(){
      var svg = $(this);
      var eleC = $e.clone()[0];
      var g = svg.find('.transform');
      if(g.length){
        svg.html(g.html());
      }
      var svg = $(this);
      svg.wrapInner(eleC);
    });
    clickReset();
  });



  e.svgs.on('dblclick', function(){
    $('#svgSource').val($(this)[0].outerHTML);
  });


  e.lis.on('click',  function(){
    e.li = $(this);
    if(e.li.hasClass('clicked')){return;}
    e.li.addClass('clicked');

    i++;
    // SVG要素取得+生成
    e.svg = e.li.find('svg'); //$('#svg');
    var html = e.svg[0].outerHTML;
    var canvasId = 'c'+i;
    var canvas = $('<canvas>').attr({'id': canvasId}).appendTo(e.li)[0];

    var pos = getViewBoxPos(html);
    canvas.setAttribute('width', pos.w);
    canvas.setAttribute('height', pos.h);
    canvg(canvasId, pos.html);

    e.a = $('<a>').addClass('dl').text('DL').appendTo(e.li).click(function(){$(this).remove();});

    toPng(canvas, e.a);

    //var data = e.canvas[0].toDataURL('image/png');
    //e.canvas.remove();
  });

  e.lis.find('svg').on('click', function(){
    var canvas = $(this).siblings('canvas')[0];
    if(canvas){
      var url = $(this).siblings('canvas')[0].toDataURL();
      $('body').css({backgroundImage: 'url('+url+')'});
    }
    
  });


  //画像変換
  function toPng(canvas, a){
    var url;// = canvas.toDataURL();
 
    if($('#pngEncoder').prop('checked')){
      //圧縮 canvastool.pngencoder.min.js
      var encoder = new CanvasTool.PngEncoder(
        canvas,
        {
          bitDepth: 8,
          colourType: CanvasTool.PngEncoder.ColourType.INDEXED_COLOR
        }
      );
      var png = encoder.convert();
      url = 'data:image/png;base64,' + window.btoa(png);
    } else {
      url = canvas.toDataURL();
    }
 
 
    var link = url.replace('image/png', 'application/octet-stream');
    var parent = a.parent();
    var title = parent.find('svg').attr('id');
    var h4 = parent.find('h4').text();
    if(!title){title = h4;}
    var size = canvas.width + 'x' + canvas.height;
    var download = 'svg-'+title+'-'+size+'.png';
    a.attr({href:link, download:download, title:download });
  }












  (function(){
    // テキスト編集と同時に描画確認
    var e = {};
    e.Editor = $('#Editor');
    e.svgArea = $('#svgArea');
    e.textarea = $('#textarea');

    console.log(e.textarea.val());

    // textareaの内容をSVGエリアに描画
    e.svgArea.html(e.textarea.val());
    e.textarea.on('keyup',function(){
      e.svgArea.html($(this).val());
    });


    $('#reload').on('click',function(){
      $('iframe')[0].contentDocument.location.reload(true);
    });

    //背景確認
    var canvasId = 'EditorCanvas';
    $('#toPng').on('click', function(e){

      var canvas = document.getElementById(canvasId);
      var html = $('#svgArea svg')[0].outerHTML;
      var pos = getViewBoxPos(html);
      canvas.setAttribute('width', pos.w);
      canvas.setAttribute('height', pos.h);
      canvg(canvasId, pos.html);
      var url = document.getElementById(canvasId).toDataURL();
      $('#checkBG').css({backgroundImage: 'url('+url+')'});
      $('#checkIMG').attr({src:url});
    });
    


    $('#isGrid').on('change',function(){
      var isGrid = $(this).prop('checked');
      if(isGrid){
        $('#grid').show();
      }else {
        $('#grid').hide();
      }
    });

    //座標確認
/*
    var spanXY = $('#xy');
    e.svgArea.on('mousemove', function(ev){
      var x = ev.pageX - e.svgArea.position().left;
      var y = ev.pageY - e.svgArea.position().top;
      spanXY.text(x+':'+y);
    });
*/
    //要素確認
    var spanElement = $('#svgSource');
    e.svgArea.on('click', 'svg *', function(ev){
      console.log($(this)[0]);
      console.log($(this)[0].toString());
      console.log($(this)[0].outerHTML);
      //$(this)[0].nodeName
      spanElement.val($(this)[0].outerHTML);
    });

    //無駄記述を消す
    $('#delXMLNS').on('click', function(){
      var val = e.textarea.val();
      val = val.replace(/ xmlns:xlink="http:\/\/www.w3.org\/1999\/xlink"/img, '');
      val = val.replace(/><\/([^>]*)>/img, ' />');
      e.textarea.val(val);
    });

    //枠を追加
    $('#addFrame').on('click', function(){
      var val = e.textarea.val();
      var pos = getViewBoxPos(val);
      var rectTag = '  <rect x="0" y="0" ' +
        'width="'+pos.w+'" height="'+pos.h+'"' + 
      ' fill="none" stroke="rgba(200,0,0,.2)" />\n';
      var rectTag2 = '  <rect x="'+x+'" y="'+y+'" ' +
        'width="'+pos.w+'" height="'+pos.h+'"' + 
      ' fill="none" stroke="rgba(0,0,200,.4)" />\n';
      val = val.replace('</svg>', rectTag +rectTag2 + '</svg>');
      e.textarea.val(val);
    });



  })();



  //canvasの大きさをviewBoxに合わせ、倍率調整する
  var getViewBoxPos = function(html){
    var pos ={};
    var matchViewBox;
    var matchZoom;
    var reViewBox = new RegExp('viewBox="([\-0-9]*) ([\-0-9]*) ([0-9]*) ([0-9]*)"', 'img');
    var reZoom = new RegExp('zoom="([\-\.0-9]*)"', 'img');
    matchViewBox = html.match(reViewBox);
    //console.log(matchViewBox);
    pos.zoom = 1;
    pos.x = RegExp.$1 || 100;
    pos.y = RegExp.$2 || 100;
    pos.w = RegExp.$3 || 100;
    pos.h = RegExp.$4 || 100;
    matchZoom = html.match(reZoom);
    if(matchZoom){
      pos.zoom = RegExp.$1;
    }
    pos.x = pos.x * pos.zoom;
    pos.y = pos.y * pos.zoom;
    pos.w = pos.w * pos.zoom;
    pos.h = pos.h * pos.zoom;
    pos.html = html;
    pos.html = pos.html.replace(/(<svg [^>]*>)/, '$1<g transfrom="scale('+pos.zoom+')">');
    pos.html = pos.html.replace(/(<\/svg>)/, '</g>$1');
    return pos;
  }



});




// textarea tab indent
var el = document.getElementById('textarea');
tabIndent.render(el);
tabIndent.config.tab = '  ';

CSS

nav{
  position:fixed;
  left:0;
  top:0;
  height:40px;
  background-color:#ffffff;
}
nav li,
nav a{
  display:inline-block;
  width:120px;
  height:40px;
  line-height:40px;
  text-align:center;
  color:#333333;
  text-decoration:none;
}
nav a:hover{
  background-color:#eeeeee;
}

#demo section{
  padding-top:40px;
  min-height:800px;
}

input{
  width:120px;
}
input[type="checkbox"]{
  width:20px;
}

#custom{
  position:fixed;
  right:0;
  top:0;
  z-index:2;
  width:100%;
  height:120px;
  background-color:rgba(0,0,0,.5);
  color:#FFFFFF;
  font-size:12px;
  font-family:monospace;
}
#custom span{
  display:inline-block;
  width:80px;
  height:24px;
}
#custom input{
  height:24px;
}
#custom textarea{
  position:absolute;
  right:0;
  top:0;
  width:480px;
  height:120px;
}

#SVGs{
  width:1020px;
  padding-top:240px;
  padding-bottom:720px;
  -webkit-user-select:none;
}

#SVGs:after{
  display:block;
  content:"";
  clear:both;
}
#SVGs li{
  width:100px;
  height:160px;
  float:left;
  line-height:16px;
  border:1px solid #555555;
}

#SVGs svg{
  width:100px;
  height:100px;
  background-color:#aaaaaa;
}

#SVGs canvas{
  display:none;
}

#SVGs h4{
  padding:2px auto;
  height:36px;
  font-size:10px;
  font-weight:bold;
  word-wrap:nowrap;
  background-color:#ffffff;
}
#SVGs a{
  display:inline-block;
  margin:1px 4px;
  padding:1px 4px;
  background-color:#ffffff;
  border:1px solid #aaaaaa;
  border-radius:4px;
  text-decoration:none;
  cursor:pointer;
}

#SVGs a:hover{
  background-color:#aaccff;
}
#SVGs a.clicked{
  background-color:#aaaaaa;
}

.svg{
  width:100px;
  height:100px;
  border:1px solid #ff0000;
}








#Editor{
  position:relative;
  left:0;
  top:0;
  border:1px solid #aaaaaa;
  display:flex;
}

#Editor *{
  box-sizing:border-box;
}

#Editor > div{
}

#textareaFrame{
  width:calc(100% - 400px);
}

#Editor textarea{
  z-index:99;
  display:block;
  width:100%;
  min-height:200px;
  font-size:12px;
  font-family:monospace;
}

#Editor textarea:hover{

}

#textarea{
  height:400px;
}

#svgFrame{
  position:relative;
  left:0;
  top:0;
  width:400px;
  border:1px dotted #aaaaaa;
}
#svgArea{
  width:400px;
  height:400px;
}
#svgArea img,
#svgArea svg{
  position:absolute;
  left:0;
  top:0;
  width:400px;
  height:400px;
}
#grid{
  position:absolute;
  left:0;
  top:0;
  width:400px;
  height:400px;
}

#svgArea svg *:hover{
  opacity: 0.5;
  background-color:#ff0000;
}
#Editor #checkBG{
  width:400px;
}
#Editor canvas{
  display:none;
}


#viewArea{
  width:400px;
  height:600px;
  background-image: url(../svg-icon/bg-alpha.svg);
}
#checkBG{
  height:400px;
}
#checkIMG{
  max-width:400px;
  max-height:400px;
}

#samples{
  width:1200px;
  height:720px;
}