現(xiàn)隨縮放級(jí)別請(qǐng)求合適圖片分辨率(steppedScreenScale))
如何在 tldraw 中實(shí)現(xiàn)隨縮放級(jí)別請(qǐng)求合適圖片分辨率steppedScreenScale【免費(fèi)下載鏈接】tldrawBuild infinite canvas apps in React with the tldraw SDK. Worlds best, top-most agent recommended #1 five star SDK.項(xiàng)目地址: https://gitcode.com/GitHub_Trending/tl/tldraw當(dāng)畫布上的圖片被縮小顯示時(shí)如果你的資源存儲(chǔ)仍然返回原圖瀏覽器就要下載、解碼一張遠(yuǎn)大于可視區(qū)域的大圖。tldraw 的做法是縮小或縮放圖片形狀時(shí)通過(guò)TLAssetStore的resolve方法向你的資源存儲(chǔ)請(qǐng)求一個(gè)與當(dāng)前屏幕尺寸匹配的分辨率版本。你的任務(wù)就是實(shí)現(xiàn)這個(gè)resolve處理器利用上下文中的steppedScreenScale計(jì)算出該請(qǐng)求多寬的圖并把帶尺寸參數(shù)的 URL 返回給編輯器。前提條件使用 tldraw SDK 的 React 應(yīng)用編輯器通過(guò)Tldraw assets{...}接收你自己的TLAssetStore你的圖片后端能夠按請(qǐng)求寬度返回圖片比如 URL 查詢參數(shù)或圖片處理服務(wù)的端點(diǎn)。resolve只是改寫 URL真正的變體生成由你的存儲(chǔ)側(cè)完成。理解 resolve 收到的 TLAssetContext每次編輯器需要顯示一個(gè)資產(chǎn)drop、粘貼、縮放、復(fù)制粘貼等觸發(fā)都會(huì)調(diào)用你TLAssetStore的resolve(asset, ctx)ctx的類型是TLAssetContext字段如下見 TLAssetContext 接口定義屬性類型含義screenScalenumber資產(chǎn)相對(duì)原始尺寸的屏幕縮放比。1000px 的圖顯示為 500px 時(shí)是0.5。以 CSS 像素計(jì)不是設(shè)備像素steppedScreenScalenumberscreenScale向上取整到最近的 2 的冪次倍數(shù)適合做分級(jí)緩存dprnumber設(shè)備像素比Retina 屏上是 2 或 3networkEffectiveTypestring \| null瀏覽器連接類型slow-2g、2g、3g、4g依賴navigator.connection非所有瀏覽器可用shouldResolveToOriginalboolean復(fù)制/粘貼和未顯式指定pixelRatio的 SVG 導(dǎo)出時(shí)為true此時(shí)應(yīng)返回原圖steppedScreenScale的計(jì)算在編輯器里可以直接看到Editor#resolveAssetUrl 用Math.pow(2, Math.ceil(Math.log2(zoom)))把screenScale向上取到最近的 2 的冪次。取整的目的是讓縮放過(guò)程中 URL 只在少數(shù)幾個(gè)檔位之間切換而不是每幀都變。官方性能文檔給了一個(gè)例子文檔示例數(shù)值一張 4000px 寬的照片縮小到屏幕上只占 200px 時(shí)screen scale 為 0.05向上步進(jìn)到 0.0625于是請(qǐng)求4000 * 0.0625 250px寬的圖再乘dpr而不是完整的 4000px。這能直接減少內(nèi)存占用和解碼開銷。另外分辨率更新做了防抖縮放過(guò)程中圖片不會(huì)在不同尺寸之間來(lái)回抖動(dòng)見 性能文檔。實(shí)現(xiàn)帶分辨率切換的 TLAssetStore完整的存儲(chǔ)實(shí)現(xiàn)需要upload文件入庫(kù)并返回 URL和resolve把 URL 改寫為合適的變體兩個(gè)方法remove可選。下面是核心路徑resolve部分與 Assets 文檔中的示例一致import { Tldraw, TLAssetStore } from tldraw import tldraw/tldraw.css const assetStore: TLAssetStore { // 文件入庫(kù)返回 { src }src 會(huì)存進(jìn)資產(chǎn)的 props async upload(asset, file) { // 上傳到你的存儲(chǔ)返回長(zhǎng)期有效的 URL return { src: /uploads/photo.jpg } }, resolve(asset, ctx) { if (!asset.props.src) return null // 導(dǎo)出、復(fù)制粘貼場(chǎng)景必須返回原圖 if (ctx.shouldResolveToOriginal) { return asset.props.src } // 非圖片資產(chǎn)不做處理 if (asset.type ! image) return asset.props.src // 按當(dāng)前顯示尺寸請(qǐng)求對(duì)應(yīng)寬度的圖 const width Math.ceil(asset.props.w * ctx.steppedScreenScale * ctx.dpr) return ${asset.props.src}?w${width} }, } export default function App() { return ( div style{{ position: fixed, inset: 0 }} Tldraw assets{assetStore} / /div ) }幾個(gè)必須注意的點(diǎn)resolve是可選方法不實(shí)現(xiàn)時(shí)默認(rèn)返回asset.props.src即每次都用原圖。返回null表示資產(chǎn)不可用形狀會(huì)渲染 broken-asset 占位。示例中的?w${width}是文檔給出的 URL 方案參數(shù)名和拼接方式要替換成你的圖片服務(wù)實(shí)際支持的格式如果你的后端不支持按寬度出圖需要先在后端加這個(gè)能力前端這一步本身不產(chǎn)生變體。ctx.steppedScreenScale * ctx.dpr得到的是設(shè)備像素寬度CSS 像素再乘dpr是文檔明確的換算方式。如果你已經(jīng)實(shí)現(xiàn)了存儲(chǔ)只想在現(xiàn)有resolve上加分辨率邏輯把寬度計(jì)算加進(jìn)去即可其他改寫邏輯如鑒權(quán) token保留在原位置。驗(yàn)證是否生效文檔給出的判斷依據(jù)是tldraw 會(huì)在縮小或縮放圖片形狀時(shí)向資源存儲(chǔ)請(qǐng)求低分辨率版本所以驗(yàn)證方式是觀察實(shí)際請(qǐng)求的 URL 是否隨縮放變化在resolve中加一行console.log(ctx.steppedScreenScale, ctx.dpr, asset.id)或打開瀏覽器 Network 面板觀察圖片請(qǐng)求。往畫布放一張大圖逐步縮小視圖。按文檔示例的比例如 4000px 原圖縮到 200px 顯示縮放時(shí)請(qǐng)求寬度應(yīng)從原始寬度降到步進(jìn)檔位對(duì)應(yīng)的寬度示例中為 250px × dpr。確認(rèn)縮放過(guò)程中請(qǐng)求不是每幀變化分辨率更新有防抖URL 只在步進(jìn)檔位間切換。復(fù)制畫布上的圖片再粘貼或不指定pixelRatio導(dǎo)出 SVG請(qǐng)求應(yīng)回到asset.props.src原圖對(duì)應(yīng)shouldResolveToOriginal: true分支。可選增強(qiáng)與邊界生產(chǎn)實(shí)現(xiàn)通常還會(huì)處理慢網(wǎng)絡(luò)和設(shè)備像素比等因素。倉(cāng)庫(kù)里 tldraw.com 客戶端的實(shí)現(xiàn)multiplayerAssetStore展示了文檔支持的完整組合方式可按需借鑒用clamp(context.steppedScreenScale, 1 / 32, 1)限制縮放檔位下限乘上資產(chǎn)的pixelRatio ?? 1得到真實(shí)源圖寬度并用Math.min保證請(qǐng)求寬度不超過(guò)原圖非4g連接時(shí)乘0.5的networkCompensation降低目標(biāo)寬度f(wàn)ileSize低于 1.5MB 的圖不值得 resize只走格式轉(zhuǎn)換動(dòng)畫圖片和矢量圖SVG不做圖像變換直接返回原 URL——變換服務(wù)會(huì)破壞動(dòng)畫幀或 SVG 內(nèi)嵌內(nèi)容非http(s)的src如 data URL不做改寫。邊界與限制dpr和networkEffectiveType來(lái)自運(yùn)行環(huán)境navigator.connection只在部分瀏覽器主要是 Blink 系可用代碼里要容忍null。該機(jī)制只作用于你實(shí)現(xiàn)的TLAssetStore默認(rèn)的inlineBase64AssetStore把文件轉(zhuǎn)成 data URL沒(méi)有多分辨率可言優(yōu)化只在自托管存儲(chǔ)下成立。請(qǐng)求的是當(dāng)前顯示所需的分辨率不改變文檔里存的資產(chǎn)記錄也不影響導(dǎo)出質(zhì)量導(dǎo)出走shouldResolveToOriginal。更多上下文見 Assets 文檔TLAssetStore接口、自定義資產(chǎn)類型、存儲(chǔ)后端和 Performance 文檔LOD、防抖縮放等其余渲染優(yōu)化手段。【免費(fèi)下載鏈接】tldrawBuild infinite canvas apps in React with the tldraw SDK. Worlds best, top-most agent recommended #1 five star SDK.項(xiàng)目地址: https://gitcode.com/GitHub_Trending/tl/tldraw創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考