gpt4 book ai didi

reactjs - 如何在 React 中测量 SVG 元素?

转载 作者:行者123 更新时间:2023-12-03 15:51:02 26 4
gpt4 key购买 nike

要在我的应用程序中渲染某些 SVG 元素,我需要首先测量一些其他 SVG 元素。

例如,假设 <text>随机定位在正方形 (0,0) - (100,100) 中的元素,可以有各种字体大小、字体系列等。

如果文本位于 (10,20),宽度为 30,高度为 40,我想设置包含 <svg>宽度为 40 (= 10 + 30),高度为 60 (= 20 + 40)。

重点是:<text>需要测量之前 渲染 <svg> .

帮助 <text>测量,我创建了以下组件:

class MeasureSvgElements extends React.Component {
storeSvgReference = svg => {
if (svg !== null) {
this.svg = svg;
}
};

measure() {
const childElements = Array.from(this.svg.children);
const dimensions = childElements
.map(element => element.getBoundingClientRect())
.map(({ width, height }) => ({ width, height }));

this.props.onChange(dimensions);
}

componentDidMount() {
this.measure();
}

componentDidUpdate() {
this.measure();
}

render() {
return (
<svg width="0" height="0" style={{ display: 'block' }} ref={this.storeSvgReference}>
{this.props.children}
</svg>
);
}
}

可用于一次测量多个元素:
<MeasureSvgElements onChange={onChange}>
{['Hello', 'Stack', 'Overflow'].map(str => <text>{str}</text>)}
</MeasureSvgElements>
onChange尺寸准备好后将被调用。

现在,我不确定使用 <MeasureSvgElements> 的最佳方式是什么渲染包含 <svg>使用 onChange 提供的尺寸.

或者,有没有更好的方法?

最佳答案

一种解决方案可能是模拟每个 text渲染之前的元素,收集高度和宽度(除了位置),然后遍历尺寸以确定应该应用到父元素的尺寸。
工作代码沙盒:https://codesandbox.io/s/stack-43880276-dynamic-svg-textbox-id3rt
数据结构:

import React, { useState, useEffect } from "react";
import styled from "styled-components";

const yourTextData = [
{
id: 0,
posX: 0,
posY: 0,
str: "~~Hello~~",
fontFamily: "URW Chancery L, cursive",
fontSize: "30"
},
{
id: 1,
posX: 20,
posY: 20,
str: "~~Stack~~",
fontFamily: "URW Chancery L, cursive",
fontSize: "30"
},
{
id: 2,
posX: 40,
posY: 40,
str: "~~Overflow~~",
fontFamily: "URW Chancery L, cursive",
fontSize: "30"
},
{
id: 3,
posX: 0,
posY: 80,
str: "This SVG with text sets its own",
fontFamily: "Arial, sans-serif",
fontSize: "30"
},
{
id: 4,
posX: 40,
posY: 120,
str: "d i m e n s i o n s",
fontFamily: "FreeMono, monospace",
fontSize: "30"
}
];
定义你的组件和钩子(Hook):
const DynamicSVGText = (props) => {
const [svgWidth, setSvgWidth] = useState(0);
const [svgHeight, setSvgHeight] = useState(0);
const [textDims, setTextDims] = useState([]); // array of objects, defining dims/pos for each texteach text

测量功能
这将在创建每个 text 时调用元素并保存到 textDims钩。
  const measure = (data) => {
// create a mock element
let newText = document.createElement("text");
newText.setAttribute("id", data.id);
document.body.appendChild(newText);

// append text data
let theTextEle = document.getElementById(`${data.id}`);
theTextEle.innerHTML += data.str;

// append text font / size, bc might as well be fancy
theTextEle.style.fontFamily = data.fontFamily;
theTextEle.style.fontSize = `${data.fontSize}px`;

// measure element
let width = theTextEle.getBoundingClientRect().width;
let height = theTextEle.getBoundingClientRect().height;

// delete element
theTextEle.parentNode.removeChild(theTextEle);

// set data
let dimData = [width, height];
//console.log(dimData);

// return dimension data
return dimData;
};
创建函数 text要素:
  const SvgText = ({ text }) =>
text.map((data, i) => {
let dimensions = measure(data);

let updatedTextDims = textDims;

updatedTextDims[data.id] = {
x: data.posX,
y: data.posY,
w: dimensions[0],
h: dimensions[1]
};

return (
<StyledText
fontFamily={data.fontFamily}
fontSize={data.fontSize}
key={data.id}
x={data.posX.toString()}
y={(data.posY + dimensions[1]).toString()}
>
{data.str}
</StyledText>
);
});
使用Effect检测 textDims Hook 更改
  useEffect(() => {
let tw = 0; // longest width
let th = 0; // tallest height

// loop through text elements and their dimensions,
// set total width/height to the greatest dimensions across objects
for (let d = 0; d < textDims.length; d++) {
let thisWidth = textDims[d].x + textDims[d].w;
let thisHeight = textDims[d].y + textDims[d].h;

if (thisWidth > tw) {
tw = thisWidth;
}

if (thisHeight > th) {
th = thisHeight;
}
}

setSvgWidth(tw);
setSvgHeight(th);
}, [textDims]);
完成组件,以及一些样式
  return (
<svg
width={svgWidth.toString()}
height={svgHeight.toString()}
style={{ display: "block" }}
>
<SvgText text={props.text} />
</svg>
);
};

export default function App() {
return (
<Container>
<DynamicSVGText text={yourTextData} />
</Container>
);
}

const Container = styled.div`
display: flex;
flex-direction: row;
justify-content: center;
`;

const StyledText = styled.text``;

关于reactjs - 如何在 React 中测量 SVG 元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43880276/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com