SVG загружается несколько раз на одной странице. SVG используется для графического представления значений. Представьте карту, на которой каждый регион показывает заданное значение с использованием цветового кода.
В каждом SVG, для каждой области динамически применяется класс CSS, чтобы соответствовать желаемому используемому шаблону заливки SVG.
Стили и шаблоны CSS определены в файле SVG. Вот пример:
<svg height = "100" width = "100">
<style>
/* */
.striped-pain-1 {fill: url(#striped-pain-1);}
/* */
</style>
<defs>
<pattern id = "striped-pain-1" width = "4" height = "1" patternTransform = "rotate(45 0 0)" patternUnits = "userSpaceOnUse">
<line x1 = "0" y1 = "0" x2 = "0" y2 = "2" style = "stroke:#EABFD5; stroke-width:6"></line>
</pattern>
</defs>
Проблема в том, что когда один из SVG скрыт (например, через display:none), все SVG оттуда до нижней части страницы теряют заливку узором.
Я сделал упрощенный Plunker, показывающий проблему.
https://plnkr.co/edit/F5TzOwDEzneHEW7PT3Ls?p=preview
Единственный способ, который я нашел, чтобы предотвратить это, - использовать другой шаблон ids для каждого SVG, но, поскольку все используют один и тот же файл, мне не нравится решение дублировать их все и переименовывать идентификаторы только для этого. Интересно, должно быть лучшее решение.
Спасибо, но не могли бы вы подробнее ответить? Почему использование display:none нарушает стиль? Я немного не понимаю, что происходит.
display: ни у одного поддерева нет CSS. Без CSS никакие стили или атрибуты, сопоставленные стилям, работать не будут.
@RobertLongson, раз уж разыгрывается награда, вы можете добавить эти комментарии в ответ.
Этот вопрос больше относится к структуре html, чем к отображению css. Тег DEFS предназначен для хранения структур, поэтому настоящая проблема заключается в том, чтобы поместить определение внутри тега div, которое будет скрыто. Кроме того, это дублированные идентификаторы, в чем и заключается суть вопроса. Ответ добавлен. w3schools.com/tags/att_global_id.aspdeveloper.mozilla.org/en-US/docs/Web/SVG/Element/defs






Я бы поместил шаблоны в другой элемент svg: <svg class = "defs">. Этот элемент svg может иметь position:absolute и очень маленькую ширину и высоту. Если вы добавите left: -200px;, этот элемент svg станет невидимым.
Также: если один элемент SVG имеет это правило css: .striped-pain-1 {fill: url(#striped-pain-1);}, вам не нужно добавлять его ко второму. Фактически, вы можете удалить элемент <style> из svg и добавить это правило в css.
Попробуйте: щелкните числа (1,2,3), чтобы скрыть или показать элементы svg.
let spans = Array.from(document.querySelectorAll("#commands span"))
let svgs = Array.from(document.querySelectorAll(".svgcontainer"))
spans.forEach((s,i) =>{
let n = 0;
s.addEventListener("click",(e)=>{
n++;
let thisSvg = svgs[i].querySelector("svg")
if (n%2 == 1){thisSvg.style.display = "none";
}else{
thisSvg.style.display = "block";}
})
})svg {
display:block;
}
.defs {
position: absolute;
left: -200px;
}
span {
display: inline-block;
width: 2em;
height: 1em;
border: 1px solid;
text-align: center;
cursor: pointer;
}
.svgcontainer {
height: 100px;
width: 100px;
border: 1px solid;
display: inline-block;
}<p id = "commands"><span>1</span> <span>2</span> <span>3</span></p>
<svg class = "defs" width = "1" height = "1">
<defs>
<pattern id = "striped-pain-1" width = "4" height = "1" patternTransform = "rotate(45 0 0)" patternUnits = "userSpaceOnUse">
<line x1 = "0" y1 = "0" x2 = "0" y2 = "2" style = "stroke:#EABFD5; stroke-width:6"></line>
</pattern>
<pattern id = "striped-pain-2" width = "4" height = "1" patternTransform = "rotate(45 0 0)" patternUnits = "userSpaceOnUse">
<line x1 = "0" y1 = "0" x2 = "0" y2 = "2" style = "stroke:#EABFD5; stroke-width:6"></line>
</pattern>
</defs>
</svg>
<div class = "svgcontainer">
<svg height = "100" width = "100">
<style>
/* */
.striped-pain-1 {fill: url(#striped-pain-1);}
/* */
</style>
<circle class = "striped-pain-1" cx = "50" cy = "50" r = "40" stroke = "black" stroke-width = "3" fill = "red" />
</svg>
</div>
<div class = "svgcontainer">
<svg height = "100" width = "100">
<!-- <style>
/* */
.striped-pain-1 {fill: url(#striped-pain-1);}
/* */
</style>-->
<!--<defs>
<pattern id = "striped-pain-1" width = "4" height = "1" patternTransform = "rotate(45 0 0)" patternUnits = "userSpaceOnUse">
<line x1 = "0" y1 = "0" x2 = "0" y2 = "2" style = "stroke:#EABFD5; stroke-width:6"></line>
</pattern>
</defs>-->
<circle class = "striped-pain-1" cx = "50" cy = "50" r = "40" stroke = "black" stroke-width = "3" fill = "red" />
</svg>
</div>
<div class = "svgcontainer">
<svg height = "100" width = "100">
<style>
/* */
.striped-pain-2 {fill: url(#striped-pain-2);}
/* */
</style>
<circle class = "striped-pain-2" cx = "50" cy = "50" r = "40" stroke = "black" stroke-width = "3" fill = "red" />
</svg>
</div>В конце концов я использовал именно такой подход. Я просто делюсь всем defs для всех svgs в невидимом элементе svg. Это также упростило мой код, чтобы избежать ненужного дублирования.
Эта проблема возникает из-за того, что вы указали один и тот же id для двух разных элементов:
<pattern id = "striped-pain-1" в строках 52 и 69.
В HTML id должен быть уникальным.
The id attribute specifies a unique id for an HTML element (the value must be unique within the HTML document).
Замена дублированного id на уникальный решает проблему. См. Фрагмент ниже:
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href = "' + document.location + '" />');</script>
<link rel = "stylesheet" href = "style.css" />
<script data-require = "[email protected]" src = "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver = "1.5.11"></script>
<script src = "app.js"></script>
<script>
function show(id) {
document.getElementById('circle-' + id).style.display = 'block';
}
function hide(id) {
document.getElementById('circle-' + id).style.display = 'none';
}
function reset() {
document.getElementById('circle-1').style.display = 'block';
document.getElementById('circle-2').style.display = 'block';
}
</script>
</head>
<body ng-controller = "MainCtrl">
<div style = "padding:10px">
<input type='button' onclick = "hide(1)" value = "Step 1: Click here to hide first circle. Second will loose style." />
</div>
<div style = "padding:10px">
<input type='button' onclick = "show(1)" value = "Step 2: Click here to show first circle. Second will gain style." />
</div>
<div style = "padding:10px">
<input type='button' onclick = "hide(2)" value = "Step 3: Click here to hide second circle. First is not affected." />
</div>
<div style = "padding:10px">
<input type='button' onclick = "reset()" value = "Step 4: Reset." />
</div>
<div id = "circle-1" style = "padding:10px;border:solid grey 1px">
Circle 1
<svg height = "100" width = "100">
<style>
/* */
.striped-pain-1 {fill: url(#striped-pain-1);}
/* */
</style>
<defs>
<pattern id = "striped-pain-1" width = "4" height = "1" patternTransform = "rotate(45 0 0)" patternUnits = "userSpaceOnUse">
<line x1 = "0" y1 = "0" x2 = "0" y2 = "2" style = "stroke:#EABFD5; stroke-width:6"></line>
</pattern>
</defs>
<circle class = "striped-pain-1" cx = "50" cy = "50" r = "40" stroke = "black" stroke-width = "3" fill = "red" />
</svg>
</div>
<div id = "circle-2" style = "padding:10px;border:solid grey 1px">
Circle 2
<svg height = "100" width = "100">
<style>
/* */
.striped-pain-2 {fill: url(#striped-pain-2);}
/* */
</style>
<defs>
<pattern id = "striped-pain-2" width = "4" height = "1" patternTransform = "rotate(45 0 0)" patternUnits = "userSpaceOnUse">
<line x1 = "0" y1 = "0" x2 = "0" y2 = "2" style = "stroke:#EABFD5; stroke-width:6"></line>
</pattern>
</defs>
<circle class = "striped-pain-2" cx = "50" cy = "50" r = "40" stroke = "black" stroke-width = "3" fill = "red" />
</svg>
</div>
<div style = "padding:10px;border:solid grey 1px">
Circle 3
<svg height = "100" width = "100">
<style>
/* */
.striped-pain-3 {fill: url(#striped-pain-3);}
/* */
</style>
<defs>
<pattern id = "striped-pain-3" width = "4" height = "1" patternTransform = "rotate(45 0 0)" patternUnits = "userSpaceOnUse">
<line x1 = "0" y1 = "0" x2 = "0" y2 = "2" style = "stroke:#EABFD5; stroke-width:6"></line>
</pattern>
</defs>
<circle class = "striped-pain-3" cx = "50" cy = "50" r = "40" stroke = "black" stroke-width = "3" fill = "red" />
</svg>
</div>
<div style = "padding:10px;">
These circles are SVGs. They have background applied as a pattern. The first two use clases with the same name, but the third not.
Hidding the first SVG affects the second one, but hidding the second does not affect the first.
</div>
</body>
</html>Возможно, вы захотите избавиться от SVG и использовать более простой способ:
function show(id) {
document.getElementById('circle-' + id).style.display = 'block';
}
function hide(id) {
document.getElementById('circle-' + id).style.display = 'none';
}
function reset() {
document.getElementById('circle-1').style.display = 'block';
document.getElementById('circle-2').style.display = 'block';
}#circle-1,
#circle-2,
#circle-3 {
padding: 10px;
border: solid grey 1px
}
.circle {
display: inline-block;
width: 80px;
height: 80px;
margin: 10px;
border: solid 3px #000;
border-radius: 55%;
background: linear-gradient(135deg, #fff 20%, pink 21%, pink 50%, #fff 51%, #fff 71%, pink 72%) 0 0 / 8px 8px;
}
}<div style = "padding:10px">
<input type='button' onclick = "hide(1)" value = "Step 1: Click here to hide first circle. Second will loose style." />
</div>
<div style = "padding:10px">
<input type='button' onclick = "show(1)" value = "Step 2: Click here to show first circle. Second will gain style." />
</div>
<div style = "padding:10px">
<input type='button' onclick = "hide(2)" value = "Step 3: Click here to hide second circle. First is not affected." />
</div>
<div style = "padding:10px">
<input type='button' onclick = "reset()" value = "Step 4: Reset." />
</div>
<div id = "circle-1">Circle 1 <span class = "circle"></span></div>
<div id = "circle-2">Circle 2 <span class = "circle"></span></div>
<div id = "circle-3">Circle 3 <span class = "circle"></span></div>они не используют идентификатор дважды, они дважды ссылаются на один и тот же шаблон, пробой - это шаблоны в div, которые получают стиль "display: none", что делает шаблон несуществующим, поэтому на них нельзя ссылаться в следующем div .
Извините, @Salix, но display: none только делает элемент невидимым для зрителя. Он НЕ удаляется из DOM, поэтому он все еще существует и, следовательно, все еще доступен из JS, CSS, HTML. @Kosh Очень, сделать уникальный идентификатор - правильный путь.
о да, я забыл, что я удалил второй шаблон 'stripped-pain-1' для тестирования, но если вы это сделаете, вы не сможете изменить шаблон из другого кружка div, он должен быть снаружи, что я имел в виду.
Ваша проблема в том, что вы определяете путь SVG с id = "striped-pain-1". Два шага: во-первых, переместите из соединяемых элементов уникальный шаблон SVG для использования в качестве стиля, я использовал "# striped-pain-unique". Затем используйте в качестве URL-адреса для заполнения каждого элемента, который вам нужен.
.striped-pain-1 {fill: url(#striped-pain-unique);}
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href = "' + document.location + '" />');</script>
<link rel = "stylesheet" href = "style.css" />
<script data-require = "[email protected]" src = "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver = "1.5.11"></script>
<script src = "app.js"></script>
<script>
function show(id) {
document.getElementById('circle-' + id).style.display = 'block';
}
function hide(id) {
document.getElementById('circle-' + id).style.display = 'none';
}
function reset() {
document.getElementById('circle-1').style.display = 'block';
document.getElementById('circle-2').style.display = 'block';
}
</script>
</head>
<body ng-controller = "MainCtrl">
<div style = "padding:10px">
<input type='button' onclick = "hide(1)" value = "Step 1: Click here to hide first circle. Second will loose style." />
</div>
<div style = "padding:10px">
<input type='button' onclick = "show(1)" value = "Step 2: Click here to show first circle. Second will gain style." />
</div>
<div style = "padding:10px">
<input type='button' onclick = "hide(2)" value = "Step 3: Click here to hide second circle. First is not affected." />
</div>
<div style = "padding:10px">
<input type='button' onclick = "reset()" value = "Step 4: Reset." />
</div>
<svg height = "100" width = "100">
<defs>
<pattern id = "striped-pain-unique" width = "4" height = "1" patternTransform = "rotate(45 0 0)" patternUnits = "userSpaceOnUse">
<line x1 = "0" y1 = "0" x2 = "0" y2 = "2" style = "stroke:#EABFD5; stroke-width:6"></line>
</pattern>
</defs>
</svg>
<div id = "circle-1" style = "padding:10px;border:solid grey 1px">
Circle 1
<svg height = "100" width = "100">
<style>
/* */
.striped-pain-1 {fill: url(#striped-pain-unique);}
/* */
</style>
<defs>
<pattern id = "striped-pain-1" width = "4" height = "1" patternTransform = "rotate(45 0 0)" patternUnits = "userSpaceOnUse">
<line x1 = "0" y1 = "0" x2 = "0" y2 = "2" style = "stroke:#EABFD5; stroke-width:6"></line>
</pattern>
</defs>
<circle class = "striped-pain-1" cx = "50" cy = "50" r = "40" stroke = "black" stroke-width = "3" fill = "red" />
</svg>
</div>
<div id = "circle-2" style = "padding:10px;border:solid grey 1px">
Circle 2
<svg height = "100" width = "100">
<style>
/* */
.striped-pain-1 {fill: url(#striped-pain-unique);}
/* */
</style>
<defs>
<pattern id = "striped-pain-1" width = "4" height = "1" patternTransform = "rotate(45 0 0)" patternUnits = "userSpaceOnUse">
<line x1 = "0" y1 = "0" x2 = "0" y2 = "2" style = "stroke:#EABFD5; stroke-width:6"></line>
</pattern>
</defs>
<circle class = "striped-pain-1" cx = "50" cy = "50" r = "40" stroke = "black" stroke-width = "3" fill = "red" />
</svg>
</div>
<div style = "padding:10px;border:solid grey 1px">
Circle 3
<svg height = "100" width = "100">
<style>
/* */
.striped-pain-2 {fill: url(#striped-pain-unique);}
/* */
</style>
<defs>
<pattern id = "striped-pain-2" width = "4" height = "1" patternTransform = "rotate(45 0 0)" patternUnits = "userSpaceOnUse">
<line x1 = "0" y1 = "0" x2 = "0" y2 = "2" style = "stroke:#EABFD5; stroke-width:6"></line>
</pattern>
</defs>
<circle class = "striped-pain-2" cx = "50" cy = "50" r = "40" stroke = "black" stroke-width = "3" fill = "red" />
</svg>
</div>
<div style = "padding:10px;">
These circles are SVGs. They have background applied as a pattern. The first two use clases with the same name, but the third not.
Hidding the first SVG affects the second one, but hidding the second does not affect the first.
</div>
</body>
</html>Я забыл добавить: «Объекты, созданные внутри элемента <defs>, не отображаются напрямую», поэтому стили css начинают работать, когда уникальный блок def помещается за пределы toogle div. developer.mozilla.org/en-US/docs/Web/SVG/Element/defs
Итак, вы узнали, что не используйте display: none со ссылками. Вы можете сделать ширину и высоту SVG равными 0, вывести его за пределы экрана, установить видимость: скрыть или другие вещи, чтобы скрыть это без использования display: none