Обработка тайлов на SVG. Видны прорези между ними, что делать?

Ссылка скопирована
27 февраля 2026 1 ответ

Всем привет. Перейду сразу к делу. Решил создать тестовую tilesheet картинку, разрезать её на тайлы и засетать в SVGшку. Создать что-то типа "карты" для игры.
Выглядит картинка вот так:

Обработка тайлов на SVG. Видны прорези между ними, что делать?

На пустом месте в будущем будут остальные тайлы. Но не суть.
Проблема в следующем, когда я размещаю тайлы и стыкую их впритык, точно попиксельно, то получается вот такое:

Обработка тайлов на SVG. Видны прорези между ними, что делать?

Проблема в прорезях между ними.

Обработка тайлов на SVG. Видны прорези между ними, что делать?

Аттрибут shape-rendering="crispEdges" помог справится с такой же проблемой когда я ставил так черные векторные rectы, их тоже видно на картинке выше (угол из чёрных ректов). Для данного случая, как видно на картинке, я попытался засетать свойство для тэга image
image-rendering: pixelated;
Вроде, это немного улучшило их вид, но всё равно прорези остались. В реакте это выглядит примерно вот так (если конечно это вам необходимо):

return (             <g key={index}>                 {new Array(posY).fill(null).map((_, y) => {                     return new Array(posX).fill(null).map((_, x) => {                         const add = y > 0 ? y * posX : 0                         const currentTileId = matrix[x + add] || 0                         return (                             <svg                                  x={x * cell.x}                                  y={y * cell.y}                                 width={cell.x}                                 height={cell.y}                                 data-tile={currentTileId}                                 viewBox={`${(currentTileId * 64)} ${0} ${cell.x} ${cell.y}`}                             >                                 <image                                      style={{ imageRendering: "pixelated" }}                                     href={image}                                 />                             </svg>                         )                     })                 })}             </g>         )

return ( <g key={index}> {new Array(posY).fill(null).map((_, y) => { return new Array(posX).fill(null).map((_, x) => { const add = y > 0 ? y * posX : 0 const currentTileId = matrix[x + add] || 0 return ( <svg x={x * cell.x} y={y * cell.y} width={cell.x} height={cell.y} data-tile={currentTileId} viewBox={`${(currentTileId * 64)} ${0} ${cell.x} ${cell.y}`} > <image style={{ imageRendering: "pixelated" }} href={image} /> </svg> ) }) })} </g> )

Учтите, код ещё крайне сырой, например тайлы по оси Y на тайлшите еще не считываются на viewBox, и там стоит просто 0, а я лишь решаю проблемы по мере их поступления.

В общем вопрос тот же: можно ли хоть как-то избавиться от этих прорезей? Читал, что это возможно связано с сглаживанием на картинках. Возможно стоит попробовать какие-то альтернативные методы вставки тайлов в svg? Canvas не рассматриваем, слишком много нужно переделать.

UPD:
Масштабирование 1920x1080 на общем вьюбоксе. Т.е. пропорция 16/9. Вьюбокс смещен по x y на -960(+32) -540(+32) чтобы центрировать игрока. Также для svg добавил свойство aspect-ratio 16/9 чтобы постоянно поддерживать данную пропорцию.

Обработка тайлов на SVG. Видны прорези между ними, что делать?

Сделал предположение, что необходимо с помощью пропорции изменить высоту для одного тайла. 64 * 1080 / 1920 = 36.
Изменение размеров тайлов на 64x36 не помогло.

UPD2:
Сделал jsfiddle чтобы можно было рассмотреть проблему.
snippet
На таком приближении прорези видно на хроме, а вот на фаерфокс, только лишь одна.

UPD3:
Сделал еще один jsfiddle, приблизил и сместил немного игрока, чтобы можно было рассмотреть проблему.
snippet
Пожалуйста, очень надеюсь на вашу помощь!

Дополнительно:

