javascript - 自定义useOneLineText React Hook,可调整字体大小并始终将文本保持在一行
问题描述
我正在尝试创建一个自定义钩子,它将文本保持在一行,这就是我到目前为止所得到的:
import { useEffect, useState, useRef } from "react";
export default function useOneLineText(initialFontSize, text) {
const containerRef = useRef(null);
const [adjustedFontSize, setAdjustedFontSize] = useState(initialFontSize);
useEffect(() => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const containerWidth = containerRef.current.getBoundingClientRect().width;
let currentFontSize = initialFontSize;
do {
ctx.font = `${currentFontSize}px "Lato"`;
currentFontSize -= 1;
} while (containerWidth < ctx.measureText(text).width);
setAdjustedFontSize(currentFontSize);
}, []);
return { containerRef, adjustedFontSize, text };
}
以及用法:
import React, { useState } from "react";
import "./style.css";
import useOneLineText from "./useOneLineText";
const initialFontSize = 32;
export default function App() {
const [shortText, setShortText] = useState("Hello Peaceful World!");
const { containerRef, adjustedFontSize, text } = useOneLineText(
initialFontSize,
shortText
);
return (
<div>
<h1
ref={containerRef}
style={{ width: "100px", fontSize: `${adjustedFontSize}px` }}
>
{text}
</h1>
<h1 style={{ width: "100px", fontSize: `${initialFontSize}px` }}>
Hello Cruel World!
</h1>
<button onClick={() => setShortText("Hello World!")}>Remove Peace</button>
</div>
);
}
我想知道为什么尝试使用Remove Peace
按钮更改文本时我的字体没有更新。我也不确定在 useEffect 中循环并将字体大小减小 1 是否是最好的方法,是否可以在没有循环的情况下计算调整后的字体大小?这是我的工作示例。
解决方案
好吧,您的代码已经可以正常工作了。从您的示例中,初始字体大小 32px 在安装时更改为 10px。此外,您的效果仅在安装时运行。如果不删除这个词,它也已经满足containerWidth < ctx.measureText(text).width
.
如果您希望在 containerWidth 或 textWidth 更改时发生效果,那么您可以添加更多状态并将它们添加到您的 useEffect 依赖项列表中。
const [container, setContainerState] = useState(null);
const [textWidth, setTextWidth] = useState(null);
useEffect(() => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const refWidth = containerRef.current.getBoundingClientRect().width;
let currentFontSize = initialFontSize;
if (
textWidth !== ctx.measureText(text).width ||
containerWidth !== refWidth
) {
do {
ctx.font = `${currentFontSize}px "Lato"`;
currentFontSize -= 1;
} while (refWidth < ctx.measureText(text).width);
setContainerWidth(containerWidth);
setTextWidth(textWidth);
setAdjustedFontSize(currentFontSize);
}
}, [textWidth, containerWidth]);
为了更快地调整字体大小,您可以从使用二分搜索帮助您更快找到正确宽度的 jquery 问题中查看此答案?
推荐阅读
- postgresql - 什么时候我们应该在 PostgreSQL 中使用 JSONB
- c - insertAtTail 未在链表中添加节点
- html - 如何在 HTML 中提供绝对文件路径
- jquery - 用另一个元素Jquery替换元素
- php - 使用输入值,查询类别是否包含名称或公司名称。我要退回公司名单
- debugging - Intellij如何在调试期间从堆栈跟踪中打开源代码
- django - 如何使用 django 计算文件的下载次数
- python - Python WeakRef.WeakMethod 传递参数
- shell - 在使用 ^A(即 \001)作为分隔符的 CSV 文件末尾添加空列?
- javascript - javascript中的console.time()与Date.now()有什么区别,哪个性能更好