iOS/macOS Mail в темном режиме инвертирует цвета маски SVG, что приводит к изменению поведения маскирования
У меня есть изображение SVG, которое использует маскирование, чтобы вырезать отверстие в другой форме. Я упростил сложные формы, связанные с этим репрезентативным примером:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
<defs>
<mask id="mask">
<rect x="0" y="0" width="256" height="256" fill="#ffffff" />
<circle cx="128" cy="128" r="32" fill="#000000" />
</mask>
</defs>
<circle mask="url(#mask)" cx="128" cy="128" r="64" fill="#ff0000" />
</svg>
Это работает, как и ожидалось, т. е. рисует следующую форму пончика практически в любом контексте:
Однако, если я встраиваю SVG в электронное письмо и просматриваю его в macOS Mail (16.0, входит в состав Monterey 12.3.1) или iOS Mail при включенном темном режиме, я получаю эту своеобразную версию:
Похоже, что эти два приложения пытаются угадать интерпретацию SVG в темном режиме и ошибочно изменили маску на очень темно-серый (#232323
, если бы мне пришлось угадывать, какой цвет фона самого приложения в темном режиме) и#000000
на , тем самым в основном, но не полностью инвертируя поведение маскирования.
Это похоже на ошибку в Mail. Есть ли способ сказать Mail, чтобы он не связывался с цветами, определенными в маске? Я пробовал пару обходных путей, но их было недостаточно:
- с использованием
prefers-color-scheme
чтобы определить цвета маски, чтобы я мог «предварительно инвертировать» ее для темного режима, который работает здесь, но ломает изображение в любом другом контексте - скрывает окраску маски настолько, что не пытается ее инвертировать (например, с помощью
linear-gradient(#ffffff,#ffffff)
вместо того, чтобы просто#ffffff
), который просто ломает изображения везде
2 ответа
Работая над предложением ccprog, я заставил этот SVG работать, как и ожидалось:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
<defs>
<mask id="mask" mask-type="alpha">
<path
d="
M 0 0
L 256 0
L 256 256
L 0 256
L 0 0
M 128 96
a 32 32 180 1 1 0 64
a 32 32 180 1 1 0 -64
z
"
fill-rule="evenodd"
/>
</mask>
</defs>
<circle mask="url(#mask)" cx="128" cy="128" r="64" fill="#ff0000" />
</svg>
Помимо перехода наmask-type
(чтобы мы маскировали то, что iOS/macOS Mail не попытается инвертировать), маску пришлось переопределить. В частности, он должен был заполнить все, что не входит в круг, используяfill-rule="evenodd"
чтобы он заполнил нужные области. Я не мог просто переключить существующие фигуры на использование непрозрачности, потому чтоcircle
хотелось бы иметь непрозрачность 0 (чтобы указать, что круг должен быть вырезан) иrect
будет проходить за ним с непрозрачностью 1, что сделает маску недействующей.
Новый путь маски, если он отображается черным цветом на белом фоне, выглядит следующим образом:
Вы также можете упростить свой SVG, используя составной путь.
«Вырезанная» область определяется вспомогательным путем с противоположным направлением пути.
В твоем случае:
// outer circle - clockwise
M 128 64
a 64 64 0 0 1 0 128
a 64 64 0 0 1 0 -128
z
// innercircle - counter clockwise
M 128 96
a 32 32 180 1 0 0 64
a 32 32 180 1 0 0 -64
z
Вы также можете сделать это наоборот: против часовой стрелки для внешней формы, по часовой стрелке для внутренней.
Таким образом, вам не нужно никаких дополнительныхfill-rule
- даже менее способные приложения, такие как средства просмотра изображений, могут безупречно отображать эти svg.
Эта концепция (отсечение путем чередования направлений траектории) фактически существует с самых первых технологий рисования Безье (например, постскриптум).
Вы можете создавать составные контуры в любом векторном редакторе (например, Adobe Illustrator, inkscape и т. д.), применяя операции с контурами, такие как вычитание/извлечение.
Дополнительная литература: порядок намотки правила заполнения