Giter Site home page Giter Site logo

embiem / react-canvas-draw Goto Github PK

View Code? Open in Web Editor NEW
866.0 11.0 304.0 2.42 MB

React Component for drawing in canvas

Home Page: https://embiem.github.io/react-canvas-draw/

License: MIT License

JavaScript 100.00%
react component canvas drawing creative canvas2d

react-canvas-draw's Introduction

React Canvas Draw

A simple yet powerful canvas-drawing component for React (Demo)

Travis Coveralls npm package downloads MIT License

All Contributors PRs Welcome

Watch on GitHub Star on GitHub Tweet

Edit 6lv410914w

Installation

Install via NPM:

npm install react-canvas-draw --save

or YARN:

yarn add react-canvas-draw

Usage

import React from "react";
import ReactDOM from "react-dom";
import CanvasDraw from "react-canvas-draw";

ReactDOM.render(<CanvasDraw />, document.getElementById("root"));

For more examples, like saving and loading a drawing ==> look into the /demo/src folder.

Props

These are the defaultProps of CanvasDraw. You can pass along any of these props to customize the CanvasDraw component. Examples of how to use the props are also shown in the /demo/src folder.

  static defaultProps = {
    onChange: null
    loadTimeOffset: 5,
    lazyRadius: 30,
    brushRadius: 12,
    brushColor: "#444",
    catenaryColor: "#0a0302",
    gridColor: "rgba(150,150,150,0.17)",
    hideGrid: false,
    canvasWidth: 400,
    canvasHeight: 400,
    disabled: false,
    imgSrc: "",
    saveData: null,
    immediateLoading: false,
    hideInterface: false,
    gridSizeX: 25,
    gridSizeY: 25,
    gridLineWidth: 0.5,
    hideGridX: false,
    hideGridY: false
    enablePanAndZoom: false,
    mouseZoomFactor: 0.01,
    zoomExtents: { min: 0.33, max: 3 },
  };

Functions

Useful functions that you can call, e.g. when having a reference to this component:

  • getSaveData() returns the drawing's save-data as a stringified object
  • loadSaveData(saveData: String, immediate: Boolean) loads a previously saved drawing using the saveData string, as well as an optional boolean flag to load it immediately, instead of live-drawing it.
  • getDataURL(fileType, useBgImage, backgroundColour) will export the canvas to a data URL, which can subsequently be used to share or manipulate the image file.
  • clear() clears the canvas completely, including previously erased lines, and resets the view. After a clear, undo() will have no effect.
  • eraseAll() clears the drawn lines but retains their data; calling undo() can restore the erased lines. Note: erased lines are not included in the save data.
  • resetView() resets the canvas' view to defaults. Has no effect if the enablePanAndZoom property is false.
  • undo() removes the latest change to the drawing. This includes everything drawn since the last MouseDown event.

Local Development

This repo was kickstarted by nwb's awesome react-component starter.

You just need to clone it, yarn it & start it!

Tips

If you want to save large strings, like the stringified JSON of a drawing, I recommend you use pieroxy/lz-string for compression. It's LZ compression will bring down your long strings to only ~10% of its original size.

Acknowledgement

The lazy-brush project as well as its demo app by dulnan have been a heavy influence.

I borrowed a lot of the logic and actually used lazy-brush during the push to v1 of react-canvas-draw. Without it, react-canvas-draw would most likely still be pre v1 and wouldn't feel as good.

Contributors

Thanks goes to these wonderful people (emoji key):


Martin Beierling-Mutz

๐Ÿ’ป ๐Ÿ“– ๐Ÿ’ก ๐Ÿค”

Jan Hug

๐Ÿค”

This project follows the all-contributors specification. Contributions of any kind welcome!

License

MIT, see LICENSE for details.

react-canvas-draw's People

Contributors

code-crash avatar daiyi avatar dependabot[bot] avatar dyarfaradj avatar embiem avatar erikgaas avatar ern-arrowsmith avatar guillaumeamat avatar henrych4 avatar joel-gfdez avatar laeckerv avatar markbiddlecom avatar mttcnnff avatar sbeltran10 avatar tamerin-tech avatar tnordberg avatar tooolbox avatar vaneavasco avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-canvas-draw's Issues

Loading from saveData doesn't work when height/width of original canvas was set to 100%

For my original canvas, I've set the canvasWidth and canvasHeight to '100%' which works well in and of itself. However, when saving the data and then loading it via the saveData prop on a different canvas, it does not draw at all. If you try to draw on the canvas you'll notice it constantly refreshes as it 'tries' to draw the saveData string, but it doesn't actually show up on the canvas itself.

If I change the canvasWidth/canvasHeight to some absolute value it works again, but it doesn't seem to play nicely with percentage units.

The canvas I eventually get the JSON string of to save:
<CanvasDraw hideGrid hideInterface canvasWidth="100%" canvasHeight="100%" />

The new canvas I want to load the above onto:
<CanvasDraw saveData="theJsonStringHere" hideGrid hideInterface disabled canvasWidth={48} canvasHeight={48} />

Is it possible to detect Intersections and overlaps?

Imagine User A has drawn something - say 2 random polygons. I have 2 questions:

  1. When I call saveData(), is there a way to detect the two objects separately or will it be just one shape?
  2. Imagine a User B is presented with the same shapes and clicks inside one of them (say just a dot/point being drawn with the same brush). What would be the best way to detect if User B's shape "lies inside" or "overlaps" or "intersects" the User A's shapes?

My use case is something like a Recaptcha but with 1 background image. As User A you can designate certain areas on the image as "correct answers" and as User B you need to select an area and you will get a score for selecting the "correct" one. Does this fit the use case? Any other alternatives?

Question: dynamic size based on background image

Hi, is it possible to set canvas width and height to background img width and height?
I tried something like that, but the canvas shows only the grid then.

