Canvas element does not resize when using ReactJS and PaperJS together

7.2k views Asked by At

I have found that canvas elements correctly resize on window resize when they are inside react components. They also resize correctly when used with PaperJS. However, they do not resize when used with PaperJS and ReactJS together.

Is this an incompatibility between PaperJS and ReactJS or am I instantiating PaperJS incorrectly? I'm calling paper.setup(canvas) in the componentDidMount function of the react component which contains the canvas element. Is that the correct place to do this?

I've included code snippets below.

Note: For some reason the "Run code snippet" feature complains on the ReactJS snippets, so I've included JSFiddle links which work fine.

PaperJS Only [SUCCESS] - Canvas resizes on window resize https://jsfiddle.net/eadlam/srmracev/

// Instantiate the paperScope with the canvas element
var myCanvas = document.getElementById('myCanvas');
paper.setup(myCanvas);

// Draw a circle in the center
var width = paper.view.size.width;
var height = paper.view.size.height;
var circle = new paper.Shape.Circle({
  center: [width / 2, height / 2],
  fillColor: 'grey',
  radius: 10
});

// render
paper.view.draw();
canvas {
  width: 100%;
  height: 100%;
  border: solid 1px red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.9.22/paper-core.min.js"></script>
<canvas id="myCanvas" resize="true"></canvas>

ReactJS Only [SUCCESS] - Canvas resizes on window resize https://jsfiddle.net/eadlam/0de1mpoa/

var Canvas = React.createClass({
  render: function () {
    return <canvas id="myCanvas" resize="true"></canvas>;
  }
});

React.render(<Canvas/>, document.getElementById('container'));
canvas {
  width: 100%;
  height: 100%;
  border: solid 1px red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/JSXTransformer.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/react-with-addons.js"></script>
<script src="https://facebook.github.io/react/js/jsfiddle-integration.js"></script>

<div id="container"></div>

ReactJS + HMTL5 Canvas [FAIL] - Canvas does not resize on window resize https://jsfiddle.net/eadlam/jLo3opgq/

var Canvas = React.createClass({

    componentDidMount: function () {
        // Instantiate the paperScope with the canvas element
        var myCanvas = document.getElementById('myCanvas');
        paper.setup(myCanvas);
        
        // Draw a circle in the center
        var width = paper.view.size.width;
        var height = paper.view.size.height;
        var circle = new paper.Shape.Circle({
            center: [width / 2, height / 2],
            fillColor: 'grey',
            radius: 10
        });
        
        // render
        paper.view.draw();
    },

    render: function () {
        return <canvas id="myCanvas" resize="true"></canvas>;
    }
});

React.render(<Canvas/>, document.getElementById('container'));
canvas {
  width: 100%;
  height: 100%;
  border: solid 1px red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/JSXTransformer.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/react-with-addons.js"></script>
<script src="https://facebook.github.io/react/js/jsfiddle-integration.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.9.22/paper-core.min.js"></script>

<div id="container"></div>

2

There are 2 answers

1
Alexandre Kirszenberg On BEST ANSWER

You'll have to use the data-paper-resize prop, since React doesn't recognize the resize prop.

<canvas id="myCanvas" data-paper-resize />

See Canvas Configuration and Supported Attributes.

0
Lyu Zhijie On

One way to solve this, for example:

Create a paper canvas element:

import React from 'react'
import paper from 'paper'
import './paperCanvas.css'

class PaperCanvas extends React.Component{
    constructor(props){
        super(props)
        // modify state with functions if necessary, and inherit objects from props
        this.state = {
            height: window.innerHeight,
            width: window.innerWidth,
            circle: undefined
        }
        this.updateDimensions = this.updateDimensions.bind(this);
        this.resizeMethod = this.resizeMethod.bind(this)
    }

    componentDidMount(){
        paper.setup('paperCanvas')
        this.state.circle = new paper.Path.Circle({
            center: paper.view.center,
            radius: 50,
            fillColor: 'orange'
        })
        paper.view.draw()
        window.addEventListener('resize', this.resizeMethod)
    }

    updateDimensions() {
        this.setState({
           height: window.innerHeight,
           width: window.innerWidth
         });
    }

    resizeMethod(){
        this.updateDimensions()
        this.state.circle.position = new paper.Point(this.state.width/2, this.state.height/2)
        console.log(this.state.width/2, this.state.height/2)
    }

    render(){
        return(
            <canvas id="paperCanvas" 
                height={this.state.height}
                width={this.state.width}>
            </canvas>
        )
    }
}

export default PaperCanvas

In paperCanvas.css:

#paperCanvas {
    position: absolute;
    background: transparent;
    left: 0px;
    top: 0px;
    z-index: 0; 
}