Menggambar file SVG pada kanvas HTML5

130

Apakah ada cara default untuk menggambar file SVG ke kanvas HTML5? Google Chrome mendukung memuat SVG sebagai gambar (dan hanya menggunakan drawImage), tetapi konsol pengembang memperingatkannya resource interpreted as image but transferred with MIME type image/svg+xml.

Saya tahu bahwa kemungkinan akan mengubah SVG ke perintah kanvas (seperti dalam pertanyaan ini ), tapi saya berharap itu tidak diperlukan. Saya tidak peduli dengan browser lama (jadi jika FireFox 4 dan IE 9 akan mendukung sesuatu, itu cukup bagus).

Randy Voet
sumber
4
Pertanyaan ini memiliki jawaban dengan demo langsung stackoverflow.com/questions/5495952/...
Drew LeSueur

Jawaban:

121

EDIT 16 Des, 2019

Path2D didukung oleh semua browser utama sekarang

EDIT 5 November 2014

Anda sekarang dapat menggunakan ctx.drawImageuntuk menggambar HTMLImageElements yang memiliki sumber .svg di beberapa tetapi tidak semua browser . Chrome, IE11, dan Safari berfungsi, Firefox bekerja dengan beberapa bug (tetapi setiap malam telah memperbaikinya).

var img = new Image();
img.onload = function() {
    ctx.drawImage(img, 0, 0);
}
img.src = "http://upload.wikimedia.org/wikipedia/commons/d/d2/Svg_example_square.svg";

Contoh langsung di sini . Anda akan melihat kotak hijau di kanvas. Kotak hijau kedua pada halaman adalah <svg>elemen yang sama dimasukkan ke DOM untuk referensi.

Anda juga bisa menggunakan objek Path2D baru untuk menggambar jalur SVG (string). Dengan kata lain, Anda dapat menulis:

var path = new Path2D('M 100,100 h 50 v 50 h 50');
ctx.stroke(path);

Contoh langsungnya di sini.


Jawaban anak cucu tua:

Tidak ada yang asli yang memungkinkan Anda untuk menggunakan jalur SVG di kanvas. Anda harus mengonversi diri sendiri atau menggunakan perpustakaan untuk melakukannya untuk Anda.

Saya sarankan mencari di canvg:

http://code.google.com/p/canvg/

http://canvg.googlecode.com/svn/trunk/examples/index.htm

Simon Sarris
sumber
4
Mengapa ini dibutuhkan? SVG tampaknya menggambar dengan sempurna di kanvas hanya dengan drawImage. Tapi saya masih mendapat peringatan itu. Dari mana asalnya?
shoosh
1
Simon, apa yang kamu katakan tidak benar. Dan kedua, ini adalah bug yang dikonfirmasi di Chrome.
Mathias Lykkegaard Lorenzen
4
Tampaknya Wikimedia tidak suka Anda menggunakan SVG. Saya bertukar snapsvg.io/assets/images/logo.svg sebagai SVG pertama yang tersedia yang saya temukan. Bekerja di FF. jsfiddle.net/Na6X5/331
Thomas
1
Anda juga dapat menggunakan Data URI untuk melakukan ini: jsfiddle.net/020k543w
Swivel
9
Catatan: karena Bug FireFox yang telah lama berdiri, sayangnya, svgs yang tidak memiliki tag lebar dan tinggi tidak akan ditampilkan sama sekali di kanvas. Juga, lebar dan tinggi tidak boleh dalam persentase.
Hatoru Hansou
26

Maaf, saya tidak memiliki reputasi yang cukup untuk mengomentari jawaban @Matya, tetapi jika gambar svg juga ada di base64, itu akan ditarik ke output.

Demo:

var svg = document.querySelector('svg');
var img = document.querySelector('img');
var canvas = document.querySelector('canvas');

// get svg data
var xml = new XMLSerializer().serializeToString(svg);

// make it base64
var svg64 = btoa(xml);
var b64Start = 'data:image/svg+xml;base64,';

// prepend a "header"
var image64 = b64Start + svg64;

// set it as the source of the img element
img.onload = function() {
    // draw the image onto the canvas
    canvas.getContext('2d').drawImage(img, 0, 0);
}
img.src = image64;
svg, img, canvas {
  display: block;
}
SVG

