Обложка изображения SVG независимо от размера/ориентации

#svg

Вопрос:

Ожидайте, что встроенный фрагмент кода ниже создаст экран, подобный изображению в Firefox, и т. Д. Два отсоединенных изображения показаны внизу для справки — одно пейзажное и одно портретное. Выше приведены четыре демонстрационные формы, которые я хочу покрыть изображениями, на самом деле ничего не зная об изображении — в идеале я мог бы заменить только URL-адреса и получить все «правильные» изображения, избегая какой-либо математики или условий.

Шаблоны и изображения должны быть идентичными, а не соответствовать демонстрационным сценариям. В конечном итоге мне нужна всего ОДНА такая форма в шаблоне svg, удовлетворяющая любому введенному изображению.

Я думаю, что я определенно хочу xMidYMid и рисунка, и изображения. Я перепробовал множество перестановок атрибутов viewBox, heights, width, slice / meet , patternContentUnits и patternUnits.

Я даже не могу понять, до чего масштабируются «неправильные» изображения. Похоже, что две демо-версии каждого изображения имеют точно такой же масштаб (потому что все демонстрационные прямоугольники имеют длину 490 в длинном направлении, и это похоже на то, что короткая сторона изображения сопоставляется с длинной стороной прямой или что-то в этом роде??)

введите описание изображения здесь

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg viewBox="0 0 1020 1220" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <pattern
       id="patternA"
       height="1"
       width="1"
       viewBox="0 0 1 1"
       patternContentUnits="objectBoundingBox"
       preserveAspectRatio="xMidYMid slice">
        <image
            id="imageA"
            width="1" height="1"
            preserveAspectRatio="xMidYMid slice"
            transform=""
            xlink:href="https://images.unsplash.com/photo-1625507371147-797709a083a6?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8amp;amp;ixlib=rb-1.2.1amp;amp;auto=formatamp;amp;fit=cropamp;amp;w=334amp;amp;q=80" />
    </pattern>
    <pattern
       id="patternB"
       height="1"
       width="1"
       viewBox="0 0 1 1"
       patternContentUnits="objectBoundingBox"
       preserveAspectRatio="xMidYMid slice">
        <image
            id="imageB"
            width="1" height="1"
            preserveAspectRatio="xMidYMid slice"
            transform=""
            xlink:href="https://images.unsplash.com/photo-1625508200971-f63b282addb8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8amp;amp;ixlib=rb-1.2.1amp;amp;auto=formatamp;amp;fit=cropamp;amp;w=1189amp;amp;q=80" />
    </pattern>
    <pattern
       id="patternC"
       height="1"
       width="1"
       viewBox="0 0 1 1"
       patternContentUnits="objectBoundingBox"
       preserveAspectRatio="xMidYMid meet">
        <image
            id="imageC"
            width="1" height="1"
            preserveAspectRatio="xMidYMid meet"
            transform=""
            xlink:href="https://images.unsplash.com/photo-1625507371147-797709a083a6?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8amp;amp;ixlib=rb-1.2.1amp;amp;auto=formatamp;amp;fit=cropamp;amp;w=334amp;amp;q=80" />
    </pattern>
    <pattern
       id="patternD"
       height="1"
       width="1"
       viewBox="0 0 1 1"
       patternContentUnits="objectBoundingBox"
       preserveAspectRatio="xMidYMid meet">
        <image
            id="imageD"
            width="1" height="1"
            preserveAspectRatio="xMidYMid meet"
            transform=""
            xlink:href="https://images.unsplash.com/photo-1625508200971-f63b282addb8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8amp;amp;ixlib=rb-1.2.1amp;amp;auto=formatamp;amp;fit=cropamp;amp;w=1189amp;amp;q=80" />
    </pattern>
  </defs>
  <rect
     style="fill:url(#patternA);stroke:black;"
     x="10"
     y="10"
     width="490"
     height="200" />
  <rect
     style="fill:url(#patternB);stroke:blue;"
     x="510"
     y="10"
     width="500"
     height="200" />
  <rect
     style="fill:url(#patternA);stroke:red;"
     x="160"
     y="220"
     width="200"
     height="490" />
  <rect
     style="fill:url(#patternB);stroke:green;"
     x="670"
     y="220"
     width="200"
     height="490" />
  <rect
     style="fill:url(#patternC);stroke:black;"
     x="10"
     y="720"
     width="490"
     height="490" />
  <rect
     style="fill:url(#patternD);stroke:black;"
     x="510"
     y="720"
     width="490"
     height="490" />
</svg> 

Вместо этого «неправильные» демонстрации должны быть такими, чтобы изображение в основном начиналось с 0x0 в центре и увеличивалось только до тех пор, пока изображение точно не покроет прямоугольник, но не далее:

