Задать вопрос
@PantyDev

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

Всем привет. Перейду сразу к делу. Решил создать тестовую tilesheet картинку, разрезать её на тайлы и засетать в SVGшку. Создать что-то типа "карты" для игры.
Выглядит картинка вот так:
65b6e3678441e722459642.png
На пустом месте в будущем будут остальные тайлы. Но не суть.
Проблема в следующем, когда я размещаю тайлы и стыкую их впритык, точно попиксельно, то получается вот такое:
65b6e3e31a6f3515824641.png
Проблема в прорезях между ними.
65b6e4551560d936563158.png
Аттрибут 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>
        )

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

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

UPD:
Масштабирование 1920x1080 на общем вьюбоксе. Т.е. пропорция 16/9. Вьюбокс смещен по x y на -960(+32) -540(+32) чтобы центрировать игрока. Также для svg добавил свойство aspect-ratio 16/9 чтобы постоянно поддерживать данную пропорцию.
65b773e281c97083969377.jpeg
Сделал предположение, что необходимо с помощью пропорции изменить высоту для одного тайла. 64 * 1080 / 1920 = 36.
Изменение размеров тайлов на 64x36 не помогло.

UPD2:
Сделал jsfiddle чтобы можно было рассмотреть проблему.

На таком приближении прорези видно на хроме, а вот на фаерфокс, только лишь одна.

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

Пожалуйста, очень надеюсь на вашу помощь!
  • Вопрос задан
  • 191 просмотр
Подписаться 1 Средний 12 комментариев
Решения вопроса 1
sfi0zy
@sfi0zy Куратор тега HTML
Creative frontend developer
Это похоже на известную проблему с рендерингом разных штук в браузерах. Тут два связанных момента - с одной стороны есть вопрос подгонки размеров элементов под пиксельную сетку на экране, и потенциальные ошибки с округлениями значений и "дырками" или "нахлестами" в 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, и они такие же мутные в своих формулировках.

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

Войдите, чтобы написать ответ

Похожие вопросы