Рисование файла SVG на холсте HTML5

131

Есть ли способ рисования файла SVG на холсте HTML5 по умолчанию? Google Chrome поддерживает загрузку SVG как изображения (и просто использование drawImage), но консоль разработчика предупреждает об этом resource interpreted as image but transferred with MIME type image/svg+xml.

Я знаю, что есть возможность конвертировать SVG в команды canvas (как в этом вопросе ), но я надеюсь, что это не нужно. Меня не волнуют старые браузеры (поэтому, если FireFox 4 и IE 9 будут поддерживать что-то, этого достаточно).

Рэнди Фоэт
источник
4
На этот вопрос есть ответ с живой демонстрацией stackoverflow.com/questions/5495952/…
Drew LeSueur

Ответы:

122

РЕДАКТИРОВАТЬ 16 декабря 2019

Path2D поддерживается всеми основными браузерами в настоящее время

РЕДАКТИРОВАТЬ 5 ноября 2014

Теперь вы можете использовать ctx.drawImageдля отрисовки HTMLImageElements с исходным кодом .svg в некоторых, но не во всех браузерах . Chrome, IE11 и Safari работают, Firefox работает с некоторыми ошибками (но по ночам их исправили).

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

Живой пример тут . Вы должны увидеть зеленый квадрат на холсте. Второй зеленый квадрат на странице - это тот же <svg>элемент, который вставлен в DOM для справки.

Вы также можете использовать новые объекты Path2D для рисования SVG (строки) путей. Другими словами, вы можете написать:

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

Живой пример этого здесь.


Старый ответ потомков:

Нет ничего родного, что позволяет вам использовать SVG-пути в canvas. Вы должны преобразовать себя или использовать библиотеку, чтобы сделать это для вас.

Я бы посоветовал заглянуть в canvg:

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

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

Саймон Саррис
источник
4
Зачем это нужно? SVG, кажется, отлично рисует на холсте просто drawImage. Но я все еще получаю это предупреждение. От куда это?
шош
1
Саймон, то, что ты говоришь, не правильно. А во-вторых, это подтвержденная ошибка в Chrome.
Матиас Ликкегор Лоренцен
4
Кажется, Викимедиа не нравится, когда вы используете SVG. Я поменялся местами в snapsvg.io/assets/images/logo.svg как первый доступный SVG, который я нашел. Работал в ФФ. jsfiddle.net/Na6X5/331
Томас
1
Вы также можете использовать Data URI для этого: jsfiddle.net/020k543w
Swivel
9
Примечание: из-за давней ошибки FireFox, к сожалению, svgs, у которых отсутствуют теги width и height, вообще не будут отображаться на холсте. Кроме того, ширина и высота не должны быть в процентах.
Hatoru Hansou
26

Извините, у меня недостаточно репутации, чтобы комментировать ответ @Matyas, но если изображение svg также находится в base64, оно будет отображено на выходе.

Демо-версия:

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

Энрике Кампос
источник
1
То же самое и со шрифтами, они должны быть встроены в SVG: jsfiddle.net/ykx7kp8L/121
Sphinxxx
1
Возможно, вы сможете перебирать imgтеги в svgи просто рисовать изображения на холсте отдельно после этого.
luckydonald
24

Вы можете легко нарисовать простые svgбуквы на холсте:

  1. Назначение источника SVG для изображения в формате base64
  2. Рисование изображения на холсте

Примечание . Единственным недостатком метода является то, что он не может рисовать изображения, встроенные в svg. (см. демонстрацию)

Демонстрация:

(Обратите внимание, что встроенное изображение видно только в 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/>

Матиас
источник
2
Есть ли способ исправить проблему, которую вы упомянули. Изображение встроено в SVG.
Виджей Баскаран
Извините, но я не нашел решения проблемы встроенного изображения.
Матиас
Ладно. Спасибо Матяш :)
Виджай Баскаран
6

В Mozilla есть простой способ рисования SVG на холсте, который называется « Рисование объектов DOM на холсте ».

Нати Криси
источник
Это имеет тот же недостаток, что и в первом методе @ Simon: не работает в Firefox, Chrome OK.
Amergin
3
Ваша ссылка больше не работает. Я все еще интересуюсь способом Mozilla
Alirezak
6

Как говорит Саймон выше, использование drawImage не должно работать. Но, используя библиотеку canvg и:

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

Это происходит по ссылке, предоставленной Саймоном выше, в которой есть ряд других предложений и указывается, что вы хотите либо дать ссылку, либо загрузить canvg.js и rgbcolor.js. Это позволяет вам манипулировать SVG-кодом и загружать его либо через URL, либо с помощью встроенного SVG-кода между тегами svg в функциях JavaScript.

Макс Вест
источник