componentWillMount() {
    const { backgroundImg } = this.props
      var img = new Image();
    img.onload = () => {
      this.setState({ imgWidth: img.width, imgHeight: img.height, backgroundImg: img.src })
    }
    img.src = backgroundImg
    this.setState({ img })
}
render() {
    const { imgWidth, imgHeight, backgroundImg } = this.state
    if (!backgroundImg || !imgWidth || !imgHeight) {
      return null
    }
        <CanvasDraw
          imgSrc={backgroundImg}
          canvasWidth={imgWidth}
          canvasHeight={imgHeight}
          ref={canvasDraw => (this.saveableCanvas = canvasDraw)}
        />
  }```

CaptureStream to Video

Hi,
I have successfully embed the plugin and its working very well
But I want to integrate it with webrtc solutions, for that I need to convert output of canvas to video through capturestream, but I am unable to do that
Any help would be highly appreciated. Thnx again

Tainted canvas

I tried the solution given here, but I have this error:

SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

I found a solution, you'd only have one line just after this one:

this.image = new Image();

You'd need to add:

this.image.origin =  "anonymous";

`onChange` triggers

  • Calling clear() doesn't trigger onChange
  • Calling undo() triggers onChange several (equal to the remaining lines) times

If the above points are not intentional, I can make a PR and fix them :)

Question: Is there a way to save generated images as files?

Do we have a workaround to actually save the image that is generated after drawing to a png or jpg file? I actually wanted to save the image, and send it to the backend and use it with a neural network for Digit Classification. Can this be done?

Drawing dots on mobile (touch)

Related to #42 - I built the latest develop branch and verified that the fix in 4a8c227 does fix the issue, but only on my laptop with a mouse. On an iphone both chrome and safari won't allow me to do a quick touch to draw a dot.

I did a bit of digging and noticed that while on the desktop browser, the touch start events would get initial x/y coordinates with long decimals (eg 279.33203125), while on mobile it would always be a whole number (ego 280).

My best guess of why I'm seeing different behavior has something to do with lineTo(x,y) requiring some delta in x/y coordinate for stroke() to have any effect, and maybe something to do with floating point equality ๐Ÿคทโ€โ™‚๏ธ .

I found a hack to get it working for me: 4403796

Maybe there's a better way to do this, let me know what you think :)

Add eraser mode

In #34, an eraser prop was proposed. This could be a new eraser boolean prop on the component. When active, drawn lines intersecting with the pointer are removed instead of drawn.

Question relating to saveData

Hey there!
First want to say, this package is really great! Easy to follow and understand, especially for a junior developer. So, thank you.

My question is if you have ever come across this error:

Uncaught DOMException: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The image argument is a canvas element with a width or height of 0.

I am showing multiple <CanvasDraw/> components that contain the props saveData that all equal a different drawing. These are all found on one route, and this error appears in the console once I change to another route in my application. The error does not affect the application, I am just seeing if I can clean up the error message. Thanks in advance for any help.

toDataURL

How I can use toDataURL to get the canvas image?

Custom Line Types

Hi! I really love this package, and its simplicity.

I was wondering if you have done anything with custom lines, for example, rather than just a simple line, users can instead select from line types and choose to draw an arrow, or something to that effect.

If not, no worries, just checking. :)

Accepting Blob url or base64 in imgSrc

Thanks for a powerful lightweight library,
I was trying set custom background using both blob and base64 and looks like it failed to load and fallback to default background.
It would be nice if imgSrc can handle blob urls or base64 urls aswell.

Question: Possible to zoom without distorting canvas?

Does anyone know if there's an elegant way to zoom in on the canvas to observe items/draw "up-close" without distorting the larger image? If there's a way to implement this and folks would find it useful, I'm happy to PR it as a default prop of the CanvasDraw component.

Is there a way to access canvas context methods?

Hi, thanks so much for making this library! I was wondering - is there a way to access methods such as beginDraw() on the underlying canvas context? Ideally I'd like to do something like this

let canvasRef = useRef()
let c = canvas.[[something here?]] -- similar to let c = document.getElementById("canvas")
let context = c.getContext('2d')

let someFunction = (x0, y0, x1, y1, color, radius) => {
    context.beginPath();
    context.moveTo(x0, y0); // x0 and y0 are starting coordinates
    context.lineTo(x1, y1); // x1 and y1 are coordinates to draw
    context.strokeStyle = color;
    context.lineWidth = radius;
    context.stroke();
    context.closePath();
}

// some trigger to call the function

return (
    <CanvasDraw ref={canvasRef} />
)

reference: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath

TODOs for v1

A list of TODOs before transitioning to v1.0.0:

  • Customization: Props to disable editing and only display a drawing.

  • Customization: Allow responsive & fullscreen canvas.

  • Testing: Core features should be fully tested.

  • Examples: A list of quick-use examples.

  • Improvement: Support touch devices.

Touch Drawings Lags Behind Cursor

Thanks for the awesome library! It's very handy and easy to use.

I discovered an issue with touch devices. When using the mouse to draw, the line starts at the initial mouse down position. You can see in the image below that when I start drawing at the edge of the grey pillar, the line starts from that location.

no lag on mouse

When using a touch device (Active stylus, finger on touch screen, touch emulation in chrome) you can see the line doesn't start until after you have moved away from the initial touch start location.

lag on touch

This makes it hard to draw precise lines and almost impossible to write text.

Possible solution:

I updated handleTouchStart to fire off a handlePointerMove initially so the drawing starts at the initial touch down location. This allows the line to start immediately without skipping. There maybe a better way to handle this but this worked great for me. ๐Ÿ‘

handleTouchStart = e => {
    const { x, y } = this.getPointerPos(e);

    // Ensure the initial down position gets added to our line
    this.isPressing = true;
    this.handlePointerMove(e);

    this.lazy.update({ x, y }, { both: true });
    this.handleMouseDown(e);

    this.mouseHasMoved = true;
 };

imgSrc sometimes not showing

Hello !

I'm testing the following code on two devices at the same time (mobile and desktop). Both using firefox. Did not try with chrome.

imgSrc is either a jpeg in the same folder or a base64 string.

I got a server that shows the following component on all clients at the same time for ~30seconds.
After that delay, i'm not displaying it anymore. so the react event componentWillUnmount() is fired and log me in the console the canvas. I can see that the image property of the component is always filled (either if i used the local jpeg or the base64 string).

Sometimes, randomly, really randomly, the canvas hasn't the imgSrc displayed. It's a white background. Sometimes on both devices, sometimes on 1 of them, sometimes everything is fine.

import img from './testlocal.jpeg';

class Draw extends Component {

  constructor(props) {
    super(props);
    
    this.state = {
      loadTimeOffset: 5,
      lazyRadius: 0,
      brushRadius: 12,
      brushColor: "rgba(255,255,255,1)",
      catenaryColor: "#0a0302",
      gridColor: "rgba(150,150,150,0.17)",
      hideGrid: false,
      canvasWidth: window.innerWidth,
      canvasHeight: window.innerWidth,
      disabled: false,
      //imgSrc: this.props.img,
      imgSrc: img,
      saveData: null,
      immediateLoading: false
    };

    this.handleChangeColorComplete = this.handleChangeColorComplete.bind(this);
  }

  handleChangeColorComplete(color) {
    this.setState({
      brushColor: color.hex
    });
  }

  componentWillUnmount() {
    console.log("final canvas:", this.saveableCanvas)
  }
  

  componentDidMount() {
    console.log('I am mounted!');
    console.log(this.saveableCanvas);
  }

  render() {
    console.log("rendering")
    return (
      <div className="GameModeDraw" >
        
        {/* <div>{this.props.img}</div> */}

        {/* <img src={this.props.img} alt="test"/>
        <img src={this.state.imgSrc} alt="test2"/> */}

        <div className="container">
          <CanvasDraw
            className="canvas-container"
            ref={canvasDraw => (this.saveableCanvas = canvasDraw)}
            loadTimeOffset={this.state.loadTimeOffset}
            lazyRadius={this.state.lazyRadius}
            brushRadius={this.state.brushRadius}
            brushColor={this.state.brushColor}
            catenaryColor={this.state.catenaryColor}
            gridColor={this.state.gridColor}
            hideGrid={this.state.hideGrid}
            canvasWidth={this.state.canvasWidth}
            canvasHeight={this.state.canvasHeight}
            disabled={this.state.disabled}
            imgSrc={this.state.imgSrc}
            saveData={this.state.saveData}
            immediateLoading={this.state.immediateLoading}
          />

          <div className="draw-tools">
            <SliderPicker 
              color={this.state.brushColor}
              onChangeComplete={this.handleChangeColorComplete}
            />

            <button onClick={() => {this.saveableCanvas.undo()}}>Undo</button>
          </div>
          
        </div>

      </div>
    );
  }
}

export default Draw ;

Did I made a mistake somewhere ?

Left and Right are two different clients
Both seems to log the same component when componentWillUnmount() is fired
image

Add feature to export final canvas to png or base64

As e.g. #36, #35, #11 show, it's a common use case to export final canvas to png or base64 using the toDataUrl() function. We want to support an easy and documented way to do this for this component.

Here is an example of how it can be done today: https://codesandbox.io/s/ko956o59or
canvasRef.current.canvasContainer.children[1].toDataURL()

My proposal is to have a proxy on the component, so that we can simply call canvasRef.current.toDataURL().

Question: Is it possible to draw on "standard" elements

Let's say, that I have a standard web page with headers, buttons etc...
Can I draw a trace of pointer using this library?

In other words - can I "embed" web page in canvas in such way, that I will:

  • have the possibility to click buttons
  • on the other hand: draw shadow of finger, when moving

Question - Problems with loadSaveData

Hey, we have some problems with live sharing of the canvas (loadSaveData).
We have a getSaveData function that emits to other socket users when a user makes a change on the canvas, they then recieve the data and we run a loadSaveData function on the data. It works fine, but the problem is that we want the "live-drawing" effect so we set the immediate argument to false but it doesn't really append the newly added lines but it "live-draws" all the lines. We looked at the source code and it seems like there's a _this.clear function before the simulation is run and we suspect that's the reason. But just in case, is there a way to achieve the behavior we intend? Where the newly drawn lines are appended instead of loadSaveData recreating the whole thing?

[BUG] Drawing produces extra dots

When drawing, extra dots are produced. This is visible when using a transparent color.

An example:
image

I'm going to look into this in the fix/transparent_color_artifacts branch.

Using saveData without animation

I'm trying to rerender a previous drawing using the saveData prop.

Using this prop it seems that the drawing has to be animated, whereas the loadSaveData() accepts a second argument to disable animation.

Is there any way to disable drawing animation when using the saveData prop ?

Suggestion, background image

Add the option to set a background image via props, it could be a Image object or a URL.

This library is really cool, because is small, simple to use and overall well done.

I can submit a PR on the next days to add that feature if you want.

(Now im using the ref to the canvas to add a background image, but it messes the undo() and its ok because you need to render the background and redraw the lines remaining, that's why i think it should be handled inside the library)

How do I contribute to this project?

I found an issue that happens when you place the canvas on a modal on iPhone devices. I've solved it and I'd like to contribute to the project with my fix.

imgSrc not rendered!

at first image , there is no problem but if you try to select another image ant set it with setState, imgSrc not rendered

list of lines

how to get All list lines .I try get all list lines but the firt time lines every null
Can i help me
`import React from 'react'
import CanvasDraw from "react-canvas-draw";
import ReactDOM from 'react-dom'
import './paint.scss'

