简体   繁体   中英

Convert text to Svg Path to get path length - ReactJS

I am trying to convert text to svg to get the length of svg path. But I am getting the error:

Uncaught TypeError: svgPath.getBBox is not a function

I tried a lot and search a lot but didn't find any solution.
If i have to insert the SVG element in the Html, then how can i get the svg element in the context api file?
The texts and svgs will be multiple.
You can check the live website here, if you need to review first: https://uineon.hadithapi.com/
Component:

import { useCustomizer } from '../context/CustomizerContext'
export default function Preview() {
    const { settings } = useCustomizer()

    return (
        <div className="preview">
            <div className="preview-items">
                {settings.textItems.map((item, index) => (
                    <div
                        className="preview-items--item"
                        style={{
                            "--text-color": item.color
                        }}
                    >
                        <div
                            className={`preview-items--item__text ${item.backplate}`}
                            style={{
                                fontFamily: item.font,
                                fontSize: `${item.size}px`
                            }}
                        >{item.text}</div>
                    </div>
                ))}
            </div>
        </div>
    )
}

Context File:

import { createContext, useContext } from "react"

export const CustomizerContext = createContext()

export default function CustomizerState(props) {
    const backplateUnitPrice = 3
    const size = 30
    const backplatePrice = size * backplateUnitPrice
    const initialTextItem = {
        text: "Hello",
        font: "Raleway",
        size,
        color: "#000",
        backplate: "cut-sharp",
        uvPrint: false,
        neonPrice: 0,
        backplatePrice,
        totalPrice: 0
    }
    const [settings, setSettings] = useState({
        textItems: [initialTextItem]
    })

    const addTextItem = () => {
        textToSvg("Hello");
        const newItems = [...settings.textItems, initialTextItem]
        setSettings((prevState) => (
            {...prevState, textItems: newItems}
        ))
    }

    function textToSvg(text) {
        const svgString = `<svg viewbox="387 390 74 20"> <g> <path class="st37" d="M452,408h-56c-4.42,0-8-3.58-8-8l0,0c0-4.42,3.58-8,8-8h56c4.42,0,8,3.58,8,8l0,0 C460,404.42,456.42,408,452,408z" /> </g></svg>`
        const parser = new DOMParser();
        const parsedDoc = parser.parseFromString(svgString, "image/svg+xml");
        const parsedSvg = parsedDoc.querySelector('svg');
        const svgPath = parsedSvg.querySelector('path')
        console.log(parsedDoc)
        console.log(parsedSvg)
        console.log(svgPath)

        let bbox = svgPath.getBBox();
        let x = bbox.x + bbox.width / 2;
        let y = bbox.y + bbox.height / 2;
        
        // Create a <text> element
        let textElem = document.createElementNS(svgPath.namespaceURI, "text");
        textElem.setAttribute("x", x);
        textElem.setAttribute("y", y);
        // Centre text horizontally at x,y
        textElem.setAttribute("text-anchor", "middle");
        // Give it a class that will determine the text size, colour, etc
        textElem.classList.add("label-text");
        // Set the text
        textElem.textContent = text;
        // Add this text element directly after the label background path
        svgPath.after(textElem);
        console.log(svgPath);
    }

    return (
        <CustomizerContext.Provider value={{settings, addTextItem}}>
            {props.children}
        </CustomizerContext.Provider>
    )
}

export function useCustomizer() {
    return useContext(CustomizerContext)
}

I am stuck, can someone help me to achieve this?

You have an odd viewBox and path

If your objective is to center text over that path , add a guide path.

 <svg viewbox="387 390 74 20"> <path d="M452,408h-56c-4.42,0-8-3.58-8-8l0,0c0-4.42,3.58-8,8-8h56c4.42,0,8,3.58,8,8l0,0 C460,404.42,456.42,408,452,408z"/> <path id="guide" d="M388 401h72" stroke="grey" pathLength="100"/> <text> <textPath href="#guide" startoffset="50" text-anchor="middle" dominant-baseline="middle" fill="gold" font-size="14px">Hello</textPath> </text> </svg>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM