SVG metninde otomatik satır kaydırma


108

HTML metninin öğeleri doldurmasıyla aynı şekilde <text>kapsayıcıya otomatik satır kaydırmanın ne olacağını SVG'de görüntülemek istiyorum . Bunu yapmanın bir yolu var mı? S kullanarak çizgileri seyrek olarak konumlandırmak istemiyorum .<rect><div><tspan>

Yanıtlar:


89

Metin sarma, şu anda uygulanan spesifikasyon olan SVG1.1'in bir parçası değildir. <foreignObject/>Öğe aracılığıyla HTML kullanmayı tercih etmelisiniz .

<svg ...>

<switch>
<foreignObject x="20" y="90" width="150" height="200">
<p xmlns="http://www.w3.org/1999/xhtml">Text goes here</p>
</foreignObject>

<text x="20" y="20">Your SVG viewer cannot display html.</text>
</switch>

</svg>

5
Switch'i kullanmanın yanlış yolu bu, svg spesifikasyonunda tanımlanan özelliklerden birini kullanması gerekiyor. Yedek asla örneğinizde kullanılmayacaktır. Bkz. W3.org/TR/SVG11/feature.html ve w3.org/TR/SVG11/struct.html#SwitchElement .
Erik Dahlström

22
Ayrıca <foreignObject />, IE'de desteklenmemektedir
Doug Amos

3
Ancak, tüm motorların foreignObjects oluşturamayacağını unutmayın. Özellikle batik yapmaz.
hrabinowitz

69

İşte bir alternatif:

<svg ...>
  <switch>
    <g requiredFeatures="http://www.w3.org/Graphics/SVG/feature/1.2/#TextFlow">
      <textArea width="200" height="auto">
       Text goes here
      </textArea>
    </g>
    <foreignObject width="200" height="200" 
     requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
      <p xmlns="http://www.w3.org/1999/xhtml">Text goes here</p>
    </foreignObject>
    <text x="20" y="20">No automatic linewrapping.</text>
  </switch>
</svg>

ForeignObject öğesinin bu özellik dizisiyle desteklendiği bildirilse bile, SVG 1.1 belirtimi tarafından gerekli olmadığı için HTML'nin görüntülenebileceğine dair hiçbir garanti bulunmadığına dikkat edin. Şu anda html-in-foreignobject desteği için bir özellik yok. Bununla birlikte, birçok tarayıcıda hala desteklenmektedir, bu nedenle gelecekte muhtemelen uygun bir özellik ile gerekli hale gelecektir.

Not o 'textarea' elemanı SVG Tiny 1.2 desteklerin tüm standart svg özellikleri, örneğin gelişmiş vb doldurma ve metin bu yönde serbestçe akabilir, yani ya otomatik olarak genişlik ve yükseklikte belirtebildiklerinden. ForeignObject, kırpma görünüm alanı olarak işlev görür.

Not: Yukarıdaki örnek geçerli SVG 1.1 içeriği olsa da, SVG 2'de "requiredFeatures" özelliği kaldırılmıştır, bu, "switch" öğesinin SVG 1.2 'textArea desteğine sahip olup olmadığına bakılmaksızın ilk "g" öğesini oluşturmaya çalışacağı anlamına gelir. ' elementler. SVG2 anahtar öğesi özelliklerine bakın .


1
Bu kodu FF'de test ediyordum, tarayıcı bana textArea öğesini veya foreignObject alt öğesini göstermedi. Ardından, belirtimi okuduktan sonra, requiredFeatures özniteliğinin, listesi yanlış olarak değerlendirildiğinde, requiredFeatures özniteliğine sahip öğe ve alt öğeleri işlenmeyecek şekilde davrandığını buldu. Dolayısıyla, anahtar elemanına herhangi bir ihtiyaç olmayacaktır. Anahtar öğesini kaldırdıktan sonra, foreignObject çocukları göründü (çünkü tarayıcım (FF, 8.01) svg1.1'i destekliyor). Bu yüzden burada anahtar elemanına gerek olmadığını düşünüyorum. Lütfen bana haber ver.
Rajkamal subramanian

Şimdi bir <g> öğesi kullanmak için güncellendi. Svg spesifikasyonu, izleyicilere bilinmeyen öğeler üzerinde 'requiredFeatures'a bakmalarını söylemedi, bu nedenle amaçlandığı gibi çalışması için bilinen bir svg elemanının kullanılması gerekir.
Erik Dahlström

Teşekkürler! Bunun xhtml:divyerine kullanmam gerekiyordu div, ancak bunun nedeni d3.js olabilir. TextFlow hakkında yararlı bir referans bulamadım, (hala) var mı yoksa sadece bir taslakta mıydı?
johndodo

