Как использовать расчетную ширину для прямоугольника SVG?

Я пытался разработать скелетное изображение SVG для его отображения во время загрузки данных. Вот код, который я использовал для редактирования SVG.

// converting svg tag to data url and setting it as background image
const svgURL = 'data:image/svg+xml;charset=utf-8;base64,' + btoa(document.querySelector('svg').outerHTML);
document.querySelector('#xyz').style.backgroundImage = `url(${svgURL})`;
svg {
  height: 48px;
}
.xyz {
  background-repeat: repeat-y !important;
  background-size: 100% 48px !important;
}
<svg
  width = "100%"
  height = "48"
  xmlns = "http://www.w3.org/2000/svg"
  stroke = "none"
  fill = "grey"
>
  <circle cx = "24" cy = "24" r = "12" />
  <rect height = "20" width = "calc(100% - 60px)" x = "48" y = "14" rx = "10" ry = "7" fill = "grey" />
</svg>

<div id = "xyz" style = "border: red 1px solid; height: 300px; width: 100%"></div>

Как вы можете видеть, тот же svg отображается правильно, если он является частью html, но как только мы используем его в качестве фона, ширина прямоугольника устанавливается неправильно.

Есть идеи, что я делаю неправильно и как это исправить?

Кажется, в Firefox все в порядке. Сообщайте о любых ошибках в соответствующую систему отслеживания ошибок браузера.

Robert Longson 18.07.2024 10:00
Создание фильтров для вашего сайта
Создание фильтров для вашего сайта
Фильтры - удобный инструмент в арсенале веб-дизайнера. Они позволяют изменять элементы на странице с помощью всего нескольких строк кода. Эти...
Анимация SVG-узоров без единой строки CSS
Анимация SVG-узоров без единой строки CSS
Недавно я работал над веб-проектом, который позволил мне поэкспериментировать с шаблонами SVG. С SVG очень приятно работать, как только вы получите...
Как использовать d3.js для рисования 2D SVG-элементов в приложении Angular?
Как использовать d3.js для рисования 2D SVG-элементов в приложении Angular?
D3.js - это обширная библиотека, используемая для привязки произвольных данных к объектной модели документа (DOM). Мы разберем основные варианты...
0
1
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вашей основной проблемой было отсутствие viewBox и отсутствие удаления пробелов между тегами SVG.
IMG.src более снисходителен к пробелам.

К вашему сведению; xmlns NameSpace требуется для backgroundImage и IMG, но его можно опустить при использовании в качестве встроенного SVG в (современном) HTML-документе.

Вам не нужен Oldskool Base64 в современных браузерах, просто экранируйте некоторые специальные символы URI.

(Для краткости я использовал ярлык глобального идентификатора oldskool, используйте правильные ссылки в рабочем коде)

function escape(svg) {
  return "data:image/svg+xml;charset=UTF-8," + svg
    .replace(/\>[\t\s\n ]+\</g, "><") // replace all whitespace BETWEEN tags  
    .replace(/#/g, '%23')
    .replace(/"/g, "'")
    .replace(/&/g, '&amp;');
}

XYZ.style.backgroundImage = `url("${escape(SVG.outerHTML)}")`;  
IMG.src = escape(SVG.outerHTML);
img, svg { width: 100%;  height: 40px;  background: pink }
#XYZ {
  border: red 1px solid; height: 60px; width: 100%;
  background-repeat: repeat-y;
  background-size: 100% 40px;
}
<b>Original SVG</b>
<svg id=SVG xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 350 50">
  <circle cx = "24" cy = "24" r = "12" fill = "green"/>
  <rect height = "20" width = "calc(100% - 40px)" x = "48" y = "14" rx = "10" ry = "7" fill = "teal" />
</svg>

<b>backgroundImage</b>
<div id = "XYZ"></div>

<b>IMG</b>
<img id=IMG>
Ответ принят как подходящий

CSS calc() по-прежнему может быть непредсказуемым в разных браузерах при применении к элементам SVG.

Вы можете использовать этот хак, используя элементы <line> вместо <rect>.
. Мы определяем длину через x2=100%,
примените преобразование translateX, чтобы сократить линию вправо
и смещение по оси X влево.

Протестировано в Firefox, Chrome и Safari.

// converting svg tag to data url and setting it as background image
const svgURL = 'data:image/svg+xml;charset=utf-8;base64,' + btoa(document.querySelector('svg').outerHTML);
document.querySelector('#xyz').style.backgroundImage = `url(${svgURL})`;
svg {
  height: 48px;
  border:1px solid #ccc;
}
.xyz {
  background-repeat: repeat-y;
  background-size: 100% 48px !important;
  resize:both;
  overflow:auto;
  
}
<svg
  width = "100%"
  height = "48"
  xmlns = "http://www.w3.org/2000/svg"
  stroke = "none"
  fill = "grey"
>
  <circle cx = "24" cy = "24" r = "12" />
  <line x1 = "110" y1 = "24" x2 = "100%" y2 = "24" stroke-width = "20" stroke-linecap = "round" stroke = "grey" style = "transform:translate(-40px, 0)"></line>
</svg>

<h3>Resize me</h3>
<div class = "xyz" id = "xyz" style = "border: red 1px solid; height: 300px; width: 100%"></div>

Другие вопросы по теме