<svg height="40">
  <rect width="40" height="40" style="fill:rgb(255,0,255);" />
  <image xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAEX0lEQVQ4jUWUyW6cVRCFv7r3/kO3u912nNgZgESAAgGBCJgFgxhW7FkgxAbxMLwBEmIRITbsQAgxCEUiSIBAYIY4g1EmYjuDp457+Lv7n+4tFjbwAHVOnVPnlLz75ht67OhhZg/M0p6d5tD9C8SNBBs5XBJhI4uNLC4SREA0UI9yJr2c4e6QO+v3WF27w+rmNrv9Pm7hxDyHFg5yYGEOYxytuRY2SYiSCIwgRgBQIxgjEAKuZWg6R9S0SCS4qKLZElY3HC5tp7QPtmlMN7HOETUTXBJjrEGsAfgPFECsQbBIbDGJZUYgGE8ugQyPm+o0STtTuGZMnKZEjRjjLIgAirEOEQEBDQFBEFFEBWLFtVJmpENRl6hUuFanTRAlbTeZarcx0R6YNZagAdD/t5N9+QgCYAw2jrAhpjM3zaSY4OJGTDrVwEYOYw2qioigoviq5MqF31m9fg1V5fCx+zn11CLNVnufRhBrsVFE1Ihpthu4KDYYwz5YQIxFBG7duMZnH31IqHL6wwnGCLFd4pez3/DaG2/x4GNPgBhEZG/GGlxkMVFkiNMYay3Inqxed4eP33uf7Y0uu90xWkGolFAru7sZn5w5w921m3u+su8vinEO02hEWLN/ANnL2rkvv2an2yd4SCKLM0JVBsCgAYZZzrnPP0eDRzXgfaCuPHXwuEYjRgmIBlQVVLl8/hKI4fRzz3L6uWe5+PMvnHz6aa4uX+D4yYe5vXaLH86eoyoLjLF476l9oKo9pi5HWONRX8E+YznOef7Vl1h86QWurlwjbc+QpikPPfoIcZLS39pmMikp8pzae6q6oqgriqrGqS+xeLScoMYSVJlfOMTl5RXW1+5w5fJVnFGWf1/mxEMnWPppiclkTLM5RdJoUBYFZVlQ5DnZMMMV167gixKLoXXsKGqnOHnqOJ/+/CfZ+XUiZ0jTmFv5mAvf/YjEliQ2vPD8Ir6qqEcZkzt38cMRo5WruFvfL9FqpyRxQhj0qLOax5I2S08+Tu/lFiGUGOPormxwuyfMnjrGrJa88uIixeYWl776lmrzNjmw8vcG8sU7ixpHMXFsCUVg9tABjEvRgzP82j7AhbyiX5Qcv2+Bvy7dYGZ1k7efeQB/Y4PBqGBtdYvb3SFzLcfqToZc/OB1zYeBSpUwLBlvjZidmWaSB1yaYOfn6LqI/r0hyU6P+cRSlhXjbEI2zvnt7y79oqQ3qeg4g6vKjCIXehtDmi6m0UnxVnCRkPUHVNt9qkLJxgXOCYNOg34v48raPaamU2o89/KKsQ9sTSpc0JK7NwdcX8s43Ek5cnSOLC/Z2R6Rj0ra0w2W1/t0xyWn51uk2Ri1QtSO6OU5d7OSi72cQeWxKG7p/Dp//JXTy6C1Pcbc6DMpPRtjTxChEznWhwVZUCKrjCrPoPDczHLmnLBdBgZlRRWUEBR3ZKrme5TlrTGlV440Y1IrXM9qQGi6mkG5V6uza7tUIeCDElTZ1L26elX+fcH/ACJBPYTJ4X8tAAAAAElFTkSuQmCC" height="20px" width="20px" x="10" y="10"></image>
</svg>
<hr/><br/>

IMAGE
<img/>
<hr/><br/>
   
CANVAS
<canvas></canvas>
<hr/><br/>

Henrique Campos
sumber
1
Hal yang sama dengan font, mereka harus tertanam dalam SVG: jsfiddle.net/ykx7kp8L/121
Sphinxxx
1
Anda mungkin dapat mengulangi melalui imgtag di svg, dan hanya menggambar gambar di kanvas secara terpisah sesudahnya.
luckydonald
24

Anda dapat dengan mudah menggambar svgs sederhana ke kanvas dengan:

  1. Menetapkan sumber svg ke gambar dalam format base64
  2. Menggambar gambar ke atas kanvas

Catatan: Satu-satunya kelemahan dari metode ini adalah tidak dapat menggambar gambar yang disematkan di svg. (lihat demo)

Demonstrasi:

(Perhatikan bahwa gambar yang disematkan hanya terlihat di svg)

var svg = document.querySelector('svg');
var img = document.querySelector('img');
var canvas = document.querySelector('canvas');

// get svg data
var xml = new XMLSerializer().serializeToString(svg);

// make it base64
var svg64 = btoa(xml);
var b64Start = 'data:image/svg+xml;base64,';

// prepend a "header"
var image64 = b64Start + svg64;

// set it as the source of the img element
img.src = image64;

// draw the image onto the canvas
canvas.getContext('2d').drawImage(img, 0, 0);
svg, img, canvas {
  display: block;
}
SVG

<svg height="40">
  <rect width="40" height="40" style="fill:rgb(255,0,255);" />
  <image xlink:href="https://en.gravatar.com/userimage/16084558/1a38852cf33713b48da096c8dc72c338.png?size=20" height="20px" width="20px" x="10" y="10"></image>
</svg>
<hr/><br/>

IMAGE
<img/>
<hr/><br/>
   
CANVAS
<canvas></canvas>
<hr/><br/>

Matya
sumber
2
Apakah ada cara untuk memperbaiki masalah yang Anda sebutkan. Gambar tertanam di svg.
Vijay Baskaran
Maaf, tapi saya belum menemukan solusi untuk masalah gambar yang disematkan.
Matya
Baik. Terima kasih Matyas :)
Vijay Baskaran
6

Mozilla memiliki cara sederhana untuk menggambar SVG di atas kanvas yang disebut " Menggambar objek DOM ke dalam kanvas "

Nati Krisi
sumber
Ini memiliki kelemahan yang sama dengan metode pertama @ Simon: tidak berfungsi di Firefox, Chrome OK.
amergin
3
Tautan Anda tidak berfungsi lagi. Saya masih tertarik dengan cara Mozilla
Alirezak
6

Seperti kata Simon di atas, menggunakan drawImage tidak akan berhasil. Tetapi, menggunakan perpustakaan canvg dan:

var c = document.getElementById('canvas');
var ctx = c.getContext('2d');
ctx.drawSvg(SVG_XML_OR_PATH_TO_SVG, dx, dy, dw, dh);

Ini berasal dari tautan yang disediakan Simon di atas, yang memiliki sejumlah saran lain dan menunjukkan bahwa Anda ingin menautkannya, atau mengunduh canvg.js dan rgbcolor.js. Ini memungkinkan Anda untuk memanipulasi dan memuat SVG, baik melalui URL atau menggunakan kode SVG sebaris di antara tag svg, dalam fungsi JavaScript.

Max West
sumber