PerfectVector
Yazan Irene Kim8 dk okuma

SVG sınırlayıcı kutuları: Doğru koordinatları ölçün

Dönüştürülmüş SVG’de getBBox ile getBoundingClientRect’i karşılaştırın. Kaplamaları doğru yerleştirin, kontur sınırlarını test edin ve viewBox’ı açıkça belirlenmiş bir kenar payıyla sığdırın.

Bu sayfada

Bir SVG öğesinin kendi kullanıcı koordinatlarındaki sınırlarına ihtiyacınız olduğunda getBBox() kullanın. Tarayıcının görüntüleme alanına göre CSS piksel cinsinden bir dikdörtgene ihtiyacınız olduğunda getBoundingClientRect() kullanın. Bu sonuçlardan herhangi birini bir kaplamaya veya viewBox değerine kopyalamadan önce hedefin hangi koordinat sistemini kullandığını kontrol edin.

Döndürülmüş bir amblemin yerel kutusu küçük, ekrana hizalanmış kutusu ise çok daha büyük olabilir. Her iki ölçüm de geçerli olabilir. Özellikle konturlar, işaretleyiciler, kırpma veya filtreler söz konusu olduğunda, bunların hiçbirini boyanan her pikseli çevreleyen evrensel bir dikdörtgen olarak görmemelisiniz.

Ölçümü hedefe göre seçin

HedefBaşlangıç ölçümüDikkat edilmesi gereken nokta
Aynı SVG koordinat sisteminin içindeki dikdörtgengetBBox()Dikdörtgene eşleşen dönüşüm bağlamını verin
Sabit konumlu HTML seçim çerçevesigetBoundingClientRect()Görüntüleme alanı koordinatlarında tutun ve yerleşim değiştiğinde güncelleyin
Dönüştürülmüş bir grubu çevreleyen kök SVG viewBox’ıYerel kutu ve bir koordinat dönüşümüSığdırmadan önce kökün kullanıcı birimlerine dönüştürün
Konturları ve efektleri kapsayan kırpmaAyrı olarak doğrulanmış bir sınır belirleme iş akışıTemel geometri kutusunun boyanan her şeyi kapsadığını varsaymayın

MDN’in getBBox() belgesi, yerel geometri sınırlarını ve isteğe bağlı kontur, işaretleyici ve kırpma kontrollerini açıklar. Ölçülen öğenin kendi dönüşümü ve üst öğelerin dönüşümleri bu yerel sonuca dâhil edilmez. Bir grubun alt öğeleri ise grup içindeki yerleşimleriyle birlikte grubun geometrisine katkıda bulunur.

MDN’in getBoundingClientRect() başvuru belgesi, görüntüleme alanına göre koordinatları açıklar. Kaydırma bu koordinat ilişkisini değiştirir. CSS piksel cinsinden bu değerler, otomatik olarak SVG kullanıcı birimleri veya fiziksel baskı boyutları değildir.

Yatay bir ekran dikdörtgeninin içinde, aynı eğime sahip yerel bir dikdörtgenle çevrili eğik bir amblemi gösteren çizim
İki koordinat sistemini gösteren kavramsal çizim. Yerel dikdörtgen çizimin eksenlerini izler; görüntüleme alanı dikdörtgeni ise ekranla hizalı kalır.

Orijinal bir dönüştürülmüş amblemi ölçün

Bu test örneği, dikdörtgen bir açıklığı olan turkuaz bir halka ve ayrı bir altın renkli üçgen içerir. İkisinde de birleşimleri yuvarlak, kalın bir kontur bulunur. Grup ötelenmiş, döndürülmüş ve ölçeklendirilmiştir.

