Bir SVG use örneğinin çevresindeki beklenmeyen boşluğu gidermek için bunun kaynak viewBox değerinden mi, en-boy oranına göre sığdırmadan mı, yoksa çevresindeki CSS satır kutusundan mı kaynaklandığını belirleyin. Bu kılavuz, yerleşim koordinatlarının öngörülebilir kalmasını sağlarken her nedeni nasıl teşhis edip düzelteceğinizi gösterir.

Görev, küçük bir masaüstü web sayfası düzenlemesidir: yeniden kullanılabilir bir şekli SVG içinde hassas biçimde konumlandırın, ardından çevresindeki HTML düzeninin amaçlandığı gibi sığmasını sağlayın. Örnekleri Mac'inizdeki düz metin düzenleyicisinde izleyebilir ve kaydedilmiş HTML dosyasını güncel bir masaüstü tarayıcısında açabilirsiniz.

Boşluğu hangi koordinat sistemi belirliyor?

İncelenmesi gereken üç sınır vardır: dış SVG öğesinin CSS kutusu, başvurulan bir simge için kullanılan görünüm alanı ve bu simgenin içindeki gerçek şekil. W3C, SVG görünüm alanı ile tarayıcının CSS görünüm alanını açıkça birbirinden ayırır. Bir viewBox, SVG kullanıcı koordinatlarını bir SVG görünüm alanına eşler; tarayıcı penceresini tanımlamaz. Koordinat Sistemleri, Dönüşümler ve Birimler — SVG 2

Örneğin, bir use öğesindeki x="20", SVG koordinat sisteminde bir ofset sağlar. Bu, tarayıcı penceresinin sol kenarından 20 CSS piksel anlamına gelmez. Ölçekleme ve üst öğe dönüşümleri, bu ofsetin sayfada nerede görüneceğini değiştirebilir. SVG belirtimi, use konumlandırmasını, CSS kutu düzeninden farklı davranan ek bir öteleme olarak tanımlar. Belge Yapısı — SVG 2

Bu karar tablosuyla başlayın. Bu tablo, birbirinin yerine kullanılabilecek düzeltmeler listesi değil, belgelenmiş düzen mekanizmalarından türetilmiş bir teşhis sırasıdır.

Gözlem Önce neyi incelemeli Olası düzeltme
SVG'nin tamamının altında dar bir şerit Satır içi biçimlendirme ve üst öğenin satır yüksekliği Tek başına kullanılan SVG'yi blok düzeyine alın veya satır içi hizalamasını ayarlayın
Tekrarlanan her grafiğin içinde boşluk Şekil koordinatları ile simgenin viewBox değeri İç boşluk istenmiyorsa kaynak sınırlarını daraltın
Bir simge örneğinin iki yanında fazla boşluk Örnek boyutları ile viewBox oranı Oranları eşleştirin veya bilinçli bir sığdırma ilkesi seçin
Yerel konum doğru, ancak sayfadaki konum yanlış SVG kullanıcı birimleri ile tarayıcı görünüm alanı koordinatları x ve y değerlerini atamadan önce koordinatları dönüştürün
Örnek boyutlarını değiştirmek hiçbir şeyi etkilemiyor href tarafından hedeflenen öğe Sığdırma için görünüm alanı tanımlayan bir simge kullanın veya geometriyi dönüştürün

Boşluğu eksiksiz bir yerel örnekle yeniden oluşturma

