lvbk-react-fabricjs
Version:
fabricjs implemented by react
467 lines (435 loc) • 16.7 kB
JSX
'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(' ')
};