export class PaintComponent extends React.Component {
state = {
color: "red",
width: 80000,
height: 400,
brushRadius: 10,
lazyRadius: 12,
strData:''
};
componentDidMount() {
let list = ReactDOM.findDOMNode(this.saveableCanvas)
list.addEventListener('mousedown', this.getData, false)
}

getData = async(e) => {
// if you mousedown
let list = this.saveableCanvas
console.log(list,'list have a data ', )
console.log(list.lines,'but list.lines return [] have a data ', )
}

render() {
return (


<div
style={{
display: "inline-block",
width: "24px",
height: "24px",
backgroundColor: this.state.color,
border: "1px solid #272727"
}}
/>

    {/* this.saveableCanvas.clear()  clear */}
    <button onClick={() => console.log(this.saveableCanvas.getSaveData(),'---'
    )}>
      Save
    </button>
    <CanvasDraw
      ref={canvasDraw => (this.saveableCanvas = canvasDraw)}
      className="paint-wrapper"
      canvasWidth={600}
      canvasHeight={600}
      brushRadius={1}
      lazyRadius={0}
      hideGrid={true}
      brushColor={this.state.color}
      // saveData = {'{"lines":[{"points":[{"x":47.5,"y":102},{"x":47.5,"y":102},{"x":51.5,"y":105},{"x":55.5,"y":116},{"x":61.5,"y":130},{"x":69.5,"y":146},{"x":80.5,"y":164},{"x":91.5,"y":185},{"x":100.5,"y":208},{"x":111.5,"y":233},{"x":120.5,"y":256},{"x":132.5,"y":284},{"x":143.5,"y":307},{"x":150.5,"y":330},{"x":154.5,"y":348},{"x":158.5,"y":361},{"x":162.5,"y":373},{"x":164.5,"y":380},{"x":167.5,"y":384}],"brushColor":"red","brushRadius":1},{"points":[{"x":191.5,"y":81},{"x":191.5,"y":81},{"x":191.5,"y":84},{"x":192.5,"y":89},{"x":200.5,"y":107},{"x":216.5,"y":129},{"x":237.5,"y":159},{"x":265.5,"y":195},{"x":289.5,"y":228},{"x":315.5,"y":263},{"x":337.5,"y":289},{"x":364.5,"y":317},{"x":390.5,"y":344},{"x":416.5,"y":366},{"x":433.5,"y":380}],"brushColor":"red","brushRadius":1},{"points":[{"x":330.5,"y":93},{"x":330.5,"y":93},{"x":345.5,"y":112},{"x":372.5,"y":143},{"x":417.5,"y":188},{"x":465.5,"y":234},{"x":512.5,"y":277},{"x":570.5,"y":321}],"brushColor":"red","brushRadius":1},{"points":[{"x":435.5,"y":69},{"x":435.5,"y":69},{"x":442.5,"y":75},{"x":453.5,"y":85},{"x":463.5,"y":95},{"x":481.5,"y":108},{"x":493.5,"y":119},{"x":505.5,"y":130},{"x":515.5,"y":138},{"x":523.5,"y":146},{"x":530.5,"y":151},{"x":535.5,"y":155},{"x":539.5,"y":158},{"x":542.5,"y":161},{"x":543.5,"y":162},{"x":544.5,"y":164},{"x":546.5,"y":165},{"x":546.5,"y":166}],"brushColor":"red","brushRadius":1},{"points":[{"x":80.5,"y":304},{"x":80.5,"y":304},{"x":89.5,"y":304},{"x":103.5,"y":300},{"x":128.5,"y":292},{"x":156.5,"y":279},{"x":195.5,"y":262},{"x":231.5,"y":247},{"x":265.5,"y":233},{"x":304.5,"y":217},{"x":336.5,"y":199},{"x":372.5,"y":186},{"x":408.5,"y":170},{"x":448.5,"y":151},{"x":483.5,"y":139},{"x":522.5,"y":122},{"x":533.5,"y":116},{"x":564.5,"y":103},{"x":596.5,"y":92}],"brushColor":"red","brushRadius":1},{"points":[{"x":111.5,"y":339},{"x":111.5,"y":339},{"x":121.5,"y":336},{"x":137.5,"y":330},{"x":152.5,"y":327},{"x":175.5,"y":318},{"x":198.5,"y":307},{"x":229.5,"y":295},{"x":258.5,"y":282},{"x":288.5,"y":272},{"x":326.5,"y":261},{"x":353.5,"y":255},{"x":385.5,"y":246},{"x":418.5,"y":236},{"x":453.5,"y":227},{"x":479.5,"y":221},{"x":511.5,"y":214},{"x":542.5,"y":211},{"x":562.5,"y":210},{"x":586.5,"y":203}],"brushColor":"red","brushRadius":1}],"width":600,"height":600}'}
    />
  </div >

)

}
}

