Anonymous
Текст SVG, созданный Javascript, отображается в DOM, но не отображается.
Сообщение
Anonymous » 04 янв 2026, 15:42
Следующий код создает ползунок с левым, средним и правым маркерами. При нажатии на среднюю ручку появляется прямоугольник, который должен быть меню. Код перебирает два массива для заполнения меню. Используя F12 (в Firefox 138.0–64bit), я вижу на вкладке инспектора, что текстовые элементы были созданы с правильным содержимым, но ничего не появляется, и при выборе строки в инспекторе обычно отображается ограничивающая рамка для выбранной строки. Ничего для этих текстовых элементов, которые на первый взгляд имеют тот же синтаксис, что и другой отображаемый текст.
Код: Выделить всё
//https://github.com/amitonline/true-ruler/blob/main/js/true-ruler.js
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
const control_W = 550; //width of slider
const control_H = 350; //Height of slider
const left_padding = 75;
const right_padding = 75;
const top_padding = 25;
const bottom_padding = 25;
const pillRad = 10;
const pillOpacity = 50;
const diamondSide = Math.sqrt(2 * (Math.pow(pillRad, 2))); //make the diamond the same height as the circle handles (pythagorus)
const labelOffset = 75;
const PDDheight = 120;
const PDDwidth = 75;
const PDDrad = 2;
svg.setAttribute("id", "sliderControl");
svg.setAttribute("overflow", "visible");
svg.setAttribute("viewBox", "0 0 " + control_W + " " + control_H);
svg.setAttribute("width", control_W);
svg.setAttribute("height", control_H);
svg.setAttribute("onload", "makeDraggable(evt)");
var svgNS = svg.namespaceURI;
var slider = document.createElementNS(svgNS, 'path');
slider.setAttributeNS(null, "d", "M " + left_padding + "," + (top_padding + (control_H / 2)) + " H " + (control_W - right_padding));
slider.setAttribute("id", "slider");
slider.setAttribute("stroke", "silver");
slider.setAttribute("stroke-width", "5");
slider.setAttribute("opacity", "1");
slider.setAttribute("fill", "none");
svg.appendChild(slider);
const startPill = document.createElementNS(svgNS, "circle");
startPill.setAttribute("class", "draggable");
startPill.setAttribute("id", "startPill");
startPill.setAttribute("cx", left_padding);
startPill.setAttribute("cy", (top_padding + (control_H / 2)));
startPill.setAttribute("r", pillRad);
startPill.setAttribute("fill", "#55aaff");
startPill.setAttribute("opacity", pillOpacity + "%");
//startPill.setAttribute("cursor", "move");
svg.appendChild(startPill);
const periodPill = document.createElementNS(svgNS, "rect");
periodPill.setAttribute("class", "draggable");
periodPill.setAttribute("id", "period");
periodPill.setAttribute("x", -diamondSide / 2);
periodPill.setAttribute("y", -diamondSide / 2);
periodPill.setAttribute("width", diamondSide);
periodPill.setAttribute("height", diamondSide);
periodPill.setAttribute("transform", "translate(" + (control_W / 2) + ", " + (top_padding + (control_H / 2)) + ") rotate(45)");
periodPill.setAttribute("fill", "#55aaff");
periodPill.setAttribute("opacity", pillOpacity + "%");
periodPill.addEventListener("click", function() { //don't keep recreating the menu if one already exists
if (document.getElementById("periodDD") == null) {
var menu = createPeriodDD();
}
});
svg.appendChild(periodPill);
const endPill = document.createElementNS(svgNS, "circle");
endPill.setAttribute("class", "draggable");
endPill.setAttribute("id", "endPill");
endPill.setAttribute("cx", (control_W - right_padding));
endPill.setAttribute("cy", (top_padding + (control_H / 2)));
endPill.setAttribute("r", pillRad);
endPill.setAttribute("fill", "#55aaff");
endPill.setAttribute("opacity", pillOpacity + "%");
//endPill.setAttribute("cursor", "move");
svg.appendChild(endPill);
const startLabel = document.createElementNS(svgNS, "text");
startLabel.setAttribute("class", "ibm-plex-sans-labelText");
startLabel.setAttribute("y", labelOffset);
startLabel.setAttribute("text-anchor", "left");
startLabel.textContent = "Start time";
startLabel.setAttribute("x", left_padding - (measureTextWidth(startLabel.textContent)) / 2);
svg.appendChild(startLabel);
const periodLabel = document.createElementNS(svgNS, "text");
periodLabel.setAttribute("class", "ibm-plex-sans-labelText");
periodLabel.setAttribute("y", labelOffset);
periodLabel.setAttribute("text-anchor", "center");
periodLabel.textContent = "Period";
periodLabel.setAttribute("x", (control_W / 2) - (measureTextWidth(periodLabel.textContent)) / 2);
svg.appendChild(periodLabel);
const endLabel = document.createElementNS(svgNS, "text");
endLabel.setAttribute("class", "ibm-plex-sans-labelText");
endLabel.setAttribute("y", labelOffset);
endLabel.setAttribute("text-anchor", "right");
endLabel.textContent = "End time";
endLabel.setAttribute("x", (control_W - right_padding) - (measureTextWidth(endLabel.textContent)) / 2);
svg.appendChild(endLabel);
function measureTextWidth(text) {
const testDiv = document.getElementById("Test");
testDiv.innerText = text; // Set the text to measure
// Measure width after rendering
const width = testDiv.clientWidth;
return width;
}
function createPeriodDD() {
const P = [100, 1, 1, 1, 1, 7]; //enumerated values
const U = ["ms", "sec", "min", "hour", "day", "days"]; //units for values
const periodDD = document.createElementNS(svgNS, "rect");
periodDD.setAttribute("class", "menuRect");
periodDD.setAttribute("id", "periodDD");
periodDD.setAttribute("x", ((control_W / 2) - (PDDwidth / 2)));
periodDD.setAttribute("y", (top_padding + (control_H / 2) + bottom_padding));
periodDD.setAttribute("width", PDDwidth);
periodDD.setAttribute("height", PDDheight);
periodDD.setAttribute("rx", PDDrad);
periodDD.setAttribute("ry", PDDrad);
var i = 0;
var menuitem = [];
P.forEach(element => {
menuitem[i] = document.createElementNS(svgNS, "text");
menuitem[i].setAttribute("class", "ibm-plex-sans-menuitem");
menuitem[i].setAttribute("text-anchor", "left");
menuitem[i].setAttribute("y", i * 10);
menuitem[i].textContent = P[i] + " " + U[i];
menuitem[i].setAttribute("x", "10");
periodDD.appendChild(menuitem[i]);
i += 1;
});
svg.appendChild(periodDD);
}
function makeDraggable(evt) {
var obj = evt.target;
obj.addEventListener('contextmenu', contextMenu);
obj.addEventListener('menu', menu);
obj.addEventListener('mousedown', startDrag);
obj.addEventListener('mousemove', drag);
obj.addEventListener('mouseup', endDrag);
obj.addEventListener('mouseleave', endDrag);
var selectedElement, offset, transform;
function contextMenu(evt) {
alert("context menu");
}
function menu(evt) {
alert("menu");
}
function startDrag(evt) {
if (evt.target.classList.contains('draggable')) {
selectedElement = evt.target;
console.log(selectedElement.id)
}
}
function drag(evt) { //NB for this appliocation no dragging happens - the start or end time (or both) change at a rate that fits with the period but the pills remain static
if (selectedElement) {
console.log(selectedElement.id);
evt.preventDefault();
var x = parseFloat(selectedElement.getAttributeNS(null, "x"));
selectedElement.setAttributeNS(null, "x", x + 0.1);
}
}
function endDrag(evt) {
selectedElement = null;
}
}
document.body.appendChild(svg);
Код: Выделить всё
.ibm-plex-sans-labelText {
font-family: "IBM Plex Sans", sans-serif;
fill: #000000;
font-size: 18px;
font-optical-sizing: auto;
font-weight: 600;
font-style: normal;
font-variation-settings: "wdth" 100;
}
.ibm-plex-sans-timestampText {
font-family: "IBM Plex Sans", sans-serif;
fill: #000000;
font-size: 10px;
font-optical-sizing: auto;
font-weight: 400;
font-style: italic;
font-variation-settings: "wdth" 100;
}
.ibm-plex-sans-menuitem {
font-family: "IBM Plex Sans", sans-serif;
fill: #000000;
font-size: 10px;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
font-variation-settings: "wdth" 100;
}
.static {
cursor: not-allowed;
}
.draggable {
cursor: move;
}
.menuRect {
stroke: #00aeff;
fill: rgb(253, 253, 201);
fill-opacity: 100%;
stroke-width: 1px;
filter: drop-shadow(4px 5px 2px rgb(0 0 0 / 0.4));
}
Код: Выделить всё
hidden div for measuring pixel length of text strings in a particular font/size
Подробнее здесь:
https://stackoverflow.com/questions/796 ... nt-display
1767530538
Anonymous
Следующий код создает ползунок с левым, средним и правым маркерами. При нажатии на среднюю ручку появляется прямоугольник, который должен быть меню. Код перебирает два массива для заполнения меню. Используя F12 (в Firefox 138.0–64bit), я вижу на вкладке инспектора, что текстовые элементы были созданы с правильным содержимым, но ничего не появляется, и при выборе строки в инспекторе обычно отображается ограничивающая рамка для выбранной строки. Ничего для этих текстовых элементов, которые на первый взгляд имеют тот же синтаксис, что и другой отображаемый текст. [code]//https://github.com/amitonline/true-ruler/blob/main/js/true-ruler.js var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); const control_W = 550; //width of slider const control_H = 350; //Height of slider const left_padding = 75; const right_padding = 75; const top_padding = 25; const bottom_padding = 25; const pillRad = 10; const pillOpacity = 50; const diamondSide = Math.sqrt(2 * (Math.pow(pillRad, 2))); //make the diamond the same height as the circle handles (pythagorus) const labelOffset = 75; const PDDheight = 120; const PDDwidth = 75; const PDDrad = 2; svg.setAttribute("id", "sliderControl"); svg.setAttribute("overflow", "visible"); svg.setAttribute("viewBox", "0 0 " + control_W + " " + control_H); svg.setAttribute("width", control_W); svg.setAttribute("height", control_H); svg.setAttribute("onload", "makeDraggable(evt)"); var svgNS = svg.namespaceURI; var slider = document.createElementNS(svgNS, 'path'); slider.setAttributeNS(null, "d", "M " + left_padding + "," + (top_padding + (control_H / 2)) + " H " + (control_W - right_padding)); slider.setAttribute("id", "slider"); slider.setAttribute("stroke", "silver"); slider.setAttribute("stroke-width", "5"); slider.setAttribute("opacity", "1"); slider.setAttribute("fill", "none"); svg.appendChild(slider); const startPill = document.createElementNS(svgNS, "circle"); startPill.setAttribute("class", "draggable"); startPill.setAttribute("id", "startPill"); startPill.setAttribute("cx", left_padding); startPill.setAttribute("cy", (top_padding + (control_H / 2))); startPill.setAttribute("r", pillRad); startPill.setAttribute("fill", "#55aaff"); startPill.setAttribute("opacity", pillOpacity + "%"); //startPill.setAttribute("cursor", "move"); svg.appendChild(startPill); const periodPill = document.createElementNS(svgNS, "rect"); periodPill.setAttribute("class", "draggable"); periodPill.setAttribute("id", "period"); periodPill.setAttribute("x", -diamondSide / 2); periodPill.setAttribute("y", -diamondSide / 2); periodPill.setAttribute("width", diamondSide); periodPill.setAttribute("height", diamondSide); periodPill.setAttribute("transform", "translate(" + (control_W / 2) + ", " + (top_padding + (control_H / 2)) + ") rotate(45)"); periodPill.setAttribute("fill", "#55aaff"); periodPill.setAttribute("opacity", pillOpacity + "%"); periodPill.addEventListener("click", function() { //don't keep recreating the menu if one already exists if (document.getElementById("periodDD") == null) { var menu = createPeriodDD(); } }); svg.appendChild(periodPill); const endPill = document.createElementNS(svgNS, "circle"); endPill.setAttribute("class", "draggable"); endPill.setAttribute("id", "endPill"); endPill.setAttribute("cx", (control_W - right_padding)); endPill.setAttribute("cy", (top_padding + (control_H / 2))); endPill.setAttribute("r", pillRad); endPill.setAttribute("fill", "#55aaff"); endPill.setAttribute("opacity", pillOpacity + "%"); //endPill.setAttribute("cursor", "move"); svg.appendChild(endPill); const startLabel = document.createElementNS(svgNS, "text"); startLabel.setAttribute("class", "ibm-plex-sans-labelText"); startLabel.setAttribute("y", labelOffset); startLabel.setAttribute("text-anchor", "left"); startLabel.textContent = "Start time"; startLabel.setAttribute("x", left_padding - (measureTextWidth(startLabel.textContent)) / 2); svg.appendChild(startLabel); const periodLabel = document.createElementNS(svgNS, "text"); periodLabel.setAttribute("class", "ibm-plex-sans-labelText"); periodLabel.setAttribute("y", labelOffset); periodLabel.setAttribute("text-anchor", "center"); periodLabel.textContent = "Period"; periodLabel.setAttribute("x", (control_W / 2) - (measureTextWidth(periodLabel.textContent)) / 2); svg.appendChild(periodLabel); const endLabel = document.createElementNS(svgNS, "text"); endLabel.setAttribute("class", "ibm-plex-sans-labelText"); endLabel.setAttribute("y", labelOffset); endLabel.setAttribute("text-anchor", "right"); endLabel.textContent = "End time"; endLabel.setAttribute("x", (control_W - right_padding) - (measureTextWidth(endLabel.textContent)) / 2); svg.appendChild(endLabel); function measureTextWidth(text) { const testDiv = document.getElementById("Test"); testDiv.innerText = text; // Set the text to measure // Measure width after rendering const width = testDiv.clientWidth; return width; } function createPeriodDD() { const P = [100, 1, 1, 1, 1, 7]; //enumerated values const U = ["ms", "sec", "min", "hour", "day", "days"]; //units for values const periodDD = document.createElementNS(svgNS, "rect"); periodDD.setAttribute("class", "menuRect"); periodDD.setAttribute("id", "periodDD"); periodDD.setAttribute("x", ((control_W / 2) - (PDDwidth / 2))); periodDD.setAttribute("y", (top_padding + (control_H / 2) + bottom_padding)); periodDD.setAttribute("width", PDDwidth); periodDD.setAttribute("height", PDDheight); periodDD.setAttribute("rx", PDDrad); periodDD.setAttribute("ry", PDDrad); var i = 0; var menuitem = []; P.forEach(element => { menuitem[i] = document.createElementNS(svgNS, "text"); menuitem[i].setAttribute("class", "ibm-plex-sans-menuitem"); menuitem[i].setAttribute("text-anchor", "left"); menuitem[i].setAttribute("y", i * 10); menuitem[i].textContent = P[i] + " " + U[i]; menuitem[i].setAttribute("x", "10"); periodDD.appendChild(menuitem[i]); i += 1; }); svg.appendChild(periodDD); } function makeDraggable(evt) { var obj = evt.target; obj.addEventListener('contextmenu', contextMenu); obj.addEventListener('menu', menu); obj.addEventListener('mousedown', startDrag); obj.addEventListener('mousemove', drag); obj.addEventListener('mouseup', endDrag); obj.addEventListener('mouseleave', endDrag); var selectedElement, offset, transform; function contextMenu(evt) { alert("context menu"); } function menu(evt) { alert("menu"); } function startDrag(evt) { if (evt.target.classList.contains('draggable')) { selectedElement = evt.target; console.log(selectedElement.id) } } function drag(evt) { //NB for this appliocation no dragging happens - the start or end time (or both) change at a rate that fits with the period but the pills remain static if (selectedElement) { console.log(selectedElement.id); evt.preventDefault(); var x = parseFloat(selectedElement.getAttributeNS(null, "x")); selectedElement.setAttributeNS(null, "x", x + 0.1); } } function endDrag(evt) { selectedElement = null; } } document.body.appendChild(svg);[/code] [code].ibm-plex-sans-labelText { font-family: "IBM Plex Sans", sans-serif; fill: #000000; font-size: 18px; font-optical-sizing: auto; font-weight: 600; font-style: normal; font-variation-settings: "wdth" 100; } .ibm-plex-sans-timestampText { font-family: "IBM Plex Sans", sans-serif; fill: #000000; font-size: 10px; font-optical-sizing: auto; font-weight: 400; font-style: italic; font-variation-settings: "wdth" 100; } .ibm-plex-sans-menuitem { font-family: "IBM Plex Sans", sans-serif; fill: #000000; font-size: 10px; font-optical-sizing: auto; font-weight: 400; font-style: normal; font-variation-settings: "wdth" 100; } .static { cursor: not-allowed; } .draggable { cursor: move; } .menuRect { stroke: #00aeff; fill: rgb(253, 253, 201); fill-opacity: 100%; stroke-width: 1px; filter: drop-shadow(4px 5px 2px rgb(0 0 0 / 0.4)); }[/code] [code] hidden div for measuring pixel length of text strings in a particular font/size [/code] Подробнее здесь: [url]https://stackoverflow.com/questions/79647980/javascript-created-svg-text-shows-up-in-the-dom-but-doesnt-display[/url]