<svg id="scene" width="600" height="300" viewBox="0 0 300 150"
     xmlns="http://www.w3.org/2000/svg" style="overflow:visible">
  <g id="art" transform="translate(100 35) rotate(25) scale(1.2)"
     stroke="#17364c" stroke-width="10" stroke-linejoin="round">
    <path fill="#147d78" fill-rule="evenodd"
          d="M0 0H80V60H0Z M20 20H60V40H20Z" />
    <path fill="#e5a340" d="M100 50L120 10L140 50Z" />
  </g>
</svg>
<script>
  const art = document.querySelector("#art");
  const local = art.getBBox();
  const screen = art.getBoundingClientRect();
</script>

Yerel koordinatlar yatayda 0’dan 140’a, dikeyde ise 0’dan 60’a uzanır. Delik, şeklin iç kısmını etkiler ancak bu dış sınırları küçültmez.

Bu geometriyi Chrome’da açtık ve küçük bir test düzeneğiyle ölçtük. 600 × 300 CSS piksel görüntüleme boyutunda getBBox(), x=0, y=0, width=140, height=60 döndürdü. İstemci dikdörtgeni yaklaşık 365,376 × 272,508 CSS pikseldi. Ekrandaki konumu, SVG’nin sayfada nerede bulunduğuna bağlıydı.

Görüntüleme boyutunu 300 × 150 olarak değiştirdikten sonra yerel kutu 140 × 60 olarak kaldı. İstemci dikdörtgeni yaklaşık 182,688 × 136,254 oldu; önceki boyutların yarısı. Kaynak geometri değişmemişti; sayfaya eşlenme biçimi değişmişti.

Bu sayılar, test edilen tarayıcıdaki bu örneği tanımlar. Tarayıcı motorlarının karşılaştırması veya her düzenleyicinin seçim kutusu için bir belirtim değildir.

Her çerçeveyi kendi koordinat sisteminde çizin

Yerel bir çerçeve için döndürülen koordinatları ve ölçülen grupla aynı dönüşümü kullanın. Bir sonraki ölçümün parçası olmaması için onu aynı düzeyde bir kardeş öğe olarak yerleştirin:

const scene = document.querySelector("#scene");
const box = art.getBBox();
const outline = document.createElementNS("http://www.w3.org/2000/svg", "rect");
for (const key of ["x", "y", "width", "height"]) {
  outline.setAttribute(key, box[key]);
}
outline.setAttribute("transform", art.getAttribute("transform"));
outline.setAttribute("fill", "none");
outline.setAttribute("stroke", "olive");
scene.append(outline);

Çizim ve çerçeve aynı üst öğeyi paylaştığı için bu doğrudan dönüşüm kopyalama işlemi bu örnekte uygundur. Başka bir yere eklenen dikdörtgen için iki koordinat sistemi arasında bir matris eşlemesi gerekir.

HTML çerçevesi için body öğesinin doğrudan altına, sabit konumlandırılmış ve onu kapsayan dönüştürülmüş bir üst öğesi olmayan bir div yerleştirin:

const box = art.getBoundingClientRect();
Object.assign(overlay.style, {
  position: "fixed",
  boxSizing: "border-box",
  pointerEvents: "none",
  border: "2px dashed coral",
  left: `${box.x}px`,
  top: `${box.y}px`,
  width: `${box.width}px`,
  height: `${box.height}px`,
});

Burada overlay, mevcut çerçeve öğenizdir. Kaydırma, yeniden boyutlandırma veya çizimin yerleşimini ya da dönüşümünü değiştirme sırasında yeniden ölçün. Bunun yerine belgeye göre konumlandırma kullanıyorsanız kaydırma farklarını hesaba katın; konumlandırılmış bir kapsayıcı kullanıyorsanız o kapsayıcının koordinat sistemini hesaba katın. Bu yerleştirme kurallarını karıştırmak, aslında doğru olan bir dikdörtgenin kaymış görünmesinin yaygın nedenlerinden biridir.

Test düzeneğimiz her iki çerçeveyi de gösterdi. Yerel dikdörtgen halka ve üçgenle birlikte eğilirken kesikli HTML dikdörtgeninin kenarları yatay ve dikey kaldı. Kalın kontur, geometri çerçevelerinin bazı kısımlarının dışına taştı.