А попробуйте использовать rect, а не image. Ещё можно сделать svg стэк, и использовать через use.

  • я стыки вижу, когда в illustrator рисую (собственно поэтому и не рисую). Как миллионы делают логотипы в нём - я не понимаю...
  • Такая беда обычно если размеры блоков не кратны 2. Из-за неправильного масштабирования может появиться дробное число в размерах объекта. Если появляется дробное число, то и отрисовываться будет с зазором. Размеры у вас указаны кратными 2, это хорошо. Теперь разберитесь с масштабированием и всё должно у вас заработать.
  • Александр, к сожалению мне нужен именно image, так как я использую растровое изображение в качестве tilesheet. Там дальше будет условно говоря пиксельная растровая текстура травы, например.
    По поводу use, укажите пример кода пожалуйста, что вы имели ввиду.
  • Pisiholog, масштабирование 1920x1080 на общем вьюбоксе. Т.е. пропорция 16/9. Смещена по x y на -960(+32) -540(+32) чтобы центрировать игрока. Также для svg добавил свойство aspect-ratio 16/9 чтобы постоянно поддерживать данную пропорцию

    Обработка тайлов на SVG. Видны прорези между ними, что делать?

  • PantyDev, вот тут несколько статей:
    SVG stacking for reduce page load time & request count
    Stack — спрайт здорового человека
    SVG-стеки
  • Александр, да, вот теперь до меня дошло что это такое. Я уже использовал специальные модули на ноде, которые через галп собирали sprite.svg. Я не думаю что это всё же относится к теме, так как думаю нет разницы между использованием image внутри SVG и ссылкой на id тайла с image в этом стеке.
  • у вас в коде svg стоит атрибут который всё равно не будет работать для этого тега - можете убрать его
    <g class="map" shape-rendering="crispEdges">
  • Максим, да, я тоже читал что он работает только на rect, circle и подобном, но я добавил на g и удивительно, но он работает для внутренних векторных тэгов rect, circle и т.п., влияет только на векторную графику, к сожалению! (а мне нужно чтобы он также работал на растр, в данном случае)
    При использовании тэга:

    Обработка тайлов на SVG. Видны прорези между ними, что делать?

    Без использования:

    Обработка тайлов на SVG. Видны прорези между ними, что делать?

  • PantyDev, в вашем случае эти кубики надо собирать в одном svg
  • Максим,

    в вашем случае эти кубики надо собирать в одном svg

    Вы имеете вложенность svg? От неё ничего не зависит. + это вполне позволимо. Я убирал обёртку svg и резал тайлы через clipPath - это не помогло.

  • PantyDev, я не знаю реакт,вью и прочее..
    Но в свг чуточку понимаю..
    Проблема у вас в коде
  • Это похоже на известную проблему с рендерингом разных штук в браузерах. Тут два связанных момента - с одной стороны есть вопрос подгонки размеров элементов под пиксельную сетку на экране, и потенциальные ошибки с округлениями значений и "дырками" или "нахлестами" в 1px между сущностями на экране, а с другой - собственно сглаживание, когда у нас появляются промежуточные цвета, смягчающие переходы от одних к другим. Иногда, как в таких ситуациях, мы можем воспринимать их как неуместные.

    С размерами мы еще можем попытаться что-то сделать. Например распространенный костыль состоит в том, чтобы по возможности иметь размеры элементов в целом количестве пикселей. Т.е. не давать браузеру округлять на свой вкус. А вот сглаживание мы не можем выключить просто так. Вы нашли атрибут shape-rendering, но если внимательно почитать в стандарте, что он предполагает, то там будут исключительно рекомендательные высказывания:

    the user agent might turn off anti-aliasing

    или

    might adjust line positions and line widths to align edges with device pixels

    Но "might" не означает "must". На практике сглаживание или не отключается полностью, или отключается, но границы по пикселям смещаются так, что становится еще хуже, чем было, или еще какая фигня происходит. В разных браузерах все по-разному и поведение немного меняется со временем, так что старые костыли могут переставать работать. В CSS есть свойства, связанные со словом rendering, и они такие же мутные в своих формулировках.

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

    • иметь размеры элементов в целом количестве пикселей. Т.е. не давать браузеру округлять на свой вкус.

      Ну, я вроде так и сделал :(
      Можете глянуть jsfiddle'ы - вьюбокс главного оборачивающего всё это дело SVG тэга - подпадает под 16/9 пропорции с целыми пиксельными значениями. Сдвиг и размеры каждого тайла тоже целые.
      Я ещё немного пошаманю, и если не получится, похоже действительно придется всё это дело переносить на канвас.

    • PantyDev,

      Ну, я вроде так и сделал

      Там контекст всего текста в том, что есть два связанных момента. Один решить можно, хоть и костыльно, а второй - нет. Вы может быть и решили половину задачи, которая теоретически поддается решению, но вторую половину в текущих реалиях браузерного разнообразия нельзя решить.

    Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Дмитрий К. Ответ

    Для того чтобы устранить прорези между тайлами на SVG, можно использовать несколько методов:

    1. Использование атрибута shape-rendering="crispEdges" для элементов . Этот атрибут указывает браузеру рисовать границы элементов без сглаживания, что поможет устранить прорези между тайлами.

    ```php

     

    ```

    2. Использование атрибута vector-effect="non-scaling-stroke" для элементов . Этот атрибут указывает браузеру не масштабировать обводку элемента, что также поможет избежать прорезей между тайлами.

    ```php

     

    ```

    3. Использование атрибута shape-rendering="optimizeSpeed" для элемента . Этот атрибут указывает браузеру оптимизировать отрисовку SVG для повышения производительности, что также может помочь устранить прорези между тайлами.

    ```php

     
       <!-- Ваши тайлы SVG -->

    <!-- Ваши тайлы SVG -->

    ```

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

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно