Предотвратить перекрывающиеся друг с другом фигуры с альфа-каналом?
Рассмотрим SVG с двумя частично перекрывающимися кругами, оба с fill="currentColor"
, Я не контролирую значение текущего цвета, оно может быть установлено на что-либо с помощью кода, который я не могу контролировать.
Я хочу, чтобы вся фигура имела одинаковый сплошной цвет. Это прекрасно работает, если изображения имеют, например, color: red
, Однако, когда у текущего цвета есть альфа-канал, часть, где круги перекрываются, становится темнее.
Я хочу избежать этого. По сути, я хотел бы, чтобы первое изображение выглядело как второе в этом примере:
<svg viewBox="0 0 10 10" style="color: rgba(0,0,0,50%); width: 100px;">
<circle cx="3" cy="5" r="3" fill="currentColor"></circle>
<circle cx="7" cy="5" r="3" fill="currentColor"></circle>
</svg>
<svg viewBox="0 0 10 10" style="color: rgb(50%,50%,50%); width: 100px;">
<circle cx="3" cy="5" r="3" fill="currentColor"></circle>
<circle cx="7" cy="5" r="3" fill="currentColor"></circle>
</svg>
Возможно ли это сделать, возможно, используя режим наложения?
2 ответа
Простой способ достичь желаемого - просто превратить круги в обтравочный контур.
<svg viewBox="0 0 10 10" style="color: rgba(0,0,0,50%); width: 100px;">
<defs>
<clipPath id="myClip">
<circle cx="3" cy="5" r="3"></circle>
<circle cx="7" cy="5" r="3"></circle>
</clipPath>
</defs>
<rect width="100%" height="100%" fill="currentColor" clip-path="url(#myClip)"/>
</svg>
Если ваша цель состоит в том, чтобы просто переместить цвет до полной непрозрачности, это может быть достигнуто с помощью относительно простого фильтра:
<svg viewBox="0 0 10 10" style="color: rgba(0,0,0,50%); width: 100px;">
<filter id="filter">
<feComponentTransfer in="SourceGraphic">
<feFuncA type="linear" slope="100"/>
</feComponentTransfer>
</filter>
<circle cx="3" cy="5" r="3" fill="currentColor" style="filter:url(#filter)"></circle>
<circle cx="7" cy="5" r="3" fill="currentColor" style="filter:url(#filter)"></circle>
</svg>
<svg viewBox="0 0 10 10" style="color: rgb(50%,50%,50%); width: 100px;">
<circle cx="3" cy="5" r="3" fill="currentColor"></circle>
<circle cx="7" cy="5" r="3" fill="currentColor"></circle>
</svg>
Если, как вы описали, вы хотите эмулировать эффект прозрачности на цветном фоне, это немного сложнее, и результат на самом деле не идеален.
Ниже добавлен белый фон отдельно за контуром каждого цветного объекта.
Обратите внимание на два свойства:
color-interpolation-filters:sRGB
необходим для правильного добавления цвета- без
shape-rendering:crispEdges
Вы получите некоторые артефакты, где объекты перекрываются. Но установка этого требует цены: вы теряете сглаживание везде. В зависимости от используемой формы, это может быть вполне заметно.
<svg viewBox="0 0 10 10" style="color: rgba(0,0,0,50%); width: 100px; shape-rendering:crispEdges">
<filter id="filter" style="color-interpolation-filters:sRGB">
<feFlood flood-color="#fff" flood-opacity="1" result="bg" />
<feComponentTransfer in="SourceGraphic" result="opaque">
<feFuncA type="linear" slope="100"/>
</feComponentTransfer>
<feComposite in="bg" in2="opaque" operator="in" result="combine" />
<feComposite in="SourceGraphic" in2="combine" operator="atop" />
</filter>
<circle cx="3" cy="5" r="3" fill="currentColor" style="filter:url(#filter)"></circle>
<circle cx="7" cy="5" r="3" fill="currentColor" style="filter:url(#filter)"></circle>
</svg>
<svg viewBox="0 0 10 10" style="color: rgb(50%,50%,50%); width: 100px;">
<circle cx="3" cy="5" r="3" fill="currentColor"></circle>
<circle cx="7" cy="5" r="3" fill="currentColor"></circle>
</svg>