Desteği varsaymak yerine kontur seçeneklerini test edin

Varsayılan yerel kutu kontur genişliğini kapsamaz. MDN, getBBox({ stroke: true }) kullanımını belgeler; ancak seçenekler parametresinin uyumluluğu, uzun süredir kullanılan parametresiz yöntemden ayrı değerlendirilmelidir.

Chrome test örneğimizde { stroke: true } geçirmek, parametresiz çağrıyla aynı 140 × 60 kutuyu döndürdü. 10 birimlik konturu kaldırmak da istemci dikdörtgenini değiştirmedi. Görünür koyu kenarlık belirgin biçimde değiştiği için bu testte iki sonuç da boyanan alanın tamamını temsil etmiyordu.

Bir çağrının hata vermeden seçenekler nesnesi kabul etmesi, seçeneği uyguladığını kanıtlamaya yetmez. Bilinen, konturlu bir şekli test edin ve hedef tarayıcınızda döndürülen boyutları kontrol edin. Nesne, kontur ve işaretleyiciler dâhil edilmiş sınırları ayırt etmek için SVG sınırlayıcı kutu tanımlarını kullanın.

Yarım kontur genişliği kadar pay bırakma kuralını her şekle genellemeyin. Gönye birleşimleri, işaretleyiciler, ölçeklenmeyen konturlar, gölgeler ve filtreler farklı biçimlerde dışarı taşabilir. Kontrolünüzdeki, birleşimleri yuvarlak basit bir test örneği için açıkça belirlenmiş bir kenar payı ve görsel inceleme yeterli olabilir. Otomatik bir dışa aktarma kırpma aracı için bu durumların bilinçli olarak ele alınması gerekir.

Kök viewBox’ı sığdırmadan önce yerel kutuyu dönüştürün

İstemci dikdörtgeninin x, y, width ve height değerlerini asla doğrudan SVG viewBox’ına yapıştırmayın. Bu değerler sayfa konumlandırmasını içerir ve farklı bir birim sistemi kullanır.

Bu test örneğinde yerel kutunun dört köşesini kök SVG’nin kullanıcı koordinatlarına eşleyin. MDN’in getScreenCTM() başvuru belgesi, SVG koordinatlarını belgenin görüntüleme alanına eşlemek için kullanılan matrisi açıklar. Çizim matrisini ters kök matrisiyle birleştirmek, bu ortak ekran eşlemesini ortadan kaldırır:

const box = art.getBBox();
const rootMatrix = scene.getScreenCTM();
const artMatrix = art.getScreenCTM();
if (!rootMatrix || !artMatrix) throw new Error("SVG is not measurable");
 
const toRoot = rootMatrix.inverse().multiply(artMatrix);
const corners = [
  [box.x, box.y],
  [box.x + box.width, box.y],
  [box.x + box.width, box.y + box.height],
  [box.x, box.y + box.height],
].map(([x, y]) => new DOMPoint(x, y).matrixTransform(toRoot));
 
const xs = corners.map(p => p.x);
const ys = corners.map(p => p.y);
const x = Math.min(...xs);
const y = Math.min(...ys);
const width = Math.max(...xs) - x;
const height = Math.max(...ys) - y;
const padding = 12; // Chosen for this simple fixture, in root user units.
scene.setAttribute("viewBox", [
  x - padding, y - padding,
  width + 2 * padding, height + 2 * padding,
].join(" "));

Bu işlem, tersine çevrilebilir iki boyutlu dönüşümlere sahip, görüntülenmiş bir SVG varsayar. Yerel bir dikdörtgenin köşelerini eşlemek, eksenlere hizalı ve güvenli tarafta kalan bir dış çerçeve verir; dönüştürülmüş her eğriyi çevreleyen mümkün olan en sıkı kutuyu vermeyebilir.

