You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Jul 19, 2019. It is now read-only.
I am trying to create a PaperJS bridge similar to ReactARTFiber. I have a few questions about the integration, and I thought this was the best place to ask them, since I basically copy-pasted the code for ReactARTFiber.js.
Note that I use a custom version of React 16.0.0-alpha.12, where I export ReactFiberReconciler through react-dom package.
I have a few problems specific to how PaperJS works. Also check out this issue
This is my PaperRenderer
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import paper from 'paper'
import invariant from 'fbjs/lib/invariant'
import emptyObject from 'fbjs/lib/emptyObject'
import { ReactFiberReconciler } from 'react-dom'
const TYPES = {
LAYER: 'Layer',
GROUP: 'Group',
PATH: 'Path',
CIRCLE: 'Circle',
TOOL: 'Tool',
}
const Layer = TYPES.LAYER
const Group = TYPES.GROUP
const Path = TYPES.PATH
const Circle = TYPES.CIRCLE
const Tool = TYPES.TOOL
class Paper extends Component {
static propTypes = {
activeTool: PropTypes.string,
height: PropTypes.number,
onWheel: PropTypes.func,
width: PropTypes.number,
zoom: PropTypes.number,
}
componentDidMount() {
const { activeTool, children, height, width, zoom } = this.props
this._paper = new paper.PaperScope()
this._paper.setup(this._canvas)
this._paper.view.viewSize = new paper.Size(width, height)
this._paper.view.zoom = zoom
this._mountNode = PaperRenderer.createContainer(this._paper)
PaperRenderer.updateContainer(
children,
this._mountNode,
this,
)
this._paper.view.draw()
if (activeTool) {
this._paper.tools.forEach(tool => {
if (tool.name === activeTool) {
tool.activate()
}
})
}
}
componentDidUpdate(prevProps, prevState) {
const { activeTool, children, height, width, zoom } = this.props
if (width !== prevProps.width || height !== prevProps.height) {
this._paper.view.viewSize = new paper.Size(width, height)
}
if (zoom !== prevProps.zoom) {
this._paper.view.zoom = zoom
}
PaperRenderer.updateContainer(
children,
this._mountNode,
this,
)
this._paper.view.draw()
if (activeTool !== prevProps.activeTool) {
this._paper.tools.forEach(tool => {
if (tool.name === activeTool) {
tool.activate()
}
})
}
}
componentWillUnmount() {
PaperRenderer.updateContainer(
null,
this._mountNode,
this,
)
}
render() {
const { height, onWheel, width } = this.props
const canvasProps = {
ref: ref => this._canvas = ref,
height,
onWheel,
width,
}
return (
<canvas {...canvasProps} />
)
}
}
function applyLayerProps(instance, props, prevProps = {}) {
// TODO
}
function applyToolProps(tool, props, prevProps = {}) {
// TODO
}
function applyGroupProps(tool, props, prevProps = {}) {
// TODO
}
function applyCircleProps(instance, props, prevProps = {}) {
if (props.center !== prevProps.center) {
instance.center = new paper.Point(props.center)
}
if (props.strokeColor !== prevProps.strokeColor) {
instance.strokeColor = props.strokeColor
}
if (props.strokeWidth !== prevProps.strokeWidth) {
instance.strokeWidth = props.strokeWidth
}
if (props.fillColor !== prevProps.fillColor) {
instance.fillColor = props.fillColor
}
}
function applyPathProps(instance, props, prevProps = {}) {
if (props.strokeColor !== prevProps.strokeColor) {
instance.strokeColor = props.strokeColor
}
if (props.strokeWidth !== prevProps.strokeWidth) {
instance.strokeWidth = props.strokeWidth
}
}
const PaperRenderer = ReactFiberReconciler({
appendChild(parentInstance, child) {
if (child.parentNode === parentInstance) {
child.remove()
}
if (
child instanceof paper.Path &&
(
parentInstance instanceof paper.Layer ||
parentInstance instanceof paper.Group
)
) {
child.addTo(parentInstance)
}
},
appendInitialChild(parentInstance, child) {
if (typeof child === 'string') {
// Noop for string children of Text (eg <Text>{'foo'}{'bar'}</Text>)
invariant(false, 'Text children should already be flattened.')
return
}
if (
child instanceof paper.Path &&
(
parentInstance instanceof paper.Layer ||
parentInstance instanceof paper.Group
)
) {
child.addTo(parentInstance)
}
},
commitTextUpdate(textInstance, oldText, newText) {
// Noop
},
commitMount(instance, type, newProps) {
// Noop
},
commitUpdate(instance, updatePayload, type, oldProps, newProps, internalInstanceHandle) {
instance._applyProps(instance, newProps, oldProps)
},
createInstance(type, props, internalInstanceHandle) {
const { children, ...paperProps } = props
let instance
switch (type) {
case TYPES.TOOL:
instance = new paper.Tool(paperProps)
instance._applyProps = applyToolProps
break
case TYPES.LAYER:
instance = new paper.Layer(paperProps)
instance._applyProps = applyLayerProps
break
case TYPES.GROUP:
instance = new paper.Group(paperProps)
instance._applyProps = applyGroupProps
break
case TYPES.PATH:
instance = new paper.Path(paperProps)
instance._applyProps = applyPathProps
break
case TYPES.CIRCLE:
instance = new paper.Path.Circle(paperProps)
instance._applyProps = applyCircleProps
break
}
invariant(instance, 'PaperReact does not support the type "%s"', type)
instance._applyProps(instance, props)
return instance
},
createTextInstance(text, rootContainerInstance, internalInstanceHandle) {
return text
},
finalizeInitialChildren(domElement, type, props) {
return false
},
insertBefore(parentInstance, child, beforeChild) {
invariant(
child !== beforeChild,
'PaperReact: Can not insert node before itself'
)
child.insertAbove(beforeChild)
},
prepareForCommit() {
// Noop
},
prepareUpdate(domElement, type, oldProps, newProps) {
return true
},
removeChild(parentInstance, child) {
//destroyEventListeners(child)
child.remove()
},
resetAfterCommit() {
// Noop
},
resetTextContent(domElement) {
// Noop
},
getRootHostContext() {
return emptyObject
},
getChildHostContext() {
return emptyObject
},
scheduleAnimationCallback: window.requestAnimationFrame,
scheduleDeferredCallback: window.requestIdleCallback,
shouldSetTextContent(props) {
return (
typeof props.children === 'string' ||
typeof props.children === 'number'
)
},
useSyncScheduling: true,
})
export {
Paper,
Layer,
Path,
Circle,
Group,
Tool,
}
This might be a stupid question, but is there a way to reverse the process of calling createInstance? I would like to create parent instance before its children.
For example, this is the order in which PaperJS instances are created:
createInstance Path
createInstance Circle
createInstance Group
createInstance Layer
createInstance Path
createInstance Circle
createInstance Group
createInstance Layer
createInstance Circle (3x)
createInstance Layer
createInstance Tool (2x)
For example: even though Path is a child of Layer, its instance is created before Layer. Problem is, when I create a new paper.Path, if there is no paper.Layer yet, PaperJS automatically creates one for me. So I end up with 4 paper.Layers instead of 3.
Next problem I have is, when I change zoom for example. My entire Paper tree is re-rendered, executing unnecessary calls to commitUpdate, when all I need to do is set this._paper.view.zoom = zoom in PapercomponentDidUpdate. How can I optimize this? What is the right/best way? Basically I could completely skip this piece of code:
Hi :)
I am trying to create a
PaperJS
bridge similar toReactARTFiber
. I have a few questions about the integration, and I thought this was the best place to ask them, since I basically copy-pasted the code for ReactARTFiber.js.Note that I use a custom version of React 16.0.0-alpha.12, where I export
ReactFiberReconciler
throughreact-dom
package.I have a few problems specific to how PaperJS works. Also check out this issue
This is my
PaperRenderer
This is my JSX structure
Questions:
This might be a stupid question, but is there a way to reverse the process of calling createInstance? I would like to create parent instance before its children.
For example, this is the order in which PaperJS instances are created:
For example: even though
Path
is a child ofLayer
, its instance is created beforeLayer
. Problem is, when I create a newpaper.Path
, if there is nopaper.Layer
yet, PaperJS automatically creates one for me. So I end up with 4paper.Layers
instead of 3.Next problem I have is, when I change
zoom
for example. My entire Paper tree is re-rendered, executing unnecessary calls tocommitUpdate
, when all I need to do is setthis._paper.view.zoom = zoom
inPaper
componentDidUpdate
. How can I optimize this? What is the right/best way? Basically I could completely skip this piece of code:I am also trying to figure out how to write tests. PaperJS supports node-canvas and offers import/export to SVG and JSON. Maybe I can use that.
Any other advice? I was looking at the react source code, but it's big, not really sure yet where to start :)
The text was updated successfully, but these errors were encountered: