Code Monkey home page Code Monkey logo

react-measure-text-worker's Introduction

πŸ“ react-measure-text-worker πŸ”¨

An experimental React component that performs expensive text measurements off the main thread and return results to the component's children.

Demo

Background

Problem

Require ability to dynamically measure text for width, height, and other style attributes off-thread without interacting with DOM.

Concepts

Three main concepts:

  1. WebWorker work is done off the main UI thread.
  2. With the introduction of OffscreenCanvas in Chrome 69, we can now perform Canvas work in a WebWorker.
  3. Inside a Canvas, you can do some powerful calculations on styles and positioning.

Let's combine these three concepts in the context of an application that does significant DOM or Canvas measuring. We can move these expensive calculations off the main thread by performing the same calculations inside a Canvas on a separate thread via a WebWorker. This will allow the main thread (UI thread) to free up resources, and allow the main thread to run smoothly and maintain a desired 60fps.

More details on OffscreenCanvas with WebWorkers can be found here

Solution - Declarative Approach

<MeasureTextOffThread/>

A React component that is able to handle expensive measurments of text attributes off-thread in a WebWorker, which then returns the requested measurements to the main thread for handing off to child components.

Getting Started

Clone the repo, install the dependencies, and run the dev environment. That's it!

git clone https://github.com/johnrjj/react-measure-text-worker.git
yarn install
yarn start

Navigate to localhost:1234 to see the app running

API

MeasureTextOffThread renders a "child as a function" pattern which provides a textData object to the children, which the children can then use to render however they would like.

import { MeasureTextOffThread } from 'react-measure-text-off-thread';

const text = 'measure this text';

// inside render...
<MeasureTextOffThread
  text={text}
  fontSize={20}
  fontFamily={'Arial'}
>
{textData => (
  <span>
    <div style={{ width: textData.width, height: textdata.height }}>
    	Do overlay here
    </div>
    <span>{text}</span>
  </span>
)}
</MeasureTextOffThread>

Architecture

       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                                                     
       β”‚           β”‚                                                                                     
       β”‚    App    β”‚                     thread                                                          
       β”‚           β”‚                    boundary                                                         
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                                                                     
             β”‚                              β”‚                                                            
             β”‚                                                                                           
             β”‚                              β”‚                                                            
             β”‚                postMessage         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                    
             β–Ό                request to    β”‚     β”‚                 β”‚                                    
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    webworker          β”‚    WebWorker    β”‚                                    
β”‚                         │─────────────────┼────▢│    onmessage    │────────────────────┐               
β”‚ </MeasureTextOffThread> │◀────────┐             β”‚                 β”‚                    β–Ό               
β”‚                         β”‚         β”‚       β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚                                          β”‚                  β”‚     β”‚
             β”‚                      β”‚       β”‚                                  β”‚ Worker processes β”‚ LRU β”‚
             β”‚                      β”‚                                          β”‚      request     β”‚cacheβ”‚
             β”‚                      β”‚       β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚                  β”‚     β”‚
    ({ width, height })             β”‚          β”‚                           β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”˜
             β”‚                      β”‚       β”‚  β”‚ postMessage Response Bus  β”‚             β”‚               
             β”‚                      └─────────◀│         (shared)          β”‚β—€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               
             β–Ό                              β”‚  β”‚                           β”‚       send response         
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      payload to bus         
β”‚                         β”‚                 β”‚                                                            
β”‚        children         β”‚                                                                              
β”‚                         β”‚                 β”‚                                                            
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                                                              

Performance

πŸ”₯ It's really fast.

react-measure-text-worker's People

Contributors

johnrjj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

codeurs2020

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.