From df5be8ecd934ef17bf491562e187ec610671e0a8 Mon Sep 17 00:00:00 2001 From: Kashif Ghaffar Asim Date: Sun, 22 Mar 2020 11:44:15 +0500 Subject: [PATCH 01/10] Image Issue Fixed --- .gitignore | 1 + examples/main.jsx | 33 ++++++++------- src/SketchField.jsx | 98 ++++++++++++++------------------------------- src/fabrictool.js | 2 +- src/index.js | 4 +- 5 files changed, 51 insertions(+), 87 deletions(-) diff --git a/.gitignore b/.gitignore index 752b9500..5343b86c 100644 --- a/.gitignore +++ b/.gitignore @@ -180,3 +180,4 @@ $RECYCLE.BIN/ # Windows shortcuts *.lnk +/nbproject/private/ \ No newline at end of file diff --git a/examples/main.jsx b/examples/main.jsx index 6d242d54..7b870fda 100644 --- a/examples/main.jsx +++ b/examples/main.jsx @@ -94,6 +94,7 @@ const styles = { } }; + console.log(Tools) /** * Helper function to manually fire an event * @@ -111,6 +112,7 @@ function eventFire(el, etype) { } class SketchFieldDemo extends React.Component { + constructor(props) { super(props); @@ -121,7 +123,7 @@ class SketchFieldDemo extends React.Component { backgroundColor: 'transparent', shadowWidth: 0, shadowOffset: 0, - tool: Tools.Pencil, + tool: Tools.Select, enableRemoveSelected: false, fillWithColor: false, fillWithBackgroundColor: false, @@ -143,7 +145,7 @@ class SketchFieldDemo extends React.Component { expandBack: false, expandImages: false, expandControlled: false, - text: 'a text, cool!', + text: 'Testing!', enableCopyPaste: false, }; } @@ -163,14 +165,8 @@ class SketchFieldDemo extends React.Component { }; _download = () => { - console.save(this._sketch.toDataURL(), 'toDataURL.txt'); - console.save(JSON.stringify(this._sketch.toJSON()), 'toDataJSON.txt'); - - /*eslint-enable no-console*/ - let { imgDown } = this.refs; let event = new Event('click', {}); - imgDown.href = this._sketch.toDataURL(); imgDown.download = 'toPNG.png'; imgDown.dispatchEvent(event); @@ -267,6 +263,7 @@ class SketchFieldDemo extends React.Component { _addText = () => this._sketch.addText(this.state.text); componentDidMount = () => { + console.log('here'); (function(console) { console.save = function(data, filename) { if (!data) { @@ -300,6 +297,9 @@ class SketchFieldDemo extends React.Component { secondary: { main: '#11cb5f' }, // This is just green.A700 as hex. }, }); + + + return (
@@ -339,7 +339,9 @@ class SketchFieldDemo extends React.Component {
+
+ this.setState({ expandImages: !this.state.expandImages })}> + this.setState({ expandImages: !this.state.expandImages })}> }/> +
@@ -627,9 +629,7 @@ class SketchFieldDemo extends React.Component { value={this.state.imageUrl}/>
@@ -642,6 +642,8 @@ class SketchFieldDemo extends React.Component {
+ +
- {/* Sketch area */} -
-
diff --git a/src/SketchField.jsx b/src/SketchField.jsx index 5e8b6f7c..6e5495f0 100644 --- a/src/SketchField.jsx +++ b/src/SketchField.jsx @@ -2,6 +2,7 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; + import History from './history'; import {uuid4} from './utils'; import Select from './select'; @@ -18,6 +19,7 @@ const fabric = require('fabric').fabric; /** * Sketch Tool based on FabricJS for React Applications */ + class SketchField extends PureComponent { static propTypes = { @@ -60,6 +62,8 @@ class SketchField extends PureComponent { style: PropTypes.object, }; + + static defaultProps = { lineColor: 'black', lineWidth: 10, @@ -67,7 +71,7 @@ class SketchField extends PureComponent { backgroundColor: 'transparent', opacity: 1.0, undoSteps: 25, - tool: Tool.Pencil, + tool: Tool.Circle, widthCorrection: 2, heightCorrection: 0, forceValue: false @@ -77,6 +81,7 @@ class SketchField extends PureComponent { parentWidth: 550, action: true }; + _initTools = (fabricCanvas) => { this._tools = {}; this._tools[Tool.Select] = new Select(fabricCanvas); @@ -120,7 +125,9 @@ class SketchField extends PureComponent { * } */ addImg = (dataUrl, options = {}) => { + let canvas = this._fc; + fabric.Image.fromURL(dataUrl, (oImg) => { let opts = { left: Math.random() * (canvas.getWidth() - oImg.width * 0.5), @@ -315,6 +322,8 @@ class SketchField extends PureComponent { zoom = (factor) => { let canvas = this._fc; let objects = canvas.getObjects(); + + for (let i in objects) { objects[i].scaleX = objects[i].scaleX * factor; objects[i].scaleY = objects[i].scaleY * factor; @@ -356,6 +365,7 @@ class SketchField extends PureComponent { * Perform a redo operation on canvas, if it cannot redo it will leave the canvas intact */ redo = () => { + let history = this._history; if (history.canRedo()) { let canvas = this._fc; @@ -396,42 +406,11 @@ class SketchField extends PureComponent { return this._history.canRedo() }; - /** - * Exports canvas element to a dataurl image. Note that when multiplier is used, cropping is scaled appropriately - * - * Available Options are - * - * - * - * - * - * - * - * - * - * - * - *
NameTypeArgumentDefaultDescription
format String pngThe format of the output image. Either "jpeg" or "png"
qualityNumber1Quality level (0..1). Only used for jpeg.
multiplierNumber1Multiplier to scale by
leftNumberCropping left offset. Introduced in v1.2.14
topNumberCropping top offset. Introduced in v1.2.14
widthNumberCropping width. Introduced in v1.2.14
heightNumberCropping height. Introduced in v1.2.14
- * - * @returns {String} URL containing a representation of the object in the format specified by options.format - */ + toDataURL = (options) => this._fc.toDataURL(options); - /** - * Returns JSON representation of canvas - * - * @param propertiesToInclude Array Any properties that you might want to additionally include in the output - * @returns {string} JSON string - */ toJSON = (propertiesToInclude) => this._fc.toJSON(propertiesToInclude); - /** - * Populates canvas with data from the specified JSON. - * - * JSON format must conform to the one of fabric.Canvas#toDatalessJSON - * - * @param json JSON string or object - */ fromJSON = (json) => { if (!json) return; let canvas = this._fc; @@ -445,13 +424,6 @@ class SketchField extends PureComponent { }, 100) }; - /** - * Clear the content of the canvas, this will also clear history but will return the canvas content as JSON to be - * used as needed in order to undo the clear if possible - * - * @param propertiesToInclude Array Any properties that you might want to additionally include in the output - * @returns {string} JSON string of the canvas just cleared - */ clear = (propertiesToInclude) => { let discarded = this.toJSON(propertiesToInclude); this._fc.clear(); @@ -459,9 +431,6 @@ class SketchField extends PureComponent { return discarded }; - /** - * Remove selected object from the canvas - */ removeSelected = () => { let canvas = this._fc; let activeObj = canvas.getActiveObject(); @@ -551,12 +520,17 @@ class SketchField extends PureComponent { addText = (text, options = {}) => { let canvas = this._fc; + console.log('canvas') + console.log(canvas); + console.log('canvas') let iText = new fabric.IText(text, options); + let opts = { left: (canvas.getWidth() - iText.width) * 0.5, top: (canvas.getHeight() - iText.height) * 0.5, }; Object.assign(options, opts); + iText.set({ 'left': options.left, 'top': options.top @@ -574,12 +548,7 @@ class SketchField extends PureComponent { backgroundColor } = this.props; - let canvas = this._fc = new fabric.Canvas(this._canvas/*, { - preserveObjectStacking: false, - renderOnAddRemove: false, - skipTargetFind: true - }*/); - + let canvas = this._fc = new fabric.Canvas(this._canvas); this._initTools(canvas); // set initial backgroundColor @@ -606,11 +575,7 @@ class SketchField extends PureComponent { canvas.on('object:moving', this._onObjectMoving); canvas.on('object:scaling', this._onObjectScaling); canvas.on('object:rotating', this._onObjectRotating); - // IText Events fired on Adding Text - // canvas.on("text:event:changed", console.log) - // canvas.on("text:selection:changed", console.log) - // canvas.on("text:editing:entered", console.log) - // canvas.on("text:editing:exited", console.log) + this.disableTouchScroll(); @@ -659,21 +624,20 @@ class SketchField extends PureComponent { let canvasDivStyle = Object.assign({}, style ? style : {}, width ? { width: width } : {}, height ? { height: height } : { height: 512 }); - return ( -
this._container = c} - style={canvasDivStyle}> - this._canvas = c}> - Sorry, Canvas HTML5 element is not supported by your browser - :( - -
+
this._container = c} + style={canvasDivStyle}> + this._canvas = c}> + Sorry, Canvas HTML5 element is not supported by your browser + :( + +
) } } -export default SketchField \ No newline at end of file +export default SketchField diff --git a/src/fabrictool.js b/src/fabrictool.js index 05125b98..94d66996 100644 --- a/src/fabrictool.js +++ b/src/fabrictool.js @@ -29,4 +29,4 @@ class FabricCanvasTool { } } -export default FabricCanvasTool; \ No newline at end of file +export default FabricCanvasTool; diff --git a/src/index.js b/src/index.js index d075d846..cf158267 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,10 @@ import SketchField from './SketchField' import Tools from './tools' -export {SketchField} +export { SketchField } export {Tools} export default { SketchField, Tools -}; \ No newline at end of file +}; From cf95afe867df939cc340699dc43a7bca8c3f20b7 Mon Sep 17 00:00:00 2001 From: Kashif Ghaffar Asim Date: Tue, 24 Mar 2020 11:37:05 +0500 Subject: [PATCH 02/10] Commit files --- examples/main.jsx | 24 +++++++++++++++---- src/SketchField.jsx | 56 +++++++++++++++------------------------------ 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/examples/main.jsx b/examples/main.jsx index 6d242d54..8a3ba98c 100644 --- a/examples/main.jsx +++ b/examples/main.jsx @@ -121,7 +121,7 @@ class SketchFieldDemo extends React.Component { backgroundColor: 'transparent', shadowWidth: 0, shadowOffset: 0, - tool: Tools.Pencil, + tool: Tools.Select, enableRemoveSelected: false, fillWithColor: false, fillWithBackgroundColor: false, @@ -145,6 +145,7 @@ class SketchFieldDemo extends React.Component { expandControlled: false, text: 'a text, cool!', enableCopyPaste: false, + isOpen: false }; } @@ -158,15 +159,19 @@ class SketchFieldDemo extends React.Component { _save = () => { let drawings = this.state.drawings; + console.log(drawings) drawings.push(this._sketch.toDataURL()); - this.setState({ drawings: drawings }); + this.setState({ drawings: drawings, isOpen: true }); }; + _open = () =>{ + if(this.state.isOpen == true){ + this.setState({drawings: drawings }) + } + } + _download = () => { console.save(this._sketch.toDataURL(), 'toDataURL.txt'); - console.save(JSON.stringify(this._sketch.toJSON()), 'toDataJSON.txt'); - - /*eslint-enable no-console*/ let { imgDown } = this.refs; let event = new Event('click', {}); @@ -307,6 +312,14 @@ class SketchFieldDemo extends React.Component { Sketch Tool + + + + + (this._sketch = c)} lineColor={this.state.lineColor} lineWidth={this.state.lineWidth} + removeItem={this._removeSelected} fillColor={ this.state.fillWithColor ? this.state.fillColor diff --git a/src/SketchField.jsx b/src/SketchField.jsx index 5e8b6f7c..a0bf341f 100644 --- a/src/SketchField.jsx +++ b/src/SketchField.jsx @@ -1,6 +1,6 @@ /*eslint no-unused-vars: 0*/ -import React, {PureComponent} from 'react'; +import React, {PureComponent, useEffect} from 'react'; import PropTypes from 'prop-types'; import History from './history'; import {uuid4} from './utils'; @@ -566,33 +566,18 @@ class SketchField extends PureComponent { }; componentDidMount = () => { - let { - tool, - value, - undoSteps, - defaultValue, - backgroundColor - } = this.props; - - let canvas = this._fc = new fabric.Canvas(this._canvas/*, { - preserveObjectStacking: false, - renderOnAddRemove: false, - skipTargetFind: true - }*/); + let { tool, value, undoSteps, defaultValue, backgroundColor } = this.props; + let canvas = this._fc = new fabric.Canvas(this._canvas); this._initTools(canvas); - - // set initial backgroundColor this._backgroundColor(backgroundColor) - let selectedTool = this._tools[tool]; + selectedTool.configureCanvas(this.props); this._selectedTool = selectedTool; - - // Control resize window.addEventListener('resize', this._resize, false); + window.addEventListener("keydown", this.deleteKey, false); - // Initialize History, with maximum number of undo steps this._history = new History(undoSteps); // Events binding @@ -607,21 +592,17 @@ class SketchField extends PureComponent { canvas.on('object:scaling', this._onObjectScaling); canvas.on('object:rotating', this._onObjectRotating); // IText Events fired on Adding Text - // canvas.on("text:event:changed", console.log) - // canvas.on("text:selection:changed", console.log) - // canvas.on("text:editing:entered", console.log) - // canvas.on("text:editing:exited", console.log) this.disableTouchScroll(); - this._resize(); - - // initialize canvas with controlled value if exists (value || defaultValue) && this.fromJSON(value || defaultValue); - }; - componentWillUnmount = () => window.removeEventListener('resize', this._resize); + componentWillUnmount = () => { + window.removeEventListener('resize', this._resize); + window.addEventListener("keydown", this.deleteKey, false); + + } componentDidUpdate = (prevProps, prevState) => { if (this.state.parentWidth !== prevState.parentWidth @@ -630,11 +611,9 @@ class SketchField extends PureComponent { this._resize() } - if (this.props.tool !== prevProps.tool) { this._selectedTool = this._tools[this.props.tool] || this._tools[Tool.Pencil] } - //Bring the cursor back to default if it is changed by a tool this._fc.defaultCursor = 'default'; this._selectedTool.configureCanvas(this.props); @@ -648,13 +627,14 @@ class SketchField extends PureComponent { } }; + deleteKey = (event) =>{ + if(event.code == "Delete"){ + this.props.removeItem() + } + } + render = () => { - let { - className, - style, - width, - height - } = this.props; + let { className, style, width, height } = this.props; let canvasDivStyle = Object.assign({}, style ? style : {}, width ? { width: width } : {}, @@ -676,4 +656,4 @@ class SketchField extends PureComponent { } } -export default SketchField \ No newline at end of file +export default SketchField From 88eb17013dde9903381888a369f73df8025d6487 Mon Sep 17 00:00:00 2001 From: Srijon Date: Mon, 23 Mar 2020 23:39:07 -0700 Subject: [PATCH 03/10] change to be able to modify image on loading --- examples/main.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/main.jsx b/examples/main.jsx index 6d242d54..c7dcf6bb 100644 --- a/examples/main.jsx +++ b/examples/main.jsx @@ -121,7 +121,7 @@ class SketchFieldDemo extends React.Component { backgroundColor: 'transparent', shadowWidth: 0, shadowOffset: 0, - tool: Tools.Pencil, + tool: Tools.Select, enableRemoveSelected: false, fillWithColor: false, fillWithBackgroundColor: false, From 255b1abf10225dbe79a5a0b98139f3f0d127ae17 Mon Sep 17 00:00:00 2001 From: Srijon Date: Sat, 28 Mar 2020 23:13:08 -0700 Subject: [PATCH 04/10] changes to delete from delete keyboard button --- examples/main.jsx | 1 + src/SketchField.jsx | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/examples/main.jsx b/examples/main.jsx index c7dcf6bb..8d3851e7 100644 --- a/examples/main.jsx +++ b/examples/main.jsx @@ -346,6 +346,7 @@ class SketchFieldDemo extends React.Component { ref={c => (this._sketch = c)} lineColor={this.state.lineColor} lineWidth={this.state.lineWidth} + removeItem={this._removeSelected} fillColor={ this.state.fillWithColor ? this.state.fillColor diff --git a/src/SketchField.jsx b/src/SketchField.jsx index 5e8b6f7c..15f54f66 100644 --- a/src/SketchField.jsx +++ b/src/SketchField.jsx @@ -591,7 +591,8 @@ class SketchField extends PureComponent { // Control resize window.addEventListener('resize', this._resize, false); - + window.addEventListener('keydown', this.deleteKey, false) + // Initialize History, with maximum number of undo steps this._history = new History(undoSteps); @@ -621,7 +622,10 @@ class SketchField extends PureComponent { }; - componentWillUnmount = () => window.removeEventListener('resize', this._resize); + componentWillUnmount = () => { + window.removeEventListener('resize', this._resize); + window.removeEventListener('keydown', this.deleteKey, false) + } componentDidUpdate = (prevProps, prevState) => { if (this.state.parentWidth !== prevState.parentWidth @@ -648,6 +652,12 @@ class SketchField extends PureComponent { } }; + deleteKey = (event) => { + if(event.code == "Delete" || event.code == "Backspace"){ + this.props.removeItem() + } + } + render = () => { let { className, From 678da10377f5e21814baf33f49e6816c04525941 Mon Sep 17 00:00:00 2001 From: Kashif Ghaffar Asim Date: Wed, 1 Apr 2020 13:40:56 +0500 Subject: [PATCH 05/10] - download Process as json Array - Local Save and Open Objects --- examples/main.jsx | 162 ++++++++++++++++++++++++++++++++++++-------- src/SketchField.jsx | 72 +++++++++++++++----- src/history.js | 49 +++++++++++--- 3 files changed, 226 insertions(+), 57 deletions(-) diff --git a/examples/main.jsx b/examples/main.jsx index 969d94d8..d1f39dd1 100644 --- a/examples/main.jsx +++ b/examples/main.jsx @@ -94,7 +94,6 @@ const styles = { } }; - console.log(Tools) /** * Helper function to manually fire an event * @@ -102,6 +101,7 @@ const styles = { * @param etype the event type */ function eventFire(el, etype) { + if (el.fireEvent) { el.fireEvent('on' + etype); } else { @@ -131,7 +131,7 @@ class SketchFieldDemo extends React.Component { canUndo: false, canRedo: false, controlledSize: false, - sketchWidth: 600, + sketchWidth: 800, sketchHeight: 600, stretched: true, stretchedX: false, @@ -147,7 +147,8 @@ class SketchFieldDemo extends React.Component { expandControlled: false, text: 'Testing!', enableCopyPaste: false, - isOpen: false + isOpen: true, + dataJson: dataJson, }; } @@ -160,26 +161,125 @@ class SketchFieldDemo extends React.Component { }; _save = () => { - let drawings = this.state.drawings; - console.log(drawings) - drawings.push(this._sketch.toDataURL()); - this.setState({ drawings: drawings, isOpen: true }); + var array = [] + var stObject = this._sketch._fc._objects; + for (var key in stObject) { + var obArray = [] + var orgState = stObject[key].__originalState; + if(orgState){ + if(orgState.objects){ + for(var j = 0; j < orgState.objects.length; j++){ + var newHash = this._getHash(orgState.objects[j]); + obArray.push(newHash); + } + } + var hash = this._getHash(stObject[key].__originalState, obArray); + array.push(hash) + } + } + var objects = { + "objects": array, + "background": "red", + } + + // var backgroundImage = this._sketch._fc.backgroundImage._element.src; + this.setState({isOpen: true , objects: objects}); }; - _open = () =>{ - if(this.state.isOpen == true){ - this.setState({drawings: drawings }) - } + _open = () => { + // this._setBackGround(this.state.backgroundImage) + this._sketch.fromJSON(this.state.objects) + } _download = () => { - let { imgDown } = this.refs; - let event = new Event('click', {}); - imgDown.href = this._sketch.toDataURL(); - imgDown.download = 'toPNG.png'; - imgDown.dispatchEvent(event); + this._sketch.download(); }; + // Start Setting Background + _setBackGround =(src)=>{ + let sketch = this._sketch; + let { stretched, stretchedX, stretchedY, originX, originY } = this.state; + sketch.setBackgroundFromDataUrl(src, { + stretched: true, + stretchedX: true, + stretchedY: true, + originX: originX, + originY: originY + }) + + } + // End + + + + // Start + // + // Process + + _getHash = (obj, obArray) => { + console.log(obj); + var hash = { + type: obj.type, + version: obj.version, + originX: obj.originX, + originY: obj.originY, + left: obj.left, + top: obj.top, + width: obj.width, + height: obj.height, + fill: obj.fill, + stroke: obj.stroke, + strokeWidth: obj.strokeWidth, + strokeDashArray: obj.strokeDashArray, + strokeLineCap: obj.strokeLineCap, + strokeLineJoin: obj.strokeLineJoin, + strokeMiterLimit: obj.strokeMiterLimit, + scaleX: obj.scaleX, + scaleY: obj.scaleY, + angle: obj.angle, + flipX: obj.flipX, + flipY: obj.flipY, + opacity: obj.opacity, + shadow: obj.shadow, + visible: obj.visible, + clipTo: obj.clipTo, + backgroundColor: obj.backgroundColor, + fillRule: obj.fillRule, + paintFirst: obj.paintFirst, + globalCompositeOperation: obj.globalCompositeOperation, + transformMatrix: obj.transformMatrix, + skewX: obj.skewX, + skewY: obj.skewY, + path: obj.path, + x1: obj.x1, + x2: obj.x2, + y1: obj.y1, + y2: obj.y2, + objects: obArray, + radius: obj.radius, + startAngle: obj.startAngle, + endAngle: obj.endAngle, + text: obj.text, + fontSize: obj.fontSize, + fontWeight: obj.fontWeight, + fontFamily: obj.fontFamily, + fontStyle: obj.fontStyle, + lineHeight: obj.lineHeight, + underline: obj.underline, + overline: obj.overline, + linethrough: obj.linethrough, + textAlign: obj.textAlign, + textBackgroundColor: obj.textBackgroundColor, + charSpacing: obj.charSpacing, + crossOrigin: "", + cropX: obj.cropX, + cropY: obj.cropY, + src: obj.src, + } + return hash; + } + _renderTile = (drawing, index) => { return ( { + console.log(accepted) if (accepted && accepted.length > 0) { let sketch = this._sketch; let reader = new FileReader(); + let { stretched, stretchedX, stretchedY, originX, originY } = this.state; reader.addEventListener( 'load', - () => - sketch.setBackgroundFromDataUrl(reader.result, { - stretched: stretched, - stretchedX: stretchedX, - stretchedY: stretchedY, - originX: originX, - originY: originY, + () =>sketch.setBackgroundFromDataUrl(reader.result, { + }), false, ); @@ -271,11 +368,10 @@ class SketchFieldDemo extends React.Component { _addText = () => this._sketch.addText(this.state.text); componentDidMount = () => { - console.log('here'); (function(console) { console.save = function(data, filename) { + if (!data) { - console.error('Console.save: No data'); return; } if (!filename) filename = 'console.json'; @@ -312,41 +408,47 @@ class SketchFieldDemo extends React.Component {
- + Sketch Tool - + title="Open" + disabled={!this.state.isOpen} + onClick={this._open}> + @@ -381,7 +483,7 @@ class SketchFieldDemo extends React.Component { height={ this.state.controlledSize ? this.state.sketchHeight : null } - defaultValue={dataJson} + defaultValue={this.state.dataJson} value={controlledValue} forceValue onChange={this._onSketchChange} diff --git a/src/SketchField.jsx b/src/SketchField.jsx index 32661e33..a29973aa 100644 --- a/src/SketchField.jsx +++ b/src/SketchField.jsx @@ -1,9 +1,10 @@ -/*eslint no-unused-vars: 0*/ + /*eslint no-unused-vars: 0*/ import React, {PureComponent, useEffect} from 'react'; import PropTypes from 'prop-types'; import History from './history'; + import {uuid4} from './utils'; import Select from './select'; import Pencil from './pencil'; @@ -79,7 +80,8 @@ class SketchField extends PureComponent { state = { parentWidth: 550, - action: true + action: true, + save: null, }; _initTools = (fabricCanvas) => { @@ -186,11 +188,13 @@ class SketchField extends PureComponent { _onObjectModified = (e) => { let obj = e.target; obj.__version += 1; + let prevState = JSON.stringify(obj.__originalState); let objState = obj.toJSON(); - // record current object state as json and update to originalState + obj.__originalState = objState; let currState = JSON.stringify(objState); + this._history.keep([obj, prevState, currState]); }; @@ -236,8 +240,7 @@ class SketchField extends PureComponent { _onMouseUp = (e) => { this._selectedTool.doMouseUp(e); // Update the final state to new-generated object - // Ignore Path object since it would be created after mouseUp - // Assumed the last object in canvas.getObjects() in the newest object + if (this.props.tool !== Tool.Pencil) { const canvas = this._fc; const objects = canvas.getObjects(); @@ -369,7 +372,6 @@ class SketchField extends PureComponent { let history = this._history; if (history.canRedo()) { let canvas = this._fc; - //noinspection Eslint let [obj, prevState, currState] = history.redo(); if (obj.__version === 0) { this.setState({ action: false }, () => { @@ -406,12 +408,14 @@ class SketchField extends PureComponent { return this._history.canRedo() }; - - toDataURL = (options) => this._fc.toDataURL(options); + toDataURL = (options) => { + this._fc.toDataURL(options); + } toJSON = (propertiesToInclude) => this._fc.toJSON(propertiesToInclude); fromJSON = (json) => { + if (!json) return; let canvas = this._fc; setTimeout(() => { @@ -456,7 +460,7 @@ class SketchField extends PureComponent { copy = () => { let canvas = this._fc; - canvas.getActiveObject().clone(cloned => this._clipboard = cloned); + }; paste = () => { @@ -491,11 +495,14 @@ class SketchField extends PureComponent { * @param options */ setBackgroundFromDataUrl = (dataUrl, options = {}) => { + console.log(dataUrl); + + let canvas = this._fc; if (options.stretched) { delete options.stretched; Object.assign(options, { - width: canvas.width, + width: canvas.width , height: canvas.height }) } @@ -520,9 +527,6 @@ class SketchField extends PureComponent { addText = (text, options = {}) => { let canvas = this._fc; - console.log('canvas') - console.log(canvas); - console.log('canvas') let iText = new fabric.IText(text, options); let opts = { @@ -541,7 +545,6 @@ class SketchField extends PureComponent { componentDidMount = () => { let { tool, value, undoSteps, defaultValue, backgroundColor } = this.props; - let canvas = this._fc = new fabric.Canvas(this._canvas); this._initTools(canvas); this._backgroundColor(backgroundColor) @@ -575,8 +578,7 @@ class SketchField extends PureComponent { componentWillUnmount = () => { window.removeEventListener('resize', this._resize); window.addEventListener("keydown", this.deleteKey, false); - - } + } componentDidUpdate = (prevProps, prevState) => { if (this.state.parentWidth !== prevState.parentWidth @@ -601,12 +603,48 @@ class SketchField extends PureComponent { } }; + /** + * Delete key Commands for selection deleted. + * @event params + */ deleteKey = (event) =>{ - if(event.code == "Delete"){ + if(event.code == "Delete" || event.code == "BackSpace"){ this.props.removeItem() } } + /** + * Download Content + */ + download = () => { + this._history.saveToFile(); + } + + /** + * Save Current Index + */ + + save = () => { + let canvas = this._fc; + let objects = canvas.getObjects(); + let stObjects = JSON.stringify(objects) + this.setState({save: stObjects}) + } + + /** + * Open Current Saved + */ + + open = () => { + let canvas = this._fc; + + let objects = this.state.save; + + + + this.setState({isView: true}) + } + render = () => { let { className, style, width, height } = this.props; diff --git a/src/history.js b/src/history.js index e0e54f8b..272c6bbe 100644 --- a/src/history.js +++ b/src/history.js @@ -2,7 +2,7 @@ * Maintains the history of an object */ class History { - constructor(undoLimit = 10, debug = false) { + constructor(undoLimit = 1000, debug = false) { this.undoLimit = undoLimit; this.undoList = []; this.redoList = []; @@ -35,18 +35,20 @@ class History { * * @param obj */ + + keep(obj) { + try { - this.redoList = []; - if (this.current) { - this.undoList.push(this.current); - } - if (this.undoList.length > this.undoLimit) { - this.undoList.shift(); - } - this.current = obj; + if (this.current) { + this.undoList.push(this.current); + } + if (this.undoList.length > this.undoLimit) { + this.undoList.shift(); + } + this.current = obj; } finally { - this.print(); + this.print(); } } @@ -120,6 +122,33 @@ class History { this.print(); } + /** + * Save actions to a json file + * + * + */ + saveToFile() { + var allElement = this.undoList; + if(this.current){ + if(this.redoList.length == 0){ + allElement = this.current + } + } + + const a = document.createElement("a"); + a.href = URL.createObjectURL(new Blob([JSON.stringify(allElement, null, 4)], { + type: "text/plain" + })); + a.setAttribute("download", "image.txt"); + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + } + + /** + * print object + */ + print() { if (this.debug) { /* eslint-disable no-console */ From 7be2b4308ec309f7a2d1da0da5fad2ecf4b20099 Mon Sep 17 00:00:00 2001 From: Kashif Ghaffar Asim Date: Fri, 3 Apr 2020 13:05:25 +0500 Subject: [PATCH 06/10] Changes in sketch and main js --- examples/main.jsx | 52 ++++++++++++++++++--------------------------- src/SketchField.jsx | 27 ++++++++++++++++------- 2 files changed, 40 insertions(+), 39 deletions(-) diff --git a/examples/main.jsx b/examples/main.jsx index d1f39dd1..a083e239 100644 --- a/examples/main.jsx +++ b/examples/main.jsx @@ -149,6 +149,7 @@ class SketchFieldDemo extends React.Component { enableCopyPaste: false, isOpen: true, dataJson: dataJson, + url: dataUrl }; } @@ -162,7 +163,8 @@ class SketchFieldDemo extends React.Component { _save = () => { var array = [] - var stObject = this._sketch._fc._objects; + let canvas = this._sketch._fc; + var stObject = canvas._objects; for (var key in stObject) { var obArray = [] var orgState = stObject[key].__originalState; @@ -177,51 +179,35 @@ class SketchFieldDemo extends React.Component { array.push(hash) } } - var objects = { - "objects": array, - "background": "red", - } - // var backgroundImage = this._sketch._fc.backgroundImage._element.src; + var objects = { "objects": array , background: canvas.backgroundColor } + + if(canvas.backgroundImage){ + var url = canvas.backgroundImage._element.src; + this.setState({url: url}) + } this.setState({isOpen: true , objects: objects}); }; _open = () => { - // this._setBackGround(this.state.backgroundImage) - this._sketch.fromJSON(this.state.objects) - + this._sketch.changeBackground(this.state.url) + if(this.state.objects.objects.length > 0){ + this._sketch.fromJSON(this.state.objects); + } } _download = () => { this._sketch.download(); }; - // Start Setting Background - _setBackGround =(src)=>{ - let sketch = this._sketch; - let { stretched, stretchedX, stretchedY, originX, originY } = this.state; - sketch.setBackgroundFromDataUrl(src, { - stretched: true, - stretchedX: true, - stretchedY: true, - originX: originX, - originY: originY - }) - - } - // End - - - // Start // // Process _getHash = (obj, obArray) => { - console.log(obj); + var hash = { type: obj.type, - version: obj.version, originX: obj.originX, originY: obj.originY, left: obj.left, @@ -347,8 +333,7 @@ class SketchFieldDemo extends React.Component { } }; - _onBackgroundImageDrop = (accepted /*, rejected*/) => { - console.log(accepted) + _onBackgroundImageDrop = (accepted) => { if (accepted && accepted.length > 0) { let sketch = this._sketch; let reader = new FileReader(); @@ -357,8 +342,13 @@ class SketchFieldDemo extends React.Component { reader.addEventListener( 'load', () =>sketch.setBackgroundFromDataUrl(reader.result, { - + stretched: stretched, + stretchedX: stretchedX, + stretchedY: stretchedY, + originX: originX, + originY: originY, }), + false, ); reader.readAsDataURL(accepted[0]); diff --git a/src/SketchField.jsx b/src/SketchField.jsx index a29973aa..cf08a6d9 100644 --- a/src/SketchField.jsx +++ b/src/SketchField.jsx @@ -415,17 +415,17 @@ class SketchField extends PureComponent { toJSON = (propertiesToInclude) => this._fc.toJSON(propertiesToInclude); fromJSON = (json) => { - + var canvas = this._fc; if (!json) return; - let canvas = this._fc; - setTimeout(() => { + //setTimeout(() => { canvas.loadFromJSON(json, () => { canvas.renderAll(); if (this.props.onChange) { - this.props.onChange() + // this.props.onChange() } }) - }, 100) + // }, 100) + }; clear = (propertiesToInclude) => { @@ -495,9 +495,6 @@ class SketchField extends PureComponent { * @param options */ setBackgroundFromDataUrl = (dataUrl, options = {}) => { - console.log(dataUrl); - - let canvas = this._fc; if (options.stretched) { delete options.stretched; @@ -525,6 +522,20 @@ class SketchField extends PureComponent { img.src = dataUrl }; + changeBackground = (imgData) =>{ + let canvas = this._fc; + setTimeout(() => { + var img = new Image(); + img.onload = function() { + // this is syncronous + var f_img = new fabric.Image(img); + canvas.setBackgroundImage(f_img); + canvas.renderAll(); + }; + img.src = imgData; + }, 3000) + } + addText = (text, options = {}) => { let canvas = this._fc; let iText = new fabric.IText(text, options); From 1a3ec83567b61a0d1ba7f2294ce7dcb8b82dba85 Mon Sep 17 00:00:00 2001 From: Kashif Ghaffar Asim Date: Mon, 6 Apr 2020 10:37:08 +0500 Subject: [PATCH 07/10] Upload and Download Process --- examples/main.jsx | 42 ++++++++++++++++++++++++++++++++++++------ src/history.js | 26 +++++++++++++++++++------- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/examples/main.jsx b/examples/main.jsx index a083e239..8d3fff5b 100644 --- a/examples/main.jsx +++ b/examples/main.jsx @@ -32,6 +32,8 @@ import RemoveIcon from '@material-ui/icons/Remove'; import DownloadIcon from '@material-ui/icons/CloudDownload'; import ZoomInIcon from '@material-ui/icons/ZoomIn'; import ZoomOutIcon from '@material-ui/icons/ZoomOut'; +import UploadIcon from '@material-ui/icons/Backup'; + import dataJson from './data.json'; import dataJsonControlled from './data.json.controlled'; import {SketchField, Tools} from '../src'; @@ -91,7 +93,7 @@ const styles = { }, card: { margin: '10px 10px 5px 0' - } + }, }; /** @@ -111,6 +113,9 @@ function eventFire(el, etype) { } } + + + class SketchFieldDemo extends React.Component { constructor(props) { @@ -124,7 +129,7 @@ class SketchFieldDemo extends React.Component { shadowWidth: 0, shadowOffset: 0, tool: Tools.Select, - enableRemoveSelected: false, + enableRemoveSelected: true, fillWithColor: false, fillWithBackgroundColor: false, drawings: [], @@ -200,9 +205,6 @@ class SketchFieldDemo extends React.Component { this._sketch.download(); }; - // Start - // - // Process _getHash = (obj, obArray) => { @@ -341,7 +343,7 @@ class SketchFieldDemo extends React.Component { let { stretched, stretchedX, stretchedY, originX, originY } = this.state; reader.addEventListener( 'load', - () =>sketch.setBackgroundFromDataUrl(reader.result, { + () => sketch.setBackgroundFromDataUrl(reader.result, { stretched: stretched, stretchedX: stretchedX, stretchedY: stretchedY, @@ -357,6 +359,20 @@ class SketchFieldDemo extends React.Component { _addText = () => this._sketch.addText(this.state.text); + _readFile = (event) => { + let sketch = this._sketch; + let file = event.target.files[0] + if(file){ + let reader = new FileReader(); + reader.onload = function (e) { + let data = e.target.result; + console.log(data); + sketch.fromJSON(data); + } + reader.readAsText(file); + } + } + componentDidMount = () => { (function(console) { console.save = function(data, filename) { @@ -378,8 +394,11 @@ class SketchFieldDemo extends React.Component { a.dispatchEvent(e); }; })(console); + }; + + render = () => { let { controlledValue } = this.state; const theme = createMuiTheme({ @@ -430,12 +449,23 @@ class SketchFieldDemo extends React.Component { onClick={this._save}> + + 0) { + if (this.current) this.undoList.push(this.current); this.current = this.redoList.pop(); return this.current; } + return null; } finally { - this.print(); + //this.print(); } } @@ -128,15 +133,22 @@ class History { * */ saveToFile() { - var allElement = this.undoList; - if(this.current){ - if(this.redoList.length == 0){ - allElement = this.current + let dataArray = []; + + if(this.current){ + if(this.undoList.length == 0){ + allElement = this.current[0] + dataArray.push(this.current[0]) + } else { + for(let i = 0; i < this.undoList.length; i++){ + dataArray.push(this.undoList[i][0]) + } + } } - } + var hash = {"objects": dataArray} const a = document.createElement("a"); - a.href = URL.createObjectURL(new Blob([JSON.stringify(allElement, null, 4)], { + a.href = URL.createObjectURL(new Blob([JSON.stringify(hash, null, 4)], { type: "text/plain" })); a.setAttribute("download", "image.txt"); From 82feb34f28e9d6c505179a4ef637809ac8b502a6 Mon Sep 17 00:00:00 2001 From: Kashif Ghaffar Asim Date: Thu, 9 Apr 2020 00:45:25 +0500 Subject: [PATCH 08/10] - Download Image , Backgroud , Height , Width, Background and Pan Setting - Upload File and Process Data. - State Changes - Process of implemented . --- examples/main.jsx | 44 ++++++++++++++++++++++++++++++-------------- src/SketchField.jsx | 43 +++++++++++++++++-------------------------- src/history.js | 14 ++++++-------- 3 files changed, 53 insertions(+), 48 deletions(-) diff --git a/examples/main.jsx b/examples/main.jsx index 8d3fff5b..6aaffd8a 100644 --- a/examples/main.jsx +++ b/examples/main.jsx @@ -136,8 +136,8 @@ class SketchFieldDemo extends React.Component { canUndo: false, canRedo: false, controlledSize: false, - sketchWidth: 800, - sketchHeight: 600, + sketchWidth: (window.innerWidth - 400), + sketchHeight: (window.innerHeight - 200), stretched: true, stretchedX: false, stretchedY: false, @@ -154,7 +154,9 @@ class SketchFieldDemo extends React.Component { enableCopyPaste: false, isOpen: true, dataJson: dataJson, - url: dataUrl + url: dataUrl, + maxHeight: (window.innerHeight + 800), + isCanvas: false }; } @@ -191,6 +193,7 @@ class SketchFieldDemo extends React.Component { var url = canvas.backgroundImage._element.src; this.setState({url: url}) } + this.setState({isOpen: true , objects: objects}); }; @@ -360,19 +363,31 @@ class SketchFieldDemo extends React.Component { _addText = () => this._sketch.addText(this.state.text); _readFile = (event) => { - let sketch = this._sketch; - let file = event.target.files[0] + + this._clear(); + let file = event.target.files[0]; + if(file){ let reader = new FileReader(); - reader.onload = function (e) { - let data = e.target.result; - console.log(data); - sketch.fromJSON(data); - } + reader.addEventListener( + 'load', + () => this._loadData(reader.result), false, + ); reader.readAsText(file); } } + _loadData = (data) =>{ + data = JSON.parse(data); + this.setState({height: data.height, width: data.width}) + let sketch = this._sketch; + sketch.fromJSON(data); + sketch._backgroundColor(data.backgroundColor); + if(data.backImg){ + sketch.changeBackground(data.backImg) + } + } + componentDidMount = () => { (function(console) { console.save = function(data, filename) { @@ -449,6 +464,7 @@ class SketchFieldDemo extends React.Component { onClick={this._save}> + +
-
+
{ + let canvas = this._fc; + console.log(canvas); + canvas.height = 500; + canvas.renderAll() + console.log(canvas) + } + /** * Sets the background color for this sketch * @param color in rgba or hex format @@ -460,7 +468,6 @@ class SketchField extends PureComponent { copy = () => { let canvas = this._fc; - }; paste = () => { @@ -628,33 +635,17 @@ class SketchField extends PureComponent { * Download Content */ download = () => { - this._history.saveToFile(); - } - - /** - * Save Current Index - */ - - save = () => { - let canvas = this._fc; - let objects = canvas.getObjects(); - let stObjects = JSON.stringify(objects) - this.setState({save: stObjects}) + var url = null; + if(this._fc.backgroundImage){ + url = this._fc.backgroundImage._element.src; + } + let hash = { height: this._fc.height, width: this._fc.width, + backgroundColor: this._fc.backgroundColor, viewportTransform: this._fc.viewportTransform, + backImg: url, + } + this._history.saveToFile(hash); } - /** - * Open Current Saved - */ - - open = () => { - let canvas = this._fc; - - let objects = this.state.save; - - - - this.setState({isView: true}) - } render = () => { let { className, style, width, height } = this.props; diff --git a/src/history.js b/src/history.js index 7540d65a..2bed80a4 100644 --- a/src/history.js +++ b/src/history.js @@ -82,20 +82,16 @@ class History { * @returns the new current value after the redo operation, or null if no redo operation was possible */ redo() { - console.log('heres') + try { - console.log('checking is here') - console.log(this.redoList) if (this.redoList.length > 0) { - if (this.current) this.undoList.push(this.current); this.current = this.redoList.pop(); return this.current; } - return null; } finally { - //this.print(); + this.print(); } } @@ -132,7 +128,7 @@ class History { * * */ - saveToFile() { + saveToFile(hash) { let dataArray = []; if(this.current){ @@ -142,11 +138,13 @@ class History { } else { for(let i = 0; i < this.undoList.length; i++){ dataArray.push(this.undoList[i][0]) + dataArray.push(this.current[0]) } } } - var hash = {"objects": dataArray} + var hash1 = {"objects": dataArray} + hash["objects"] = dataArray; const a = document.createElement("a"); a.href = URL.createObjectURL(new Blob([JSON.stringify(hash, null, 4)], { type: "text/plain" From d1b7eea24e051de2cc36e48f309543af953193da Mon Sep 17 00:00:00 2001 From: Kashif Ghaffar Asim Date: Sat, 11 Apr 2020 22:44:47 +0500 Subject: [PATCH 09/10] Modal PopUp --- examples/main.jsx | 64 ++++++++++++++++++++++++++++++++++++++++++--- src/SketchField.jsx | 2 ++ 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/examples/main.jsx b/examples/main.jsx index 6aaffd8a..5c9f297f 100644 --- a/examples/main.jsx +++ b/examples/main.jsx @@ -42,6 +42,10 @@ import DropZone from 'react-dropzone'; import Toolbar from '@material-ui/core/Toolbar/Toolbar'; import Typography from '@material-ui/core/Typography/Typography'; +import { makeStyles } from '@material-ui/core/styles'; +import Modal from '@material-ui/core/Modal'; + + const styles = { root: { padding: '3px', @@ -94,6 +98,11 @@ const styles = { card: { margin: '10px 10px 5px 0' }, + modal: { + top: '40%', + left: '50%', + transform: 'translate(50%, 50%)' + } }; /** @@ -156,7 +165,7 @@ class SketchFieldDemo extends React.Component { dataJson: dataJson, url: dataUrl, maxHeight: (window.innerHeight + 800), - isCanvas: false + isOpen: true }; } @@ -412,7 +421,25 @@ class SketchFieldDemo extends React.Component { }; + _handleClose = () =>{ + this.setState({isOpen: false}) + } + + _setInput1 = (event) =>{ + this.setState({newHeight: event.target.value}) + } + _setInput2 = (event) =>{ + this.setState({newWidth: event.target.value}) + } + + _saveClick = () =>{ + if(this.state.newWidth && this.state.newHeight){ + this.setState({ height: parseInt(this.state.newHeight), width: parseInt(this.state.newWidth)}) + } + this.setState({isOpen: false}) + console.log(this.state.height) + } render = () => { let { controlledValue } = this.state; @@ -427,11 +454,11 @@ class SketchFieldDemo extends React.Component { }); - return (
+ Sketch Tool @@ -492,8 +519,39 @@ class SketchFieldDemo extends React.Component {
+
+ this._handleClose()} + aria-labelledby="simple-modal-title" + aria-describedby="simple-modal-description"> +
+
+

Select Size

+
+ +
+ + +
+
+ +
+ + +
+
+ +
+
+
+
+ +
- +
{ let { className, style, width, height } = this.props; + console.log(height); + console.log(width); let canvasDivStyle = Object.assign({}, style ? style : {}, width ? { width: width } : {}, From 21151f67493247285c835fc96cc3ead97e1ec470 Mon Sep 17 00:00:00 2001 From: Kashif Ghaffar Asim Date: Sun, 12 Apr 2020 12:32:55 +0500 Subject: [PATCH 10/10] Delete Key Process --- src/SketchField.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SketchField.jsx b/src/SketchField.jsx index dead7473..c2347d7a 100644 --- a/src/SketchField.jsx +++ b/src/SketchField.jsx @@ -626,7 +626,7 @@ class SketchField extends PureComponent { * @event params */ deleteKey = (event) =>{ - if(event.code == "Delete" || event.code == "BackSpace"){ + if(event.code == "Delete" || event.code == "Backspace"){ this.props.removeItem() } } @@ -647,10 +647,10 @@ class SketchField extends PureComponent { } + render = () => { let { className, style, width, height } = this.props; - console.log(height); - console.log(width); + let canvasDivStyle = Object.assign({}, style ? style : {}, width ? { width: width } : {},