我正在使用一个svg元素,其中有pathforeignObject.我试图将foreignObject放置在路径的末尾.但我不知道该怎么做.

例如,这就是我try 的.

// global
const bound = document.querySelector('.bound');
const svgns = 'http://www.w3.org/2000/svg';
const line = document.querySelector('#valLine');
const length = line.getTotalLength();
const pct =1;
const point = line.getPointAtLength(length * pct);

// create  svg text element
const textGroup = document.createElementNS(svgns,'g');
textGroup.setAttribute('class','textElement');
bound.appendChild(textGroup);

const text = document.createElementNS(svgns,'text');
text.setAttribute('x',`${point.x.toString()}`);
text.setAttribute('y',`${point.y.toString()}`);
text.setAttribute('fill','white');
text.textContent='31.13';
textGroup.appendChild(text);

// create  foreign object => g > foreignObject
const foGroup = document.createElementNS(svgns,'g');
foGroup.setAttribute('class','foreignObjectElement');
bound.appendChild(foGroup);

const fo = document.createElementNS(svgns, 'foreignObject')
fo.setAttribute("xmlns", 'http://www.w3.org/1999/xhtml');
fo.setAttribute('class','fo');
fo.setAttribute('x',`${point.x.toString()}`);
fo.setAttribute('y',`${point.y.toString()}`);
fo.setAttribute("width", "40");
fo.setAttribute("height", "40");
foGroup.appendChild(fo);


//div inside foreign object ==> g > foreignObject > div
const div = document.createElement('div');
div.setAttribute("xmlns", 'http://www.w3.org/1999/xhtml');
fo.appendChild(div);

//span inside div ==> g > foreignObject > div > span
const span = document.createElement('span');
span.setAttribute('class','pop');
span.style.setProperty('height','auto');
span.style.setProperty('width','auto');
span.style.setProperty('background-color', '#555');
span.style.setProperty('color', '#fff');
span.style.setProperty('text-align', 'center');
span.style.setProperty('border-radius', '6px');
span.style.setProperty('padding', '8px 0');
span.style.setProperty('position', 'absolute');
span.textContent = '31.13';
div.appendChild(span);
div > span::after {
    content: "";    
    position: absolute;   
    bottom: 0;   
    top: 100%;
    left: 50%;
    margin-left: -5px;
    border-width: 5px;
    border-style: solid;
    border-color: #555 transparent transparent transparent;
}
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>
  <!--<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>-->
  <body>
    <div id="container"></div>
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 720">
      <rect class="vBoxRect" width="1280" height="720" fill="green" stroke="red"></rect>
      <rect class="boundRect" x="70" y="70" width="1020" height="600" fill="none" stroke="green"></rect>
      <g class="bound" style="transform: translate(70px, 70px);">
        <g class="valLine">
          <path id="valLine" d="M0,600L42.5,600L85,334.0399725781784L127.5,313.86735572781834L212.5,222.9985644559286L255,222.9985644559286L297.5,248.66379557852153L340,248.66379557852153L382.5,248.66379557852153L425,171.66810221073513L467.5,171.66810221073513L510,146.00287108814229L552.5,248.66379557852153L595,248.66379557852153L637.5,248.66379557852153L680,197.33333333333186L722.5,197.33333333333186L765,171.66810221073513L807.5,94.67240884294881L850,94.67240884294881L892.5,94.67240884294881L935,25.495262704563594L977.5,25.495262704563594L1020,0" stroke="black" fill="none"></path>
        </g>
      </g>
    </svg>
    </svg>
  </body>
  <script src="prod.js" type="text/javascript"></script>
</html>

我最初的假设是创建一个SVG Point101,并将xy分配给foreignObject,不幸的是,这对104不起作用,但对svg 105非常有效.

通过为svg text元素指定相同的坐标,我可以将其放置在所需的位置.

换言之,如何以编程方式将100定位在与svg 101完全相同的位置?

推荐答案