введите описание изображения здесь

Здесь есть похожие вопросы, так что я уже использовал их, чтобы зайти так далеко.

Комментарии:

1. И вы должны использовать шаблон, верно? Он будет использоваться поверх непрямоугольных фигур?

2. да, он будет использоваться на произвольном пути с помощью ограничивающего прямоугольника — я предполагал, что ответ будет легко применить, но об этом было бы проще спросить.

3. Конечно, просто подтвердите, что вернуться к простому делу <изображение> невозможно.

Ответ №1:

Я не думаю, что то, чего ты хочешь, невозможно сделать. Для того чтобы изображение было правильно масштабировано в соответствии с формой с помощью meet или slice , необходимо знать размер изображения.

В ваших первоначальных попытках там нет ничего, что дало бы визуализатору какое-либо представление о фактических размерах изображений. Или даже каковы их пропорции.

Например

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg viewBox="0 0 1020 1220" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>

    <pattern
       id="patternA"
       height="1"
       width="1"
       viewBox="0 0 3977 5965"
       patternContentUnits="objectBoundingBox"
       preserveAspectRatio="xMidYMid slice">
        <image
            id="imageA"
            width="3977" height="5965"
            xlink:href="https://images.unsplash.com/photo-1625507371147-797709a083a6?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8amp;amp;ixlib=rb-1.2.1amp;amp;auto=formatamp;amp;fit=cropamp;amp;w=334amp;amp;q=80" />
    </pattern>
    
    <pattern
       id="patternB"
       height="1"
       width="1"
       viewBox="0 0 3941 2217"
       patternContentUnits="objectBoundingBox"
       preserveAspectRatio="xMidYMid slice">
        <image
            id="imageB"
            width="3941" height="2217"
            xlink:href="https://images.unsplash.com/photo-1625508200971-f63b282addb8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8amp;amp;ixlib=rb-1.2.1amp;amp;auto=formatamp;amp;fit=cropamp;amp;w=1189amp;amp;q=80" />
    </pattern>
    
  </defs>
  <rect
     style="fill:url(#patternA);stroke:black;"
     x="10"
     y="10"
     width="490"
     height="200" />
  <rect
     style="fill:url(#patternB);stroke:blue;"
     x="510"
     y="10"
     width="500"
     height="200" />
  <rect
     style="fill:url(#patternA);stroke:red;"
     x="160"
     y="220"
     width="200"
     height="490" />
  <rect
     style="fill:url(#patternB);stroke:green;"
     x="670"
     y="220"
     width="200"
     height="490" />
  <rect
     style="fill:url(#patternA);stroke:black;"
     x="10"
     y="720"
     width="490"
     height="490" />
  <rect
     style="fill:url(#patternB);stroke:black;"
     x="510"
     y="720"
     width="490"
     height="490" />
</svg> 

Комментарии:

1. «размер изображения должен быть известен», браузер, безусловно, знает это, иначе как бы preserveAspectRatio он работал с <изображением>? Дело в том, что размер целевого элемента должен передаваться <изображению> через <изображение><шаблон>, и я не уверен, что это можно сделать…

2. Я имел в виду, что если операция использует функцию сохранения на изображении, то информация об исходных границах изображения будет потеряна, и они не получат правильный/желаемый результат в шаблоне. Это потому, что в этот момент изображение фактически представляет собой «квадрат 1×1 с изображением где-то внутри».

3. Но почему это квадрат 1×1, а не прямая 490×200, которую сейчас должен определять шаблон? Они установили элементы Patterncontent для сопоставления с целевым элементом (ну, на самом деле они сделали это с помощью viewBox, но в любом случае все заканчивается одинаково), поэтому, в моем понимании, width=»1″ должна быть полной шириной целевого элемента (490 единиц), а height=»1″ должна быть полной высотой (200 единорогов). Что заставляет распространение размера останавливаться где-то посередине?

4. Спасибо. Если я установлю высоту и ширину изображения рисунка прямой кишки и поле просмотра рисунка прямой кишки на значения, соответствующие соотношению сторон прямой кишки, то я получу желаемое поведение. Это неоптимально, потому что это означает предварительное вычисление ограничивающей рамки моей цели, но в моем случае это может сработать. До сих пор вы помогали мне видеть, что квадрат 1×1 изображения эффективно обрезает его до покрывающего квадрата, затем шаблон масштабирует этот квадрат, чтобы покрыть прямую линию, объясняя эффект масштабирования, который мне не понравился.

5. Но почему это квадрат ? При objectBoundingBox этом единица измерения должна быть относительно размера цели, так что 1-это как CSS 100%, если хотите. Так почему же в контексте неквадратичной цели 1×1 (т. е. 100% х 100%) является квадратом?