ref (use DOM manipulation) is not Component's philosophy
Opened this issue · 1 comments
c0ncentus commented
https://en.reactjs.org/docs/refs-and-the-dom.html
WebComponent is Js encapsulated HTML.
No DOM manupulation.
c0ncentus commented
Configuration
<ReactArcText cssOverride={{}} dir="up" fontSize={20} isHeightForced={true} isWidthForced={true} lineHeight={1} text="Ukraine" totalSize={{height:300, width:300}} />
Code more friendly with React !
export function arrayByNum(num: number) { return Array.from(new Array(num)).map((el, i) => { if (el) { }; return i.toString() }) }
function getRect(fontSize: number): IRect { return { height: fontSize, width: fontSize } }
const radiansPerDegree = Math.PI / 180
const degreesPerRadian = 180 / Math.PI
function chord(r: number, θ: any) { return 2 * r * Math.sin(degreesToRadians(θ / 2)) };
function radiansToDegrees(angleInDegrees: number) { return angleInDegrees * degreesPerRadian };
function degreesToRadians(angleInDegrees: number) { return angleInDegrees * radiansPerDegree };
function sagitta(r: number, θ: any) { return r * (1 - Math.cos(degreesToRadians(θ / 2))) };
function getLetterRotations(metrics: IRect[], r: number) { return metrics.reduce((data, { width }) => { const rotation = radiansToDegrees(width / r); return { θ: data.θ + rotation, rotations: data.rotations.concat([data.θ + rotation / 2]) } }, { θ: 0, rotations: [] }) }
function convertDir(dir: "down" | "up") { return dir === "up" ? 1 : -1 }
export class ReactArcText extends Component<{
text: string,
cssOverride: CSSProperties,
// arc: number
fontSize: number,
totalSize: { width: number, height: number }
lineHeight: number
isWidthForced: boolean
isHeightForced: boolean
dir: "up" | "down"
}, any>{
render() {
const { dir, cssOverride, fontSize, isHeightForced, isWidthForced, lineHeight, text, totalSize } = this.props;
const { height, width } = totalSize
const radius = width / Math.PI / 2 + lineHeight;
const matrix = arrayByNum(text.length).map(() => { return getRect(fontSize) })
const innerRadius = radius - lineHeight
const { rotations, θ } = getLetterRotations(matrix, innerRadius)
return <div className="react-arc-text" style={{
...cssOverride, position: "relative",
width: isWidthForced ? `${chord(radius, Math.min(180, θ)) / fontSize}em` : "unset",
height: isHeightForced ? `${(θ > 180
? sagitta(radius, θ)
: sagitta(innerRadius, θ) + lineHeight)
/ fontSize
}em` : "unset"
}}>
{text.split("").map((letter, i) => {
const rotate = (θ * -0.5 + rotations[i]) * convertDir(dir)
const ElWidth = matrix.length < i + 1 ? undefined : matrix[i].width;
const translateX = ElWidth === undefined ? 0 : ElWidth / fontSize
return <p style={{
transform: `translateX(${translateX}em) rotate(${rotate}deg)`, position: "absolute",
bottom: dir === "down" ? '0' : 'auto',
left: "50%",
transformOrigin: `center ${(dir === "down" ? -radius + lineHeight : radius) / fontSize}em`
}}>{letter}</p>
})}
</div>
}
}
If you can impoove it ( configuration for arc value ).... there is no DOM but expect fontSize is the width of each letter (you can add spaceLetter otherwise ) better than DOM .