UNPKG

lvbk-react-fabricjs

Version:

fabricjs implemented by react

467 lines (435 loc) 16.7 kB
'use strict'; import React from 'react'; import PropTypes from 'prop-types'; import {fabric} from 'fabric'; import diff from 'deep-diff'; import observable from '../mixin/observable.js'; export default class FabricObject extends React.Component { constructor(props, context) { super(props, context); // Observable observable(this); //Object this.adjustPosition = to => this.state.object && this.state.object.adjustPosition(to); this.animate = (property, value, opts) => this.state.object && this.state.object.animate(property, value, opts); this.bringForward = intersecting => this.state.object && this.state.object.bringForward(intersecting); this.bringToFront = () => this.state.object && this.state.object.bringToFront(); this.center = () => this.state.object && this.state.object.center(); this.centerH = () => this.state.object && this.state.object.centerH(); this.centerV = () => this.state.object && this.state.object.centerV(); this.clone = (callback, propertiesToInclude) => this.state.object && this.state.object.clone(callback, propertiesToInclude); this.cloneAsImage = (callback) => this.state.object && this.state.object.cloneAsImage(callback); this.complexity = () => this.state.object && this.state.object.complexity(); this.containsPoint = (point) => this.state.object && this.state.object.containsPoint(point); this.drawBorders = (ctx) => this.state.object && this.state.object.drawBorders(ctx); this.drawControls = (ctx) => this.state.object && this.state.object.drawControls(ctx); this.fxStraighten = (callbacks) => this.state.object && this.state.object.fxStraighten(callbacks); this.get = (property) => this.state.object && this.state.object.get(property); this.getAngle = () => this.state.object && this.state.object.getAngle(); this.getBoundingRect = () => this.state.object && this.state.object.getBoundingRect(); this.getBoundingRectHeight = () => this.state.object && this.state.object.getBoundingRectHeight(); this.getBoundingRectWidth = () => this.state.object && this.state.object.getBoundingRectWidth(); this.getCenterPoint = () => this.state.object && this.state.object.getCenterPoint(); this.getClipTo = () => this.state.object && this.state.object.getClipTo(); this.getFill = () => this.state.object && this.state.object.getFill(); this.getFlipX = () => this.state.object && this.state.object.getFlipX(); this.getFlipY = () => this.state.object && this.state.object.getFlipY(); this.getLeft = () => this.state.object && this.state.object.getLeft(); this.getLocalPointer = (e, pointer) => this.state.object && this.state.object.getLocalPointer(e, pointer); this.getOpacity = () => this.state.object && this.state.object.getOpacity(); this.getOriginX = () => this.state.object && this.state.object.getOriginX(); this.getOriginY = () => this.state.object && this.state.object.getOriginY(); this.getPointByOrigin = (originX, originY) => this.state.object && this.state.object.getPointByOrigin(originX, originY); this.getScaleX = () => this.state.object && this.state.object.getScaleX(); this.getScaleY = () => this.state.object && this.state.object.getScaleY(); this.getShadow = () => this.state.object && this.state.object.getShadow(); this.getStrokeWidth = () => this.state.object && this.state.object.getStrokeWidth(); this.getSvgStyles = () => this.state.object && this.state.object.getSvgStyles(); this.getSvgTransform = () => this.state.object && this.state.object.getSvgTransform(); this.getSvgTransformMatrix = () => this.state.object && this.state.object.getSvgTransformMatrix(); this.getTop = () => this.state.object && this.state.object.getTop(); this.getTransformMatrix = () => this.state.object && this.state.object.getTransformMatrix(); this.getViewportTransform = () => this.state.object && this.state.object.getViewportTransform(); this.getVisible = () => this.state.object && this.state.object.getVisible(); this.getWidth = () => this.state.object && this.state.object.getWidth(); this.hasStateChanged = () => this.state.object && this.state.object.hasStateChanged(); this.intersectsWithObject = (other) => this.state.object && this.state.object.intersectsWithObject(other); this.intersectsWithRect = (pointTL, pointBR) => this.state.object && this.state.object.intersectsWithRect(pointTL, pointBR); this.isContainedWithinObject = (other) => this.state.object && this.state.object.isContainedWithinObject(other); this.isContainedWithinRect = (pointTL, pointBR) => this.state.object && this.state.object.isContainedWithinRect(pointTL, pointBR); this.isControlVisible = (controlName) => this.state.object && this.state.object.isControlVisible(controlName); this.isType = (type) => this.state.object && this.state.object.isType(type); this.moveTo = (index) => this.state.object && this.state.object.moveTo(index); this.remove = () => this.state.object && this.state.object.remove(); this.renderf = (ctx, noTransform) => this.state.object && this.state.object.render(ctx, noTransform); this.saveState = (options) => this.state.object && this.state.object.saveState(options); this.scale = (value) => this.state.object && this.state.object.scale(value); this.scaleToHeight = (value) => this.state.object && this.state.object.scaleToHeight(value); this.scaleToWidth = (value) => this.state.object && this.state.object.scaleToWidth(value); this.sendBackwards = () => this.state.object && this.state.object.sendBackwards(); this.sendToBack = () => this.state.object && this.state.object.sendToBack(); this.set = (key, value) => this.state.object && this.state.object.set(key, value); this.setAngle = (value) => this.state.object && this.state.object.setAngle(value); this.setClipTo = (clipTo) => this.state.object && this.state.object.setClipTo(clipTo); this.setColor = (color) => this.state.object && this.state.object.setColor(color); this.setControlsVisibility = (options) => this.state.object && this.state.object.setControlsVisibility(options); this.setControlVisible = (controlName, visible) => this.state.object && this.state.object.setControlVisible(controlName, visible); this.setCoords = (value) => this.state.object && this.state.object.setCoords(value); this.setFill = (value) => this.state.object && this.state.object.setFill(value); this.setFlipX = (value) => this.state.object && this.state.object.setFlipX(value); this.setFlipY = (value) => this.state.object && this.state.object.setFlipY(value); this.setGradient = (property, options) => this.state.object && this.state.object.setGradient(property, options); this.setLeft = (value) => this.state.object && this.state.object.setLeft(value); this.setOpacity = (value) => this.state.object && this.state.object.setOpacity(value); this.setOptions = (options) => this.state.object && this.state.object.setOptions(options); this.setOriginX = (value) => this.state.object && this.state.object.setOriginX(value); this.setOriginY = (value) => this.state.object && this.state.object.setOriginY(value); this.setPatternFill = (options) => this.state.object && this.state.object.setPatternFill(options); this.setPositionByOrigin = (pos, originX, originY) => this.state.object && this.state.object.setPositionByOrigin(pos, originX, originY); this.setScaleX = (value) => this.state.object && this.state.object.setScaleX(value); this.setScaleY = (value) => this.state.object && this.state.object.setScaleY(value); this.setShadow = (options) => this.state.object && this.state.object.setShadow(options); this.setSourcePath = (value) => this.state.object && this.state.object.setSourcePath(value); this.setStroke = (value) => this.state.object && this.state.object.setStroke(value); this.setStrokeWidth = (value) => this.state.object && this.state.object.setStrokeWidth(value); this.setTop = (value) => this.state.object && this.state.object.setTop(value); this.setTransformMatrix = (transformMatrix) => this.state.object && this.state.object.setTransformMatrix(transformMatrix); this.setupState = () => this.state.object && this.state.object.setupState(value); this.setVisible = (value) => this.state.object && this.state.object.setVisible(value); this.straighten = () => this.state.object && this.state.object.straighten(); this.toDatalessObject = (propertiesToInclude) => this.state.object && this.state.object.toDatalessObject(); this.toDataURL = () => this.state.object && this.state.object.toDataURL(options); this.toggle = (property) => this.state.object && this.state.object.toggle(property); this.toJSON = (propertiesToInclude) => this.state.object && this.state.object.toJSON(propertiesToInclude); this.toLocalPoint = (point, originX, originY) => this.state.object && this.state.object.toLocalPoint(point, originX, originY); this.toObject = (propertiesToInclude) => this.state.object && this.state.object.toObject(propertiesToInclude); this.toString = () => this.state.object && this.state.object.toString(); this.transform = (ctx, fromLeft) => this.state.object && this.state.object.transform(ctx, fromLeft); this.translateToCenterPoint = (point, originX, originY) => this.state.object && this.state.object.translateToCenterPoint(point, originX, originY); this.translateToOriginPoint = (point, originX, originY) => this.state.object && this.state.object.translateToOriginPoint(point, originX, originY); // React this.getObject = () => this.state.object; } componentWillReceiveProps(nextProps) { const difference = diff(this.props, nextProps); if (difference) { difference.forEach(comparsion => { this.set(comparsion.path[0], comparsion.rhs); }); } this.eventChanged(nextProps); } draw(object, cb) { this.setState({object}, () => { cb && cb(object); // canvas.add(object); this.initEvent(); }); } initEvent() { const {object} = this.state; if (!(object instanceof fabric.Object)) return; if (this.props.onAdded instanceof Function) { object.on('added', this.props.onAdded); } if (this.props.onRemoved instanceof Function) { object.on('removed', this.props.onRemoved); } if (this.props.onSelected instanceof Function) { object.on('selected', this.props.onSelected); } if (this.props.onModified instanceof Function) { object.on('modified', this.props.onModified); } if (this.props.onRotating instanceof Function) { object.on('rotating', this.props.onRotating); } if (this.props.onScaling instanceof Function) { object.on('scaling', this.props.onScaling); } if (this.props.onMoving instanceof Function) { object.on('moving', this.props.onMoving); } if (this.props.onMousedown instanceof Function) { object.on('mousedown', this.props.onMousedown); } if (this.props.onMouseup instanceof Function) { object.on('mouseup', this.props.onMouseup); } } eventChanged(nextProps) { const {object} = this.state; if (!(object instanceof fabric.Object)) return; if (this.props.onAdded && !nextProps.onAdded) { object.off('added'); } else if (nextProps.onAdded instanceof Function) { object.on('added', this.props.onAdded); } if (this.props.onRemoved && !nextProps.onRemoved) { object.off('removed'); } else if (nextProps.onRemoved instanceof Function) { object.on('removed', this.props.onRemoved); } if (this.props.onSelected && !nextProps.onSelected) { object.off('selected'); } else if (nextProps.onSelected instanceof Function) { object.on('selected', this.props.onSelected); } if (this.props.onModified && !nextProps.onModified) { object.off('modified'); } else if (nextProps.onModified instanceof Function) { object.on('modified', this.props.onModified); } if (this.props.onRotating && !nextProps.onRotating) { object.off('rotating'); } else if (nextProps.onRotating instanceof Function) { object.on('rotating', this.props.onRotating); } if (this.props.onScaling && !nextProps.onScaling) { object.off('scaling'); } else if (nextProps.onScaling instanceof Function) { object.on('scaling', this.props.onScaling); } if (this.props.onMoving && !nextProps.onMoving) { object.off('moving'); } else if (nextProps.onMoving instanceof Function) { object.on('moving', this.props.onMoving); } if (this.props.onMousedown && !nextProps.onMousedown) { object.off('mousedown'); } else if (nextProps.onMousedown instanceof Function) { object.on('mousedown', this.props.onMousedown); } if (this.props.onMouseup && !nextProps.onMouseup) { object.off('mouseup'); } else if (nextProps.onMouseup instanceof Function) { object.on('mouseup', this.props.onMouseup); } } render() { return null; } } FabricObject.__uid = fabric.Object.__uid; FabricObject.NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS; FabricObject.rotate = fabric.Object.rotate; FabricObject.propTypes = { angle: PropTypes.number, backgroundColor: PropTypes.string, borderColor: PropTypes.string, borderOpacityWhenMoving: PropTypes.number, borderScaleFactor: PropTypes.number, centeredRotation: PropTypes.bool, centeredScaling: PropTypes.bool, clipTo: PropTypes.func, cornerColor: PropTypes.string, cornerSize: PropTypes.number, evented: PropTypes.bool, fill: PropTypes.string, fillRule: PropTypes.string, flipX: PropTypes.bool, flipY: PropTypes.bool, globalCompositeOperation: PropTypes.string, hasBorders: PropTypes.bool, hasControls: PropTypes.bool, hasRotatingPoint: PropTypes.bool, height: PropTypes.number, hoverCursor: PropTypes.string, includeDefaultValues: PropTypes.bool, left: PropTypes.number, lockMovementX: PropTypes.bool, lockMovementY: PropTypes.bool, lockRotation: PropTypes.bool, lockScalingFlip: PropTypes.bool, lockScalingX: PropTypes.bool, lockScalingY: PropTypes.bool, lockUniScaling: PropTypes.bool, minScaleLimit: PropTypes.number, oCoords: PropTypes.object, opacity: PropTypes.number, originX: PropTypes.oneOf(['left', 'right', 'center']), originY: PropTypes.oneOf(['top', 'bottom', 'center']), padding: PropTypes.number, perPixelTargetFind: PropTypes.bool, rotatingPointOffset: PropTypes.number, scaleX: PropTypes.number, scaleY: PropTypes.number, selectable: PropTypes.bool, shadow: PropTypes.oneOfType([PropTypes.instanceOf(fabric.Shadow), PropTypes.string]), stateProperties: PropTypes.array, stroke: PropTypes.string, strokeDashArray: PropTypes.array, strokeLineCap: PropTypes.oneOf(['butt', 'round', 'square']), strokeLineJoin: PropTypes.oneOf(['bevil', 'round', 'miter']), strokeMiterLimit: PropTypes.number, strokeWidth: PropTypes.number, top: PropTypes.number, transformMatrix: PropTypes.array, transparentCorners: PropTypes.bool, type: PropTypes.string, visible: PropTypes.bool, width: PropTypes.number, }; FabricObject.defaultProps = { type: 'object', originX: 'left', originY: 'top', top: 0, left: 0, width: 0, height: 0, scaleX: 1, scaleY: 1, flipX: false, flipY: false, opacity: 1, angle: 0, skewX: 0, skewY: 0, cornerSize: 12, transparentCorners: true, hoverCursor: null, padding: 0, borderColor: 'rgba(102,153,255,0.75)', cornerColor: 'rgba(102,153,255,0.5)', centeredScaling: false, centeredRotation: true, fill: 'rgb(0,0,0)', fillRule: 'nonzero', globalCompositeOperation: 'source-over', backgroundColor: '', stroke: null, strokeWidth: 1, strokeDashArray: null, strokeLineCap: 'butt', strokeLineJoin: 'miter', strokeMiterLimit: 10, shadow: null, borderOpacityWhenMoving: 0.4, borderScaleFactor: 1, transformMatrix: null, minScaleLimit: 0.01, selectable: true, evented: true, visible: true, hasControls: true, hasBorders: true, hasRotatingPoint: true, rotatingPointOffset: 40, perPixelTargetFind: false, includeDefaultValues: true, clipTo: null, lockMovementX: false, lockMovementY: false, lockRotation: false, lockScalingX: false, lockScalingY: false, lockUniScaling: false, lockSkewingX: false, lockSkewingY: false, lockScalingFlip: false, // oCoords: null, stateProperties: ( 'top left width height scaleX scaleY flipX flipY originX originY transformMatrix ' + 'stroke strokeWidth strokeDashArray strokeLineCap strokeLineJoin strokeMiterLimit ' + 'angle opacity fill fillRule globalCompositeOperation shadow clipTo visible backgroundColor ' + 'alignX alignY meetOrSlice skewX skewY' ).split(' ') };