ฉันต้องการแสดง<text>
สิ่งที่จะตัดบรรทัดอัตโนมัติไปยังคอนเทนเนอร์ใน SVG <rect>
เช่นเดียวกับข้อความ HTML ที่เติม<div>
องค์ประกอบ มีวิธีทำไหม ฉันไม่ต้องการวางตำแหน่งเส้นแบบกระจัดกระจายโดยใช้<tspan>
s
ฉันต้องการแสดง<text>
สิ่งที่จะตัดบรรทัดอัตโนมัติไปยังคอนเทนเนอร์ใน SVG <rect>
เช่นเดียวกับข้อความ HTML ที่เติม<div>
องค์ประกอบ มีวิธีทำไหม ฉันไม่ต้องการวางตำแหน่งเส้นแบบกระจัดกระจายโดยใช้<tspan>
s
คำตอบ:
การตัดข้อความไม่ได้เป็นส่วนหนึ่งของ SVG1.1 ซึ่งเป็นข้อมูลจำเพาะที่ใช้งานอยู่ในปัจจุบัน คุณควรใช้ HTML ผ่าน<foreignObject/>
องค์ประกอบ
<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>
นี่เป็นทางเลือก:
<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 อาจได้รับการรายงานว่าได้รับการสนับสนุนด้วย featurestring นั้น แต่ก็ไม่มีการรับประกันว่า HTML จะสามารถแสดงได้เนื่องจากข้อกำหนด SVG 1.1 นั้นไม่จำเป็น ไม่มี featurestring สำหรับการสนับสนุน html-in-Foreignobject ในขณะนี้ อย่างไรก็ตามยังคงได้รับการสนับสนุนในเบราว์เซอร์จำนวนมากดังนั้นจึงมีแนวโน้มที่จะจำเป็นในอนาคตซึ่งอาจจะมีสตริงคุณลักษณะที่เกี่ยวข้อง
โปรดทราบว่าองค์ประกอบ "textArea"ใน SVG Tiny 1.2 รองรับคุณสมบัติ svg มาตรฐานทั้งหมดเช่นการเติมขั้นสูงเป็นต้นและคุณสามารถระบุความกว้างหรือความสูงเป็นแบบอัตโนมัติซึ่งหมายความว่าข้อความสามารถไหลไปในทิศทางนั้นได้อย่างอิสระ ForeignObject ทำหน้าที่ตัดวิวพอร์ต
หมายเหตุ:แม้ว่าตัวอย่างข้างต้นจะเป็นเนื้อหา SVG 1.1 ที่ถูกต้อง แต่ใน SVG 2 แอตทริบิวต์ "requiredFeatures" ได้ถูกลบออกซึ่งหมายความว่าองค์ประกอบ "switch" จะพยายามแสดงผลองค์ประกอบ "g" แรกโดยไม่คำนึงถึงการรองรับ SVG 1.2 "textArea 'องค์ประกอบ. ดูSVG2 ข้อมูลจำเพาะองค์ประกอบสวิทช์
xhtml:div
แทนdiv
แต่นั่นอาจเป็นเพราะ d3.js ฉันไม่พบข้อมูลอ้างอิงที่เป็นประโยชน์เกี่ยวกับ TextFlow มี (ยัง) อยู่หรือเป็นเพียงร่างบางส่วน?
textPath อาจดีสำหรับบางกรณี
<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>
จากรหัสของ @Mike Gledhill ฉันได้ก้าวไปอีกขั้นและเพิ่มพารามิเตอร์เพิ่มเติม หากคุณมี SVG RECT และต้องการให้ข้อความอยู่ภายในสิ่งนี้อาจเป็นประโยชน์:
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
};
boxwidth = parseInt(boxObject.getAttribute('width'))
ยอมรับความกว้างเป็นพิกเซลในขณะที่boxwidth = parseInt(boxObject.getBBox().width)
ยอมรับหน่วยการวัดประเภทใดก็ได้
ฟังก์ชันนี้สามารถเพิ่มได้โดยใช้ JavaScript Carto.net มีตัวอย่าง:
http://old.carto.net/papers/svg/textFlow/
สิ่งอื่นที่อาจเป็นประโยชน์สำหรับคุณคือพื้นที่ข้อความที่แก้ไขได้:
รหัสต่อไปนี้ใช้งานได้ดี เรียกใช้ข้อมูลโค้ดว่ามันทำอะไร
บางทีมันอาจจะล้างหรือทำให้มันทำงานกับแท็กข้อความทั้งหมดใน SVG ได้โดยอัตโนมัติ
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>
ฉันได้โพสต์คำแนะนำต่อไปนี้สำหรับการเพิ่มการตัดคำปลอมลงในองค์ประกอบ "ข้อความ" ของ SVG ที่นี่:
คุณเพียงแค่ต้องเพิ่มฟังก์ชัน JavaScript ธรรมดาซึ่งจะแยกสตริงของคุณออกเป็นองค์ประกอบ "tspan" ที่สั้นกว่า นี่คือตัวอย่างของลักษณะ:
หวังว่านี่จะช่วยได้!