script react helmet change reactjs fabricjs react-canvas

reactjs - helmet - ¿Cómo puedo usar Fabric.js con React?



react js change title (3)

Tengo una aplicación que utiliza mucho canvas de HTML5 a través de Fabric.js . La aplicación está escrita sobre Angular 1.x, y estoy planeando migrarla a React . Mi aplicación permite escribir texto y dibujar líneas, rectángulos y elipses. También es posible mover, agrandar, reducir, seleccionar, cortar, copiar y pegar uno o más de dichos objetos. También es posible hacer zoom y desplazarse por el lienzo usando varios accesos directos. En resumen, mi aplicación utiliza Fabric.js en toda su extensión.

No pude encontrar mucha información sobre cómo usar Fabric.js junto con Reaccionar, por lo que mi preocupación es que 1. ¿es posible sin mayores modificaciones ?, y 2. ¿tiene sentido o debería usar alguna otra biblioteca extensiva de lienzos que tiene un mejor soporte para Reaccionar?

El único ejemplo de React + Fabric.js que pude encontrar fue react-komik , que sin embargo es mucho más simple que mi aplicación. Mi principal preocupación es el procesamiento de eventos y la manipulación DOM de Fabric.js, y su efecto en React.

Parece que también hay una biblioteca de lienzo para React, llamada react-canvas , pero parece que le faltan muchas funciones en comparación con Fabric.js.

¿Qué debo tener en cuenta (con respecto a la manipulación del DOM, el procesamiento de eventos, etc.) cuando uso Fabric.js en una aplicación de React?


He usado Fabric para un proyecto de prueba de concepto y la idea general es la misma que, por ejemplo, para D3. Tenga en cuenta que Fabric opera sobre elementos DOM, mientras que React procesa datos en DOM, y generalmente este último se difiere. Hay dos cosas que te ayudarán a asegurarte de que tu código funcione:

Espere hasta que se monte el componente

Para hacer eso, coloque su instanciación Fabric en componentDidMount :

import React, { Component } from ''react''; import { fabric } from ''react-fabricjs''; import styles from ''./MyComponent.css''; class MyComponent extends Component { componentWillMount() { // dispatch some actions if you use Redux } componentDidMount() { const canvas = new fabric.Canvas(''c''); // do some stuff with it } render() { return ( <div className={styles.myComponent}> <canvas id="c" /> </div> ) } }

Colocar Fabric constructor en componentDidMount asegura que no fallará porque en el momento en que se ejecuta este método, el DOM está listo. (pero los accesorios a veces no son, por si acaso si usas Redux)

Use referencias para calcular el ancho y la altura real

Las referencias son referencias a elementos DOM reales. Puede hacer con los refs lo que puede hacer con los elementos DOM utilizando la API DOM: seleccione elementos innerHeight , encuentre elementos principales, asigne propiedades de estilo, calcule innerHeight e innerWidth . Esto último es precisamente lo que necesitas:

componentDidMount() { const canvas = new fabric.Canvas(''c'', { width: this.refs.canvas.clientWidth, height: this.refs.canvas.clientHeight }); // do some stuff with it }

No te olvides de definir la propiedad de los refs de this . Para hacer eso, necesitarás un constructor. Todo se vería como

import React, { Component } from ''react''; import { fabric } from ''react-fabricjs''; import styles from ''./MyComponent.css''; class MyComponent extends Component { constructor() { super() this.refs = { canvas: {} }; } componentWillMount() { // dispatch some actions if you use Redux } componentDidMount() { const canvas = new fabric.Canvas(''c'', { width: this.refs.canvas.clientWidth, height: this.refs.canvas.clientHeight }); // do some stuff with it } render() { return ( <div className={styles.myComponent}> <canvas id="c" ref={node => { this.refs.canvas = node; } /> </div> ) } }

Mezcle la tela con estado de componentes o accesorios

Puede hacer que su instancia de Fabric reaccione ante cualquier accesorio de componente o actualizaciones de estado. Para que funcione, simplemente actualice su instancia Fabric (que, como puede ver, puede almacenar como parte de las propiedades propias del componente) en componentDidUpdate . El simple hecho de confiar en las llamadas a la función de render no será de gran ayuda, ya que ninguno de los elementos que se procesan cambiará nunca en los nuevos accesorios o el nuevo estado. Algo como esto:

import React, { Component } from ''react''; import { fabric } from ''react-fabricjs''; import styles from ''./MyComponent.css''; class MyComponent extends Component { constructor() { this.refs = { canvas: {} }; } componentWillMount() { // dispatch some actions if you use Redux } componentDidMount() { const canvas = new fabric.Canvas(''c'', { width: this.refs.canvas.clientWidth, height: this.refs.canvas.clientHeight }); this.fabric = canvas; // do some initial stuff with it } componentDidUpdate() { const { images = [] } = this.props; const { fabric } = this; // do some stuff as new props or state have been received aka component did update images.map((image, index) => { fabric.Image.fromURL(image.url, { top: 0, left: index * 100 // place a new image left to right, every 100px }); }); } render() { return ( <div className={styles.myComponent}> <canvas id="c" ref={node => { this.refs.canvas = node; } /> </div> ) } }

Simplemente reemplace el procesamiento de imágenes con el código que necesita y eso depende del nuevo estado del componente o de los accesorios. ¡No olvide limpiar el lienzo antes de representar nuevos objetos en él!


También hay react-fabricjs paquete react-fabricjs que le permite usar objetos de tela como componentes de reacción. En realidad, la respuesta de Rishat incluye este paquete, pero no entiendo cómo se supone que funciona, ya que no hay ningún objeto ''fabric'' en reaccionar-fabricjs (probablemente se refería al paquete ''fabric-webpack''). Un ejemplo para el componente simple ''Hola mundo'':

import React from ''react''; import {Canvas, Text} from ''react-fabricjs''; const HelloFabric = React.createClass({ render: function() { return ( <Canvas width="900" height="900"> <Text text="Hello World!" left={300} top={300} fill="#000000" fontFamily="Arial" /> </Canvas> ); } }); export default HelloFabric;

Incluso si no desea utilizar este paquete, explorar su código puede ayudarlo a comprender cómo implementar Fabric.js en React.


Tuvimos el mismo problema en nuestra aplicación de cómo usar Fabric.js dentro de reaccionar. Mi recomendación es tratar la tela como un componente descontrolado. Tenga una instancia de fabric con la que toda su aplicación pueda hablar y haga llamadas de fabric y luego, cuando algo cambie, use la llamada a .toObject() para poner todo el estado de la tela en su tienda de Redux. Luego, su aplicación React puede leer el estado de la tela de su estado global de Redux como lo haría en cualquier aplicación React normal.

No puedo obtener un ejemplo que funcione en el editor de código de , pero aquí hay un ejemplo de JSFiddle que implementa el patrón que estoy recomendando.