Test düzeneği bu kenar payıyla yaklaşık 57.571 23 206.688 160.254 değerinde bir viewBox üretti. Sonucu inceledik ve örneğin yuvarlak konturu görüntüleme alanının içinde kaldı. Sığdırılmış viewBox farklı bir en-boy oranına sahip olduğu için geniş görüntüleme alanının yanlarında hâlâ boşluk vardı; sığdırma, oranları değiştirerek esnetmek anlamına gelmez.

Kırpma yerine bir dönme merkezine ihtiyacınız varsa transform-origin rehberi, referans kutularının dönüşü nasıl etkilediğini açıklar. Fiziksel içe aktarma boyutları için SVG boyutu sorunlarını giderme iş akışını kullanın.

Düzenlemek istediğiniz geometriyi ölçün

Kaynağınız yalnızca PNG veya JPG olarak bulunuyorsa ve düzenlenebilir şekillere ihtiyacınız varsa PerfectVector, ölçümden önce bir SVG elde etmenizi sağlayabilir. Yollarını, açıklıklarını, konturlarını ve varsa korunmuş raster içeriğini inceleyin. Bir sınırlayıcı kutu geometrinin nereye kadar uzandığını söyler; vektörleştirmenin doğru olduğunu veya görünür her ayrıntının düzenlenebilir olduğunu kanıtlamaz.

Mevcut bir SVG doğrudan ölçülebilir. SVG düzenleme rehberi, elinizde gerçekte ne olduğunu belirlemenize yardımcı olur; görsel vektörleştirmeye genel bakış ise önceki dönüştürme adımını açıklar.

Yalnızca raster biçimde bulunan çizimler için kaynağınızı PerfectVector’da deneyin, elde edilen konturları inceleyin, ardından yerleştireceğiniz veya dışa aktaracağınız grubu ölçün. Sonucu teslim edilecek kırpma olarak kabul etmeden önce bir kenar payı bırakın ve son görünür kenarları kontrol edin.

Sık sorulan sorular

İki yöntem neden farklı genişlikler döndürüyor? Farklı koordinat sistemleri kullanırlar. Yerel SVG kutusu geometriyi kullanıcı birimleriyle tanımlar; istemci dikdörtgeni ise sayfaya eşleme sonrasında görüntüleme alanına göre sınırlarını CSS pikselleriyle tanımlar. Ölçeklendirme ve döndürme bu boyutları değiştirebilir.

Sınırlayıcı kutu, çizimde delik olup olmadığını söyler mi? Hayır. Bir dikdörtgen iç topolojiyi değil, dış sınırları kaydeder. Dolu bir dikdörtgen ile aynı dış kenarlara sahip bir halka aynı sınırlayıcı kutuya sahip olabilir. Açıklıkları kontrol etmek için yolları ve dolgu kurallarını inceleyin.

İstemci dikdörtgenini viewBox olarak kullanabilir miyim? Doğrudan kullanamazsınız. Önce ilgili geometriyi kök SVG’nin kullanıcı koordinatlarına dönüştürün. Ekran konumu ve CSS piksel boyutları, kaynak koordinatlarındaki bir dikdörtgene kopyalanmamalıdır.

Kaynaklar

  1. MDN getBBox — Yerel SVG sınırlarını ve isteğe bağlı ölçüm kontrollerini tanımlar.
  2. MDN getBoundingClientRect — Görüntüleme alanına göre dikdörtgenleri ve kaydırmayı açıklar.
  3. SVG bounding-box definitions — Nesne, kontur ve işaretleyiciler dâhil edilmiş geometri sınırlarını birbirinden ayırır.
  4. MDN getScreenCTM — SVG ve görüntüleme alanı koordinatlarını ilişkilendirmek için kullanılan matrisi belgeler.

Bloga daha fazlası

Düzenlemesi daha kolay,
daha temiz bir SVG ile başlayın