2
Metin alanının ileriye dönük olarak desteklenmediği unutulmamalıdır bugzilla.mozilla.org/show_bug.cgi?id=413360
George Mauer

1
Örnek, Chrome'da çalışmıyor. Diğer tarayıcılarda test etmediniz.
posfan12

15

TextPath bazı durumlarda iyi olabilir.

<svg width="200" height="200"
    xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <defs>
  <!-- define lines for text lies on -->
  <path id="path1" d="M10,30 H190 M10,60 H190 M10,90 H190 M10,120 H190"></path>
 </defs>
 <use xlink:href="#path1" x="0" y="35" stroke="blue" stroke-width="1" />
 <text transform="translate(0,35)" fill="red" font-size="20">
  <textPath xlink:href="#path1">This is a long long long text ......</textPath>
 </text>
</svg>

3
Yalnızca sözcüğün ortasına kaydırmanın (ve tireleme değil) kabul edilebilir olduğu durumlarda. Sanat projelerinin ötesinde sorun olmayan pek çok durum düşünemiyorum. http://jsfiddle.net/nilloc/vL3zj/
Nilloc

4
@Nilloc Herkes İngilizce kullanmaz, bu yöntem Çince, Japonca veya Korece için tamamen uygundur.
Zang MingJie

Karakter tabanlı (logografik) diller için @ZangMingJie Sarma, kelimeleri bölmekten tamamen farklı bir kullanım durumu gibi görünüyor. Tüm romantik / latin / kiril / arapça (fonografik) dillerinde önemli olan bu benim açımdan buydu.
Nilloc

11

@Mike Gledhill'in koduna dayanarak, bunu bir adım daha ileri götürdüm ve daha fazla parametre ekledim. Bir SVG RECT'iniz varsa ve metnin içine sarılmasını istiyorsanız, bu kullanışlı olabilir:

function wraptorect(textnode, boxObject, padding, linePadding) {

    var x_pos = parseInt(boxObject.getAttribute('x')),
    y_pos = parseInt(boxObject.getAttribute('y')),
    boxwidth = parseInt(boxObject.getAttribute('width')),
    fz = parseInt(window.getComputedStyle(textnode)['font-size']);  // We use this to calculate dy for each TSPAN.

    var line_height = fz + linePadding;

// Clone the original text node to store and display the final wrapping text.

   var wrapping = textnode.cloneNode(false);        // False means any TSPANs in the textnode will be discarded
   wrapping.setAttributeNS(null, 'x', x_pos + padding);
   wrapping.setAttributeNS(null, 'y', y_pos + padding);

// Make a copy of this node and hide it to progressively draw, measure and calculate line breaks.

   var testing = wrapping.cloneNode(false);
   testing.setAttributeNS(null, 'visibility', 'hidden');  // Comment this out to debug

   var testingTSPAN = document.createElementNS(null, 'tspan');
   var testingTEXTNODE = document.createTextNode(textnode.textContent);
   testingTSPAN.appendChild(testingTEXTNODE);

   testing.appendChild(testingTSPAN);
   var tester = document.getElementsByTagName('svg')[0].appendChild(testing);

   var words = textnode.textContent.split(" ");
   var line = line2 = "";
   var linecounter = 0;
   var testwidth;

   for (var n = 0; n < words.length; n++) {

      line2 = line + words[n] + " ";
      testing.textContent = line2;
      testwidth = testing.getBBox().width;

      if ((testwidth + 2*padding) > boxwidth) {

        testingTSPAN = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
        testingTSPAN.setAttributeNS(null, 'x', x_pos + padding);
        testingTSPAN.setAttributeNS(null, 'dy', line_height);

        testingTEXTNODE = document.createTextNode(line);
        testingTSPAN.appendChild(testingTEXTNODE);
        wrapping.appendChild(testingTSPAN);

        line = words[n] + " ";
        linecounter++;
      }
      else {
        line = line2;
      }
    }

    var testingTSPAN = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
    testingTSPAN.setAttributeNS(null, 'x', x_pos + padding);
    testingTSPAN.setAttributeNS(null, 'dy', line_height);

    var testingTEXTNODE = document.createTextNode(line);
    testingTSPAN.appendChild(testingTEXTNODE);

    wrapping.appendChild(testingTSPAN);

    testing.parentNode.removeChild(testing);
    textnode.parentNode.replaceChild(wrapping,textnode);

    return linecounter;
}

document.getElementById('original').onmouseover = function () {

    var container = document.getElementById('destination');
    var numberoflines = wraptorect(this,container,20,1);
    console.log(numberoflines);  // In case you need it

};

