Ссылка CSS на фильтр SVG в отдельном элементе

Играя с фильтрами SVG, я столкнулся с проблемой ссылки на фильтр SVG из CSS. В некоторых случаях применение фильтра приводит к удалению элемента, к которому применяется фильтр, со страницы. Я думал, что может быть 2 причины:

  1. тот факт, что я добавлял фильтры динамически, используя D3JS;
  2. тот факт, что я ссылаюсь на фильтры в CSS, определенные в отдельном файле.

Чтобы проверить это, я создал MWE, демонстрирующий проблему. Для меня это отображается в Firefox и Chrome без ничего в левом поле и серым кружком (ожидаемый результат) в правом поле. Это устраняет причину 1, я думаю. После того, как я сделал это, я попытался:

  1. Ссылка с использованием url(.#filter-id), поэтому с ведущей точкой. Это не изменило результат.
  2. Перемещение defs в тот же элемент svg, где находится круг. Это исправляет проблему.

Мой вопрос: можно ли как-то сослаться на фильтр, определенный в отдельном элементе SVG? Я бы очень предпочел сделать это таким образом в своем приложении. Я прочитал, что есть проблемы с внешними файлами, но другой элемент в тот же файл обязательно должен быть возможен?


person Just a student    schedule 23.08.2016    source источник
comment
Вы пытаетесь написать #filter-id в файле CSS. В этом файле нет элемента с идентификатором filter-id, потому что он находится в файле HTML.   -  person Robert Longson    schedule 23.08.2016
comment
Ну да, именно поэтому я попробовал url(.#filter-id), я читал, что это должно выглядеть в файле HTML. Это не так, по крайней мере для меня.   -  person Just a student    schedule 23.08.2016
comment
Тогда вам следует найти материал получше: w3.org/TR/css3- values/#relative-urls Для таблиц стилей CSS базовым URL является URL самой таблицы стилей, а не исходного документа со стилями.   -  person Robert Longson    schedule 23.08.2016
comment
Спасибо за предложение. Я только что перепроверил, но в JSFiddle все равно все встроено, так что ссылка . должна работать, верно?   -  person Just a student    schedule 23.08.2016


Ответы (1)


Я думаю, что проблема в display:none в классе hidden, вы можете использовать другой способ скрытия, например:

svg.hidden {
  height:0;
  margin:0;
  border:none;
}

var svg = d3.select('#container').append('svg'),
    defs = svg.append('defs'),
    dsFilter;

svg.attr('width', 400).attr('height', 200);

dsFilter = defs.append('filter').attr('id', 'grayscale-d3')
dsFilter.append('feColorMatrix')
  .attr('type', 'matrix')
  .attr('values',
        '0.3333 0.3333 0.3333 0 0 ' +
        '0.3333 0.3333 0.3333 0 0 ' +
        '0.3333 0.3333 0.3333 0 0 ' +
        '0      0      0      1 0')

svg.append('text').attr('x', 2).attr('y', 2).text('appended by D3');
svg.append('circle').attr('class', 'd3').attr('cx', 200).attr('cy', 120).attr('r', 60);
body {
  margin: 0;
  font-size: 0;
}

circle {
  fill: #bada55;
  stroke: #000;
  stroke-width: 1px;
}
circle.of {
  filter: url('#grayscale-of');
}
circle.d3 {
  filter: url('#grayscale-d3');
}

svg {
  display: inline-block;
  margin: 1rem 0 0 1rem;
  border: 1px solid #000;
}
svg.hidden {
  height:0;
  margin:0;  
  border:none;
}

text {
  dominant-baseline: text-before-edge;
  font-size: 1rem;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<svg class="hidden">
  <defs>
    <filter id="grayscale-of">
      <feColorMatrix values="0.3333 0.3333 0.3333 0 0
                             0.3333 0.3333 0.3333 0 0
                             0.3333 0.3333 0.3333 0 0
                             0      0      0      1 0"
                     type="matrix">
      </feColorMatrix>
    </filter>
  </defs>
</svg>
<div id="container">
  <svg width="400" height="200">
    <text x="2" y="2">already in page</text>
    <circle class="of" cx="200" cy="120" r="60" />
  </svg>
</div>

person Community    schedule 23.08.2016
comment
Это должно было быть что-то простое! Большое спасибо, я не думаю, что понял бы это... Обновленный Fiddle , если люди ищут его. - person Just a student; 23.08.2016