我通过使用getExtentOfChar()实现了这一点,首先创建svg 101元素,然后将y值从这些 node 复制到外部对象 node .

缺点是需要首先创建文本 node ,以便异物检索准确的y位置.

//global
 const bound = document.querySelector('.bound');
 const svgns = 'http://www.w3.org/2000/svg';
 const line = document.querySelector('#valLine');
 const val = [63.75, 35.28, 48.86];

 // create  svg text element group => g for text
 const textGroup = document.createElementNS(svgns, 'g');
 textGroup.setAttribute('class', 'textElement');
 bound.appendChild(textGroup);

 // create  foreign object group=> g for foreignObject
 const foGroup = document.createElementNS(svgns, 'g');
 foGroup.setAttribute('class', 'foreignObjectElement');
 bound.appendChild(foGroup);

 document.querySelectorAll('#valLine>path').forEach(
    (a, i) => {
        const length = a.getTotalLength();
        const pct = 1;
        const point = a.getPointAtLength(length * pct);

        //create text => g > text
        const text = document.createElementNS(svgns, 'text');
        text.setAttribute('x', `${point.x.toString()}`);
        text.setAttribute('y', `${point.y.toString()}`);
        text.textContent = val[i].toString();
        textGroup.appendChild(text);

        // create  foreign object => g > foreignObject
        const fo = document.createElementNS(svgns, 'foreignObject')
        fo.setAttribute("xmlns", 'http://www.w3.org/1999/xhtml');
        fo.setAttribute('class', 'fo');
        fo.setAttribute('x', `${point.x.toString()}`);
        fo.setAttribute('y', `${(point.y).toString()}`);
        fo.setAttribute('alignment-baseline', `before-edge`);
        fo.setAttribute("width", "40");
        fo.setAttribute("height", "40");
        foGroup.appendChild(fo);

        //div inside foreign object ==> g > foreignObject > div
        const div = document.createElement('div');
        div.setAttribute("xmlns", 'http://www.w3.org/1999/xhtml');
        div.style.setProperty('position', 'fixed');
        fo.appendChild(div);

        //span inside div ==> g > foreignObject > div > span
        const span = document.createElement('span');
        span.setAttribute('class', 'pop');
        /*span.style.setProperty('height','80px');
        span.style.setProperty('width','auto');
        span.style.setProperty('background-color', '#555');
        span.style.setProperty('color', '#fff');
        span.style.setProperty('text-align', 'center');
        span.style.setProperty('border-radius', '6px');
        span.style.setProperty('padding', '8px 0');*/
        span.style.setProperty('position', 'fixed');
        span.textContent = val[i].toString();
        div.appendChild(span);

    }
 )

 const textElement = document.querySelectorAll('body > svg > g > g.textElement > text');
 const foElement = document.querySelectorAll('body > svg > g > g.foreignObjectElement > foreignObject');

 textElement.forEach((a, i) => {
    const y = a.getExtentOfChar(0).y;
    foElement[i].setAttribute('y', y);
 })


 const parent = textGroup.parentNode;
 //parent.removeChild(textGroup);
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>
  <!--<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>-->
  <body>
    <div id="container"></div>
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1536 720">
      <rect class="vBoxRect" width="1536" height="720" fill="green" stroke="red" opacity="0.1"></rect>
      <rect class="boundRect" x="70" y="70" width="1346" height="600" fill="none" stroke="none"></rect>
      <g class="bound" style="transform: translate(70px, 70px);">
        <g id="valLine">
          <path class="Rwanda" id="Rwanda" fill="none" stroke="red" stroke-width="1" d="M0,438.6554621848753L56.08333333333333,438.6554621848753L112.16666666666666,438.6554621848753L168.25,357.98319327731105L224.33333333333331,358.34658187599433L280.4166666666667,358.34658187599433L336.5,141.17647058823525L392.58333333333337,141.17647058823525L448.66666666666663,141.17647058823525L504.75,141.17647058823525L560.8333333333334,141.17647058823525L616.9166666666666,70.5882352941176L673,70.5882352941176L729.0833333333333,70.5882352941176L785.1666666666667,70.5882352941176L841.25,70.5882352941176L897.3333333333333,0L953.4166666666667,0L1009.5,0L1065.5833333333333,0L1121.6666666666667,23.5294117647058L1177.75,23.5294117647058L1233.8333333333333,23.5294117647058L1289.9166666666667,23.5294117647058L1346,23.5294117647058"></path>
          <path class="Andorra" id="Andorra" fill="none" stroke="green" stroke-width="1" d="M0,532.7731092436975L56.08333333333333,532.7731092436975L112.16666666666666,532.7731092436975L168.25,532.7731092436975L224.33333333333331,465.5462184873948L280.4166666666667,465.5462184873948L336.5,465.5462184873948L392.58333333333337,465.5462184873948L448.66666666666663,331.0924369747897L504.75,331.0924369747897L560.8333333333334,331.0924369747897L616.9166666666666,364.70588235294116L673,263.8655462184875L729.0833333333333,263.8655462184875L785.1666666666667,129.4117647058823L841.25,129.4117647058823L897.3333333333333,129.4117647058823L953.4166666666667,129.4117647058823L1009.5,230.25210084033597L1065.5833333333333,297.478991596639L1121.6666666666667,297.478991596639L1177.75,297.478991596639L1233.8333333333333,163.02521008403383L1289.9166666666667,163.02521008403383L1346,163.02521008403383"></path>
          <path class="Cuba" id="Cuba" fill="none" stroke="blue" stroke-width="1" d="M0,385.8783581344254L56.08333333333333,340.04110795732606L112.16666666666666,340.04110795732606L168.25,340.04110795732606L224.33333333333331,340.04110795732606L280.4166666666667,340.04110795732606L336.5,261.5473775717186L392.58333333333337,261.5473775717186L448.66666666666663,261.5473775717186L504.75,261.5473775717186L560.8333333333334,261.5473775717186L616.9166666666666,193.79191415980043L673,193.79191415980043L729.0833333333333,193.79191415980043L785.1666666666667,174.38265408552468L841.25,174.38265408552468L897.3333333333333,140.17685505574866L953.4166666666667,140.17685505574866L1009.5,140.17685505574866L1065.5833333333333,140.17685505574866L1121.6666666666667,140.17685505574866L1177.75,99.07632474477359L1233.8333333333333,99.07632474477359L1289.9166666666667,99.07632474477359L1346,97.28970086328088"></path>
        </g>
      </g>
    </svg>
    </svg>
  </body>
  <script type="text/javascript"></script>
</html>

Javascript相关问答推荐

根据总价格对航班优惠数组进行排序并检索前五个结果- Angular HTTP请求

如何访问Json返回的ASP.NET Core 6中的导航图像属性

通过在页面上滚动来移动滚动条

colored颜色 检测JS,平均图像 colored颜色 检测JS

在观察框架中搜索CSV数据

将本机导航路由react 到导航栏中未列出的屏幕?

为什么Mutations 观察器用微任务队列而不是macrotask队列处理?

优化Google Sheet脚本以将下拉菜单和公式添加到多行

Angular 订阅部分相互依赖并返回数组多个异步Http调用

JS:XML insertBefore插入元素

如何发送从REST Api收到的PNG数据响应

NG/Express API路由处理程序停止工作

如何使用<;Link>;执行与JS Reaction中的";window.Location=/GameOverDied;";类似的操作?

Jexl to LowerCase()和Replace()

FireBase FiRestore安全规则-嵌套对象的MapDiff

在高位图中显示每个y轴系列的多个值

当达到高度限制时,如何裁剪图像?使用html和css

如何将缓冲区数组转换回音频

我正在为我的单选按钮在HTML中设置一个值.使用Java脚本,我如何才能获得该值?

TS node 找不到依赖的模块