Aşağıdaki eksiksiz belgeyi düz metin düzenleyicisinde svg-spacing.html adıyla kaydedin, ardından tarayıcınızda açın. Belge, kitaplık veya harici dosya kullanmadan yalnızca sentetik etiketler ve dikdörtgenlerden oluşur. Açık renkli dikdörtgenler amaçlanan örnek görünüm alanlarını, koyu dikdörtgenler ise yeniden kullanılan çizimi gösterir.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>SVG spacing example</title>
  <style>
    body {
      margin: 24px;
      font: 16px system-ui, sans-serif;
    }
    #canvas {
      display: block;
      width: 320px;
      height: 200px;
      outline: 1px solid #687580;
      background: #fff;
    }
    .viewport-guide { fill: #e4edf2; }
    .artwork { fill: #356b8c; }
    text { fill: #253744; font-size: 14px; }
  </style>
</head>
<body>
  <p>Two instances with different source bounds and fitting dimensions.</p>
  <svg id="canvas" xmlns="http://www.w3.org/2000/svg"
       width="320" height="200" viewBox="0 0 320 200"
       role="img" aria-labelledby="drawing-title">
    <title id="drawing-title">Padded and tightly fitted rectangles</title>
    <defs>
      <symbol id="padded" viewBox="0 0 100 100">
        <rect id="source-shape" class="artwork"
              x="20" y="20" width="60" height="60" />
      </symbol>
      <symbol id="tight" viewBox="20 20 60 60">
        <rect class="artwork"
              x="20" y="20" width="60" height="60" />
      </symbol>
    </defs>

    <rect class="viewport-guide"
          x="20" y="20" width="120" height="60" />
    <use href="#padded" x="20" y="20" width="120" height="60" />
    <text x="160" y="55">Padded source</text>

    <rect class="viewport-guide"
          x="20" y="110" width="60" height="60" />
    <use id="tight-instance" href="#tight"
         x="20" y="110" width="60" height="60" />
    <text x="110" y="145">Tight source</text>
  </svg>
</body>
</html>

Her iki örneğin boyutları açıkça ayarlanmıştır. Böylece boşluğu incelerken örtük boyutlandırmaya güvenmek gerekmez. MDN, use öğesini başvurulan SVG içeriğini yeniden kullanmak için tanımlar ve hedef, viewBox değerine sahip bir SVG veya simge olduğunda width ile height değerlerinin sığdırmayı etkilediğini belirtir. Örnekte güncel href özniteliği kullanılır. MDN: use

İlk dikdörtgenin gerçekte nerede başladığını hesaplama

İlk kaynakta 100'e 100 boyutlarında bir viewBox vardır, ancak dikdörtgen her iki yönde de yalnızca 20 ile 80 arasındaki koordinatları kaplar. İstenen örnek görünüm alanı 120'ye 60 boyutundadır. Varsayılan xMidYMid meet sığdırmasıyla ölçek, 120 / 100 ve 60 / 100 değerlerinden küçük olanıdır: 0.6. Ölçeklenmiş viewBox 60'a 60 yer kaplar ve yatayda her iki yanda 30 birim boşluk bırakır. Bu sonuç, W3C'nin görünüm alanı dönüşümü algoritmasından çıkar. SVG 2: SVG görünüm alanının eşdeğer dönüşümünü hesaplama

Bu örnek girdiler için boyalı dikdörtgen yatayda 20 + 30 + 20 × 0.6 = 62, dikeyde 20 + 20 × 0.6 = 32 konumunda başlar. Boyutu her yönde 60 × 0.6 = 36 olur. Aritmetik, küçük ve deterministik bir hesaplamayla kontrol edilmiştir; bunlar tarayıcı testinden alınmış ölçümler değil, hesaplanmış değerlerdir.

İkinci örnekte birbirinden bağımsız iki girdi değiştirilir: kaynak sınırları 20 20 60 60 olur ve örnek görünüm alanı 60'a 60 olarak ayarlanır. Böylece dikdörtgen bu görünüm alanını doldurur ve (20, 110) SVG koordinatında başlar. Nedenleri kendiniz ayırmak için her seferinde yalnızca tek bir girdiyi değiştirin.

Örneğin içindeki boşluğu nasıl giderirsiniz?

Kaynak sınırlarındaki istenmeyen boşluğu düzeltme

Bir viewBox dört sayı içerir: minimum x, minimum y, genişlik ve yükseklik. Başlangıç noktasının sıfır olması gerekmez. Örnekte viewBox="20 20 60 60", geometrisini yeniden yazmadan dikdörtgenin mevcut sınırlarını tanımlar. MDN: viewBox

Gerçek bir grafiğin sınırlarını daraltmadan önce iç boşluğun kasıtlı olup olmadığına karar verin. Yeniden kullanılabilir şekillerden oluşan bir küme, görsel boyutlarının ve konumlarının tutarlı kalması için ortak bir koordinat çerçevesini paylaşabilir. Her simgenin sınırlarını ayrı ayrı daraltmak bu ilişkileri değiştirebilir. Bu tutarlılık tasarımın bir parçasıysa ortak sınırları koruyun.

Geometriyi incelemek için getBBox(), SVG kullanıcı koordinatlarındaki sınırları bildirir. Varsayılan olarak konturları ve işaretleyicileri dışarıda bırakır; hedef öğeye veya üst öğelerine uygulanan dönüşümleri hesaba katmaz. Bu nedenle, yalnızca dolguya dayalı bir sınırlayıcı kutu; konturlu veya dönüştürülmüş çizimi kırpmak için yeterli kanıt değildir. MDN: SVGGraphicsElement getBBox()

Eşleşmeyen en-boy oranlarının nasıl sığdırılacağını seçme

Kare bir kaynak geniş bir görünüm alanına sığdırıldığında, sınırları sıkı belirlenmiş çizimin çevresinde bile boşluk kalabilir. İstenen sonuca göre bir ilke seçin. İç sığdırma için preserveAspectRatio özniteliğini başvurulan simgeye, dış koordinat eşlemesini incelerken ise dış SVG'ye uygulayın. MDN: preserveAspectRatio

Seçenek Sonuç ve koşul
Kaynak ve görünüm alanı oranlarının eşleşmesi Oranları korurken en-boy oranına göre sığdırmadan kaynaklanan boşluğu önler
xMidYMid meet Tüm viewBox'ı ortalanmış olarak gösterir; oranlar eşleşmiyorsa boşluk bırakır
xMinYMin meet Sığdırılmış viewBox'ı sol üst tarafa taşır; kalan boşluk yine vardır
none Tekdüze olmayan ölçeklendirmeye izin verir; kare bir şekil dikdörtgene dönüşebilir
xMidYMid slice Görünüm alanını kaplar, ancak kaynak içeriğin bir kısmı bunun dışına taşar; görünürlüğü kırpma belirler

Hizalamayı değiştirmek, sığdırmadan kaynaklanan boşluğu taşır; kaynak geometriye zaten işlenmiş bir iç boşluğu gidermez. Benzer şekilde, tüm kaynak içeriğin görünüm alanında kalması gerekiyorsa slice uygun değildir. Bu ayrımlar, MDN'nin hizalama, meet, slice ve tekdüze olmayan sığdırma tanımlarına dayanır. MDN: preserveAspectRatio

Boyutlar etkisiz göründüğünde başvurulan hedefi denetleme

Düz bir grup veya yol, use öğesi buna başvuruyor diye sığdırma görünüm alanı kazanmaz. W3C, başvurulan öğe yeni bir görünüm alanı oluşturmadığında örnek width ve height değerlerinin etkisiz olduğunu belirtir. Örnek başına öngörülebilir sığdırma için yeniden kullanılabilir geometriyi, yukarıdaki gibi açık sınırları olan bir simgenin içine yerleştirin. Doğrudan geometrik ölçeklendirme için dönüşüm kullanın ve bunun konumlandırmaya etkisini hesaba katın. SVG 2: Yeniden kullanılan grafiklerin düzeni

Dış SVG'nin altındaki şeridi nasıl giderirsiniz?

SVG'nin dışındaki bir boşluk, HTML satır içi biçimlendirmesinden kaynaklanabilir. WHATWG, SVG'nin ifade içeriği içinde kullanılmasına izin verir; dolayısıyla çevredeki sayfa onu metnin yanında yerleştirebilir. CSS satır kutuları, temel çizginin üstündeki ve altındaki yazı tipi ölçülerini içerir; bu nedenle satır içi bir grafik, kutusunun altında görünür boşluk bırakabilir. HTML Standardı: SVG, CSS 2: Satır yüksekliği hesaplamaları

Eksiksiz örnek, #canvas için zaten display: block ayarını kullanır; böylece SVG satır içi satır kutusuna katılmaz. Tek başına kullanılan bir çizim için bu kuralı koruyun. Mekanizmayı incelemek için bunu geçici olarak display: inline olarak değiştirin ve çevresindeki satıra bakın.

Bir SVG'nin metnin yanında kalması gerekiyorsa dış SVG üzerinde vertical-align: bottom değerini deneyin ve metin hizalamasını kontrol edin. Bu özellik, satır içi düzeydeki bir kutuyu satırın içinde hizalar; simge sınırlarını veya iç sığdırmayı değiştirmez. Diğer içerikler ve üst öğenin satır yüksekliği satırın toplam yüksekliğini belirlemeye devam edebilir. MDN: vertical-align

Bu CSS bildirimlerini, her örneğe eklenecek birikimli düzeltmeler olarak değil, dış SVG için alternatifler olarak değerlendirin:

/* Standalone drawing */
#canvas {
  display: block;
}

/* Alternative when the drawing must stay inline */
/*
#canvas {
  display: inline;
  vertical-align: bottom;
}
*/

Koordinatlarınız tarayıcı görünüm alanından geliyorsa ne yapmalısınız?

getBoundingClientRect(), bir öğenin tarayıcı görünüm alanına göre konumunu CSS pikselleriyle bildirir. Sayfa kaydırıldıkça konumu değişir. Bu değerler SVG kullanıcı koordinatlarından farklı bir uzayda yer alır; bu yüzden left ve top değerlerini doğrudan bir örneğin x ve y değerlerine kopyalamak genellikle yanlıştır. MDN: Element getBoundingClientRect()

Girdi bir tarayıcı görünüm alanı noktasıysa koordinat dönüşümü kullanın. getScreenCTM(), SVG dönüşüm matrisini sağlar ve bunun tersi uygulandığında nokta seçilen öğenin yerel koordinatlarına dönüştürülür. Bir noktanın matrixTransform() yöntemi bu dönüşümü gerçekleştirir. MDN: getScreenCTM(), MDN: matrixTransform()

Aşağıdaki konsol kodu, yukarıdaki eksiksiz belgeye isteğe bağlı bir ektir. (100, 150) tarayıcı görünüm alanı noktasını dış SVG'nin kullanıcı koordinatlarına dönüştürür ve sınırları sıkı belirlenmiş örneği bu noktaya taşır. Örneğin dönüştürülmemiş örneğinin doğrudan bu SVG'nin alt öğesi olarak kaldığını varsayar.

(() => {
  const canvas = document.getElementById("canvas");
  const instance = document.getElementById("tight-instance");
  if (!canvas || !instance) {
    throw new Error("Open the complete SVG spacing example first.");
  }

  const matrix = canvas.getScreenCTM();
  if (!matrix) {
    throw new Error("The SVG coordinate matrix is unavailable.");
  }

  const viewportPoint = new DOMPoint(100, 150);
  const localPoint = viewportPoint.matrixTransform(matrix.inverse());
  if (!Number.isFinite(localPoint.x) || !Number.isFinite(localPoint.y)) {
    throw new Error("The SVG coordinate matrix cannot be inverted.");
  }

  instance.setAttribute("x", String(localPoint.x));
  instance.setAttribute("y", String(localPoint.y));
})();

Sonlu sayı denetimi önemlidir; çünkü terslenemeyen bir matris NaN bileşenleri üretir. Düzen veya kaydırma değişikliklerinden sonra yeni bir noktayı dönüştürürken matrisi yeniden hesaplayın. Örneğiniz dönüştürülmüş bir grubun içindeyse, dönüşümü bunun yerine üst grubun koordinat sistemine yapın. Bu kod, API belgelerine göre incelenmiştir; araştırma sırasında tarayıcıda çalıştırılmamıştır. MDN: DOMMatrixReadOnly inverse()

Üç sınırı ayrı ayrı denetleyerek işi tamamlayın: dış SVG kutusu, simgenin sığdırılmış görünüm alanı ve çizimin kendi sınırları. İstenmeyen boşluğu oluşturan sınırı düzeltin, ardından sonucu amaçlanan sayfa boyutunda doğrulayın. Böylece açıklanmamış bir boşluğu keyfî ofsetlerle telafi etmeden öngörülebilir konumlandırma elde edersiniz.

Kaynaklar