大家好,我是前端西瓜哥。
今天簡單講講圖形編輯器的顯示屬性值時,會遇到的格式轉換問題。
編輯器 github 地址:
https://github.com/F-star/suika
線上體驗:
https://blog.fstars.wang/app/suika/
圖形編輯器中的數據,通過 UI 層進行展示時,可能不會直接將數據源的原始值展示出來,而是會額外進行單位的轉換,變成另一種格式。
這里以簡單而常見的弧度為例。
圖形的旋轉在數據源中,會用弧度(radian)表示。因為弧度更適合進行數學計算,且很多 API 比如 Math.sin(x) 都需要你提供弧度。
但在面向用戶的 UI 層,我們通常會提供角度(degree),因為日常生活中人們更常使用,它更直觀。
但數據中我們還是要保存弧度的。
我們需要明確的點是:
/** * 弧度轉角度 */export function radian2Degree(radian: number) { return (radian * 180) / Math.PI;}/** * 角度轉弧度 */export function degree2Radian(degree: number) { return (degree * Math.PI) / 180;}
需要注意,格式的轉換通常會丟失一些精度的。
這里弧度和角度的轉換就是一個例子。
圓周率是一個無限不循環小數,計算的時候,會對其丟掉一些精度再參與計算,最后的結果自然也丟失了精度。
這里給一下 UI 層實現思路,以 React 組件為例,核心實現大致如下:
const [radian, setRadian] = useState(0);useEffect(() => { rect.onRotationChange((val) => { // 從編輯器內核同步過來的狀態 setRadian(val); })});<NumberInput label="旋轉" value={remainDecimal(radian2Degree(radian))} onBlur={(e) => { const degree = e.target.value; const radian = normalizeRadian(degree2Radian(degree)); rect.setRotation(radian); }}/>
題外話,UI 層會直接更新編輯器中的狀態,成功更新后通過事件訂閱通知回 UI 層,同步狀態。
弧度還是比較簡單的場景。
像是復雜一點的屬性,比如顏色值,通常要實現一個比較完善的拾色器,要支持多種格式,如RGBA、HSL、CMYK 等等,要實現的方法就更復雜也更多。
UI 層不會顯示全精度,意義不大。
比如 x 坐標的真實值是 52.24621202458749,但用戶是不希望看到這么長的值的,他只是想知道這個點大概在什么位置。
所以我們最好做一個四舍五入,比如保留有限的有效位顯示為 52.25。
需要注意的是,修改屬性值時不用做降低精度再轉為源格式,我們的數據源精度越高越好。
只在顯示時做降低精度。
因為涉及到用戶修改屬性值,所以我們需要對用戶的輸入值進行處理,嘗試得到一個合法值去修改屬性。
簡單的做法是 嚴格校驗,比如對于數字類型,出現非數字字符,就直接認為非法值。
稍微好一點的是從字符串中提取符合格式的部分。
更人性化的是猜測用戶想干嘛,做補全。比如對于 hex 格式的顏色值,用戶只輸入一個 3,我們給他補全為 33333。
畫一張圖總結一下。
展示層可能和數據源的格式不同,顯示時要做格式轉換,然后降低精度,比如對于數字通常保留 1 到 5 個小數位就夠了。
修改非源格式要做校驗和補正,然后轉回數據源格式保存起來。保存成功后再把新值傳遞到 UI 層。
本文鏈接:http://www.www897cc.com/showinfo-26-12675-0.html圖形編輯器開發:屬性顯示與格式轉換
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com