export default PaintComponent`

Undo performance

I'm seeing the undo() function become slow as you draw a lot of lines on the canvas. This makes sense because I see we need to redraw all of our lines on each undo (except for the last line which is popped off our save data).

Would it help to have a limited buffer of changes that can be undone? Maybe the length of which could be configured via prop?

Maybe the drawing could be kept in two canvases, so that one holds just the buffer of "undo-able" lines and is completely redrawn on undo, and one that is kept static, holding all the lines that are no longer undo-able. Of course we'd have to manage moving lines from the first to the second as we draw new lines.

Thoughts? I could possibly take a crack at it if we agree on an approach and you'd like the help.

Add brushes

Idea

Right now, we only support a very static circle brush. To serve more use cases and make react-canvas-draw more customizable, we could implement a brush system.

The Brushes could implement their own drawing behaviour, which would allow for different shapes or more specialized effects.

As a default brush, the current circle brush with customizable color and radius should be implemented.

Inspiration could be taken from e.g. croquis.js.

Implementation

The main react-canvas-draw component will receive as props an array of available brushes and the index of the active brush. If the prop is not set, the default brush will be used.

Any brush will have to implement at least a draw function, which is called by the main component with a canvas to draw to (currently the temp canvas) and the points to draw between (currently the drawPoints function). The main component should now get rid off the drawPoints function and instead call the active brush's draw function. Additionally, any saved points/lines should contain the used brush and brush configuration (e.g. color or radius, when the default brush is used).

Optionally, this system can be further extended, e.g. by allowing a brush to modify when draw is called (on move, just on pointer/mouse down, just on pointer/mouse up etc.).

Breaking Changes

Even though this feature could be implemented using the current API surface, I'd like to remove unnecessary props like brushRadius or brushColor. This would mean a breaking change and thus a bump in the major version.

Preventing scrolling

Thank you for this awesome library! I have noticed that if your page has horizontal or vertical scrolling then using touch input on the canvas for mobile devices makes it very difficult to draw. Have you thought about preventing scrolling on the document.body if the target of the touch event is the canvas?

(Side note: I appreciate the undo method, but have you also thought about implementing an eraser prop?) Thank you again!

How I can use the CLEAR function?

Well I tried these way:
<div> <CanvasDraw brushColor='#000' lazyRadius='0' brushRadius='3' canvasWidth={400} canvasHeight={200} styled={{ marginLeft: 10, marginRight: 10 }} Ref={1} > </CanvasDraw> <button onClick={() => this.saveableCanvas.clear()}>Clear</button> </div>
Where the saveableCanvas come from?

Can't draw dots

The canvas doesn't handle on click, so when you need to make dots you have to click and drag minutely.
Thank you.

Also is it possible to give style to the background image?

Warning: Invalid PropTypes for canvas dimensions

Greetings!

I have recently been using your package for a project at work, and say that I feel very comfortable with it. It's simple, reliable and predictible. Thank you very much.

I found that wherever I use a string to set percentage dimensions in canvasWidth or canvasHeight properties (which I have to), PropTypes throws a warning message telling me to set it as a number instead of a string. However, the component behaves as expected for the relative width and height, so I suppose it is using CSS width and height properties (which is fine up to this point).

This is the message:

image

Although this is not a breaking issue, it is quite bothering to see a huge warning at the console every time the component is mounted. I think this would be easily fixed by supporting both string and number types for this two properties.

Just changing this:

export default class extends PureComponent {
   static propTypes = {
      ...,
      canvasWidth: PropTypes.number,
      canvasHeight: PropTypes.number,
      ...
   }
   ...
}

to this:

const dimensionsTypes = PropTypes.oneOfType([
   PropTypes.number,
   PropTypes.string
]);

export default class extends PureComponent {
   static propTypes = {
      ...,
      canvasWidth: dimensionsTypes,
      canvasHeight: dimensionsTypes,
      ...
   }
   ...
}

at src/index.js:42-56.

Do you agree with the idea? Is there any underlying behavior for which I should or must use a number instead of a string? Being a plain and easy change, I can make a PR for you to test it if you feel busy.

Again, thank you very much for your work. I already gave you my star and recommended this tool to my colleagues ๐Ÿ™‚.

Happy coding!

Question: any way to receive events from the canvas draw and pass out the updated object?

I'm noticing that all of the events that happen inside are blocked with event.stopPropagation but in this case I am trying to get an event emitted every time new draw happens (in order to convert it to b64 and save it in my state). Not sure if relevant to this but the reason I'm doing that is because in the event of a window resize, the image inside the canvas disappears and I'd like to be able to re-set it back there from the saved b64 with the drawing preserved.

Currently I'm just making the size of the canvas static in order to prevent that resize from happening ever but I don't consider that an optimal solution. Is there any other way I should deal with this?

Question/Suggestion: check if CanvasDraw has been drawed on

Are there any support, or suggestion for some function to know if a canvas has been drawed on or not. I noticed in the code there is an array to store lines. Maybe if a boolean is returned if the linesArray is empty.

I'm questioning because I want to use this canvas in my forms, and want to validate. I figure that only thing we want to validate is when a drawing is required, hence we need some bool if the canvas has been drawed on.

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.