Teşekkürler. Chrome'da mükemmel çalışır. Ancak firefox'ta çalışmıyor. Demo bağlantısında yazıyor. Beklenmeyen değer NaN ayrıştırma dy özelliği. svgtext_clean2.htm: 117 etrafta bir iş bulmaya çalışıyor.
akshayb

Daha sonra Firefox'ta çalıştırdım. İşte
MSC

1
(Şu anda ENTER'a çok erken bastım.) Daha sonra Firefox ve IE'de çalıştırdım. Biraz yardıma ihtiyacınız varsa, democra.me/wrap_8_may_2014.htm adresine bir göz atın . Kodda Firefox hakkında bir yorum var.
MSC

Gördüğünüz gibi, sınırlayıcı kutuyu yukarı veya aşağı küçültmek veya doğru yerde bir üç nokta ile kısaltmak için kodu çok genişlettim.
MSC

MSC kodundaki bir satırı değiştirirdim: boxwidth = parseInt(boxObject.getAttribute('width'))sadece piksel olarak genişliği kabul eder, ancak boxwidth = parseInt(boxObject.getBBox().width)her tür ölçü birimini kabul ederdi
Massimiliano Caniparoli


7

Aşağıdaki kod iyi çalışıyor. Kod parçacığını ne yaptığını çalıştırın.

Belki temizlenebilir veya SVG'deki tüm metin etiketleriyle otomatik olarak çalışmasını sağlayabilir.

function svg_textMultiline() {

  var x = 0;
  var y = 20;
  var width = 360;
  var lineHeight = 10;
  
  

  /* get the text */
  var element = document.getElementById('test');
  var text = element.innerHTML;

  /* split the words into array */
  var words = text.split(' ');
  var line = '';

  /* Make a tspan for testing */
  element.innerHTML = '<tspan id="PROCESSING">busy</tspan >';

  for (var n = 0; n < words.length; n++) {
    var testLine = line + words[n] + ' ';
    var testElem = document.getElementById('PROCESSING');
    /*  Add line in testElement */
    testElem.innerHTML = testLine;
    /* Messure textElement */
    var metrics = testElem.getBoundingClientRect();
    testWidth = metrics.width;

    if (testWidth > width && n > 0) {
      element.innerHTML += '<tspan x="0" dy="' + y + '">' + line + '</tspan>';
      line = words[n] + ' ';
    } else {
      line = testLine;
    }
  }
  
  element.innerHTML += '<tspan x="0" dy="' + y + '">' + line + '</tspan>';
  document.getElementById("PROCESSING").remove();
  
}


svg_textMultiline();
body {
  font-family: arial;
  font-size: 20px;
}
svg {
  background: #dfdfdf;
  border:1px solid #aaa;
}
svg text {
  fill: blue;
  stroke: red;
  stroke-width: 0.3;
  stroke-linejoin: round;
  stroke-linecap: round;
}
<svg height="300" width="500" xmlns="http://www.w3.org/2000/svg" version="1.1">

  <text id="test" y="0">GIETEN - Het college van Aa en Hunze is in de fout gegaan met het weigeren van een zorgproject in het failliete hotel Braams in Gieten. Dat stelt de PvdA-fractie in een brief aan het college. De partij wil opheldering over de kwestie en heeft schriftelijke
    vragen ingediend. Verkeerde route De PvdA vindt dat de gemeenteraad eerst gepolst had moeten worden, voordat het college het plan afwees. "Volgens ons is de verkeerde route gekozen", zegt PvdA-raadslid Henk Santes.</text>

</svg>


1
SVG metninde otomatik satır kaydırma :) Javascript kodum, metin uzun olduğunda satırlar oluşturur. SVG'nin içindeki tüm metin etiketleri üzerinde çalışırsam iyi olur. javascript'te id = "" değiştirilmeden otomatik. Kötü SVG, kendi başına çoklu hatlara sahip değildir.
Peter

Güzel çözüm, ama bunu ortaya hizalayabilir misin?
Krešimir Galić

Cevap tbh kabul edilmelidir. Javascript çözümü yeterince minimal ve mantıklı.
Zac

4

Burada bir SVG "metin" öğesine bazı sahte kelime kaydırma eklemek için aşağıdaki izlenecek yolu yayınladım:

SVG Word Wrap - Durdurucu gösterilsin mi?

Yalnızca dizenizi daha kısa "tspan" öğelerine bölen basit bir JavaScript işlevi eklemeniz gerekir. İşte nasıl göründüğüne dair bir örnek:

Örnek SVG

Bu yardımcı olur umarım !

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.