Initial commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
dist
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"globalstrict": true,
|
||||
|
||||
"globals": {
|
||||
"$": false,
|
||||
"console": false,
|
||||
"document": false,
|
||||
"fabric": false,
|
||||
"jQuery": false,
|
||||
"module": false,
|
||||
"QUnit": false,
|
||||
"require": false,
|
||||
"strict": false,
|
||||
"node": false
|
||||
},
|
||||
"browserify": false,
|
||||
"strict": true,
|
||||
"curly": true,
|
||||
"forin": true,
|
||||
"latedef": true,
|
||||
"noarg": true,
|
||||
"nonbsp": true,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"eqeqeq": true,
|
||||
"esversion": 5,
|
||||
"freeze": true,
|
||||
"futurehostile": true,
|
||||
"scripturl": true
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
'use strict';
|
||||
|
||||
const gulp = require('gulp');
|
||||
const path = require('path');
|
||||
const browserify = require('browserify');
|
||||
const source = require('vinyl-source-stream');
|
||||
const buffer = require('vinyl-buffer');
|
||||
const uglifyJs = require('gulp-uglify');
|
||||
const sourcemaps = require('gulp-sourcemaps');
|
||||
const concat = require('gulp-concat');
|
||||
const rename = require('gulp-rename');
|
||||
const merge = require('merge-stream');
|
||||
|
||||
module.exports = () => {
|
||||
const debug = browserify(path.join('src', 'js', 'main.js'), {
|
||||
debug: true
|
||||
})
|
||||
.bundle()
|
||||
.pipe(source('main.js'))
|
||||
.pipe(buffer())
|
||||
.pipe(sourcemaps.init({ loadMaps: true }))
|
||||
.pipe(sourcemaps.write())
|
||||
.pipe(gulp.dest(path.join('dist', 'js')));
|
||||
|
||||
const min = browserify(path.join('src', 'js', 'main.js'), {
|
||||
debug: false
|
||||
})
|
||||
.bundle()
|
||||
.pipe(source('main.min.js'))
|
||||
.pipe(buffer())
|
||||
.pipe(uglifyJs())
|
||||
.pipe(gulp.dest(path.join('dist', 'js')));
|
||||
|
||||
return merge(debug, min);
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
const gulp = require('gulp');
|
||||
const path = require('path');
|
||||
const watch = require('gulp-watch');
|
||||
|
||||
module.exports = () => {
|
||||
const less = watch(path.join('src', 'less', '**', '*.less'), () => {
|
||||
gulp.start('compile-less');
|
||||
});
|
||||
|
||||
const js = watch(path.join('src', 'js', '**', '*.js'), () => {
|
||||
gulp.start('compile-js');
|
||||
});
|
||||
/*
|
||||
const vendorJs = watch(path.join('src', 'vendor', '**', '*.js'), () => {
|
||||
gulp.start('compile-vendor-js');
|
||||
});
|
||||
|
||||
const handlebars = watch(path.join('src', 'js', 'handlebars', '**', '*.hbs'), () => {
|
||||
gulp.start('compile-handlebars');
|
||||
});
|
||||
*/
|
||||
};
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+20
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
const gulp = require('gulp');
|
||||
const mkdirp = require('mkdirp');
|
||||
const del = require('del');
|
||||
const path = require('path');
|
||||
const buildTasks = path.join(process.cwd(), 'build-tasks');
|
||||
|
||||
gulp.task('clean-dist', () => del('dist'));
|
||||
//gulp.task('compile-vendor-js', require(path.join(buildTasks, 'compile-vendor-js')));
|
||||
gulp.task('compile-js', require(path.join(buildTasks, 'compile-js')));
|
||||
gulp.task('watcher', require(path.join(buildTasks, 'watcher')));
|
||||
|
||||
gulp.task('build', ['clean-dist'], () => {
|
||||
mkdirp.sync('dist');
|
||||
gulp.start('compile-js');
|
||||
});
|
||||
|
||||
gulp.task('watch', ['build', 'watcher']);
|
||||
gulp.task('default', ['build']);
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<link rel="stylesheet" href="/main.css?123" />
|
||||
<title>Crop - dev</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
<h1>Test</h1>
|
||||
<form id="form-control">
|
||||
<div>
|
||||
<input type="text" name="image_id" value="45809" />
|
||||
<input type="text" name="w" value="100" />
|
||||
<input type="text" name="h" value="100" />
|
||||
Mirror: <input type="checkbox" class="image-control" name="mirror" />
|
||||
</div>
|
||||
</form>
|
||||
<br /><br />
|
||||
<div id="wrapper">
|
||||
<canvas id="canvas" width="1253" height="600" data-image-id="45809"></canvas>
|
||||
</div>
|
||||
<br /><br /><br />
|
||||
</div>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.11/fabric.js"></script>
|
||||
<script src="/dist/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,28 @@
|
||||
@font-face {
|
||||
font-family: breuer;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
src: url('/fonts/breuertext-regular-webfont.woff') format('woff'),
|
||||
url('/fonts/breuertext-regular-webfont.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: breuerMedium;
|
||||
src: url('/fonts/breuertext-medium-webfont.woff') format('woff'),
|
||||
url('/fonts/breuertext-medium-webfont.ttf') format('truetype');
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: breuer;
|
||||
}
|
||||
|
||||
#container {
|
||||
background: #fff;
|
||||
text-align:center;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.canvas-container {
|
||||
margin: 0 auto;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "Croppy",
|
||||
"version": "0.0.1",
|
||||
"description": "Croppy",
|
||||
"main": "gulpfile.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@bitbucket.org:rikbar/croppy.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^13.1.1",
|
||||
"del": "^2.2.2",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-autoprefixer": "^3.1.1",
|
||||
"gulp-concat": "^2.6.0",
|
||||
"gulp-declare": "^0.3.0",
|
||||
"gulp-handlebars": "^4.0.0",
|
||||
"gulp-jscs": "^4.0.0",
|
||||
"gulp-jshint": "^2.0.4",
|
||||
"gulp-less": "^3.0.3",
|
||||
"gulp-pxtorem": "^2.0.0",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-sourcemaps": "^1.9.1",
|
||||
"gulp-strip-comments": "^2.4.3",
|
||||
"gulp-uglify": "^2.0.0",
|
||||
"gulp-uglifycss": "^1.0.6",
|
||||
"gulp-watch": "^4.3.11",
|
||||
"gulp-wrap": "^0.13.0",
|
||||
"handlebars": "^4.0.6",
|
||||
"jshint": "^2.9.4",
|
||||
"gulp-wrap": "^0.13.0",
|
||||
"handlebars": "^4.0.6",
|
||||
"jshint-stylish": "^2.2.1",
|
||||
"merge-stream": "^1.0.1",
|
||||
"mkdirp": "^0.5.1",
|
||||
"vinyl-buffer": "^1.0.0",
|
||||
"vinyl-source-stream": "^1.1.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
'use strict';
|
||||
|
||||
function ApertureHandler(canvas) {
|
||||
var _items = {x: [], y: []};
|
||||
|
||||
function init() {
|
||||
var bounds = canvas;
|
||||
var hRect = new fabric.Rect({
|
||||
width: bounds.width,
|
||||
height: bounds.height / 2,
|
||||
fill: canvas.backgroundColor,
|
||||
opacity: 0.7,
|
||||
});
|
||||
|
||||
var vRect = hRect.clone().set({
|
||||
width: bounds.width / 2,
|
||||
height: bounds.height
|
||||
});
|
||||
|
||||
_items.x = [].concat([hRect, hRect.clone()]);
|
||||
_items.y = [].concat([vRect, vRect.clone()]);
|
||||
|
||||
[].concat(_items.x, _items.y).forEach(function (o) {
|
||||
canvas.add(o);
|
||||
});
|
||||
canvas.renderAll();
|
||||
}
|
||||
init();
|
||||
|
||||
this.apply = function (axis, viewport) {
|
||||
this.getApertures(axis).forEach(function (o) {
|
||||
o.visible = false;
|
||||
});
|
||||
|
||||
var active = this.getApertures(axis === 'x' ? 'y' : 'x');
|
||||
|
||||
active.forEach(function (o) {
|
||||
o.visible = true;
|
||||
});
|
||||
|
||||
if (axis === 'y') {
|
||||
active[0].top = viewport.top - active[0].height + 0.5;
|
||||
active[1].top = viewport.top + viewport.height - 0.5;
|
||||
} else {
|
||||
active[0].left = viewport.left - active[0].width + 0.5;
|
||||
active[1].left = viewport.left + viewport.width - 0.5;
|
||||
}
|
||||
|
||||
this.getApertures().forEach(function (o) {
|
||||
o.setCoords();
|
||||
});
|
||||
|
||||
canvas.renderAll();
|
||||
};
|
||||
|
||||
this.getApertures = function (axis) {
|
||||
return axis ? _items[axis] : [].concat(_items.x, _items.y);
|
||||
};
|
||||
|
||||
this.setTransparent = function (apply) {
|
||||
this.getApertures().forEach(function (o) {
|
||||
o.opacity = apply ? 0.7 : 1;
|
||||
});
|
||||
canvas.renderAll();
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = ApertureHandler;
|
||||
@@ -0,0 +1,95 @@
|
||||
'use strict';
|
||||
|
||||
var TextButton = require('./TextButton');
|
||||
|
||||
function ButtonMenu(canvas, settings) {
|
||||
var _items = [];
|
||||
var _width = 0;
|
||||
|
||||
var _settings = $.extend({}, settings, {
|
||||
background: '#444',
|
||||
fontSize: 14,
|
||||
height: 30,
|
||||
margin: 5,
|
||||
padding: 20
|
||||
});
|
||||
|
||||
/**
|
||||
* Calculates the width of all contained items
|
||||
* @return {Number}
|
||||
*/
|
||||
function calcWidth() {
|
||||
var width = 0;
|
||||
_items.forEach(function (o) {
|
||||
width += o.width;
|
||||
});
|
||||
width += _settings.margin * (_items.length - 1);
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} text
|
||||
* @param {Function} callback
|
||||
* @return {ButtonMenu}
|
||||
*/
|
||||
this.addItem = function (text, callback) {
|
||||
_items.push(
|
||||
new TextButton(text, _settings)
|
||||
.onClick(callback)
|
||||
.set({ __group: this })
|
||||
);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {ButtonMenu}
|
||||
*/
|
||||
this.bringToFront = function () {
|
||||
_items.forEach(function (o) {
|
||||
o.bringToFront();
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {Array}
|
||||
*/
|
||||
this.getItems = function () {
|
||||
return _items;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {Number}
|
||||
*/
|
||||
this.getWidth = function () {
|
||||
_width = calcWidth();
|
||||
return _width;
|
||||
};
|
||||
|
||||
/**
|
||||
* Recalculate boundaries and add all items to canvas if required
|
||||
* @return {ButtonMenu}
|
||||
*/
|
||||
this.render = function () {
|
||||
var start = canvas.width / 2 - this.getWidth() / 2;
|
||||
var currPos = Math.round(start);
|
||||
|
||||
_items.forEach(function (o) {
|
||||
o.set({ top: 10, left: currPos })
|
||||
.setCoords();
|
||||
|
||||
if (!o.canvas) {
|
||||
o.addTo(canvas);
|
||||
}
|
||||
currPos += Math.round(o.width + _settings.margin);
|
||||
|
||||
// Disable moving of buttons
|
||||
o.lockMovementX = o.lockMovementY = true;
|
||||
});
|
||||
|
||||
canvas.renderAll();
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = ButtonMenu;
|
||||
@@ -0,0 +1,102 @@
|
||||
'use strict';
|
||||
var util = require('./Util');
|
||||
var ApertureHandler = require('./ApertureHandler');
|
||||
var ButtonMenu = require('./ButtonMenu');
|
||||
var DragbarHandler = require('./DragbarHandler');
|
||||
var Viewport = require('./Viewport');
|
||||
|
||||
var Canvas = fabric.util.createClass(fabric.Canvas, {
|
||||
initialize: function (id) {
|
||||
this.callSuper('initialize', id, {
|
||||
enableRetinaScaling: true,
|
||||
renderOnAddRemove: false,
|
||||
stateful: false,
|
||||
backgroundColor: '#d4d4d4',
|
||||
preserveObjectStacking: true,
|
||||
selection: false,
|
||||
});
|
||||
|
||||
this.on('mouse:up', function () {
|
||||
if (this.image.__moved) {
|
||||
this.aperture.setTransparent(false);
|
||||
}
|
||||
$(this.upperCanvasEl).css('cursor', 'default');
|
||||
this.renderAll();
|
||||
});
|
||||
},
|
||||
|
||||
get_apertures: function () {
|
||||
return this.__aperturehandler ||
|
||||
(this.__aperturehandler = new ApertureHandler(this));
|
||||
},
|
||||
|
||||
get_dragbars: function () {
|
||||
return this.__dragbars ||
|
||||
(this.__dragbars = new DragbarHandler(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {fabric.Image}
|
||||
*/
|
||||
get_image: function () {
|
||||
return this.__image;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {Viewport}
|
||||
*/
|
||||
get_viewport: function () {
|
||||
return this.__viewport ||
|
||||
(this.__viewport = new Viewport(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {Canvas}
|
||||
*/
|
||||
removeImage: function () {
|
||||
if (!this.__image) {
|
||||
return this;
|
||||
}
|
||||
return this.remove(this.__image);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {fabric.Image} img
|
||||
* @return {Canvas}
|
||||
*/
|
||||
setImage: function (img) {
|
||||
this.removeImage();
|
||||
this.__image = img;
|
||||
this.__image.addTo(this).center().on('mousedown', function () {
|
||||
img.canvas.aperture.setTransparent(true);
|
||||
}).setCoords();
|
||||
this.viewport.reset();
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
// Define properties
|
||||
util.setProperties(Canvas.prototype, {
|
||||
aperture: {
|
||||
get: Canvas.prototype.get_apertures
|
||||
},
|
||||
dragbars: {
|
||||
get: Canvas.prototype.get_dragbars
|
||||
},
|
||||
image: {
|
||||
get: Canvas.prototype.get_image
|
||||
},
|
||||
topMenu: {
|
||||
get: function () {
|
||||
if (!this.__topMenu) {
|
||||
this.__topMenu = new ButtonMenu(this);
|
||||
}
|
||||
return this.__topMenu;
|
||||
}
|
||||
},
|
||||
viewport: {
|
||||
get: Canvas.prototype.get_viewport
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Canvas;
|
||||
@@ -0,0 +1,97 @@
|
||||
'use strict';
|
||||
|
||||
var DragHandle = function (handler) {
|
||||
var _currentAxis;
|
||||
var _dragging;
|
||||
|
||||
// Event declarations
|
||||
var events = {
|
||||
mouseDown: function () {
|
||||
_dragging = true;
|
||||
_currentAxis = this.axis;
|
||||
handler.canvas.image.trigger('mousedown');
|
||||
},
|
||||
mouseUp: function () {
|
||||
_dragging = false;
|
||||
_currentAxis = null;
|
||||
handler.canvas.image.trigger('mouseup');
|
||||
},
|
||||
mouseMove: function (e) {
|
||||
if (!_dragging) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentAxis === 'h') {
|
||||
handler.canvas.image.left -= e.e.movementX;
|
||||
} else {
|
||||
handler.canvas.image.top -= e.e.movementY;
|
||||
}
|
||||
// Trigger moving for image, to stay within bounds
|
||||
handler.canvas.image.setCoords().trigger('moving');
|
||||
handler.canvas.renderAll();
|
||||
}
|
||||
};
|
||||
|
||||
function getRect(text, width) {
|
||||
var txt = new fabric.Text(text, {
|
||||
fontFamily: 'breuer',
|
||||
fontSize: 12,
|
||||
fill: '#fff',
|
||||
originX: 'center',
|
||||
top: 2
|
||||
});
|
||||
|
||||
var rect = new fabric.Rect({
|
||||
fill: '#666',
|
||||
width: width,
|
||||
height: 20,
|
||||
originX: 'center',
|
||||
});
|
||||
|
||||
return new fabric.Group([rect, txt]).set({
|
||||
evented: false,
|
||||
});
|
||||
}
|
||||
|
||||
this.getCanvas = function () {
|
||||
return handler.canvas;
|
||||
};
|
||||
|
||||
this.getHandles = function () {
|
||||
if (!this.__handles) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [].concat(this.__handles.h, this.__handles.v);
|
||||
};
|
||||
|
||||
this.init = function () {
|
||||
var viewportData = this.getCanvas().viewport.data;
|
||||
var tracks = handler.getTracks();
|
||||
|
||||
if (this.__handles) {
|
||||
this.getCanvas().remove(this.__handles.h);
|
||||
this.getCanvas().remove(this.__handles.v);
|
||||
}
|
||||
|
||||
this.__handles = {
|
||||
h: getRect(viewportData.dim.width + ' cm', viewportData.width),
|
||||
v: getRect(viewportData.dim.height + ' cm', viewportData.height)
|
||||
};
|
||||
|
||||
this.__handles.h.addTo(this.getCanvas()).centerH().set({ top: tracks.h.top }).setCoords();
|
||||
this.__handles.v.addTo(this.getCanvas())
|
||||
.setAngle(90)
|
||||
.centerV().set({ left: tracks.v.left + tracks.v.width })
|
||||
.setCoords();
|
||||
|
||||
this.getCanvas()
|
||||
.on('mouse:move', events.mouseMove)
|
||||
.on('mouse:up', events.mouseUp);
|
||||
|
||||
tracks.h.on('mousedown', events.mouseDown.bind(tracks.h));
|
||||
tracks.v.on('mousedown', events.mouseDown.bind(tracks.v));
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = DragHandle;
|
||||
@@ -0,0 +1,81 @@
|
||||
'use strict';
|
||||
var DragHandle = require('./DragHandle');
|
||||
|
||||
function DragbarHandler(canvas) {
|
||||
var _items = { h: null, v: null };
|
||||
|
||||
/**
|
||||
* @return {DragbarHandler}
|
||||
*/
|
||||
this.apply = function () {
|
||||
if (!canvas.__hasDragbars) {
|
||||
this.init();
|
||||
canvas.__hasDragbars = true;
|
||||
}
|
||||
this.sync();
|
||||
|
||||
if (!this.__handles) {
|
||||
this.__handles = new DragHandle(this);
|
||||
}
|
||||
|
||||
this.__handles.init();
|
||||
|
||||
[].concat(_items.h, _items.v).forEach(function (o) {
|
||||
o.bringToFront();
|
||||
});
|
||||
|
||||
this.__handles.getHandles().forEach(function (o) {
|
||||
o.bringToFront();
|
||||
});
|
||||
|
||||
canvas.renderAll();
|
||||
return this;
|
||||
};
|
||||
|
||||
this.canvas = canvas;
|
||||
|
||||
/**
|
||||
* Removes dragbars from canvas
|
||||
*/
|
||||
this.clear = function () {
|
||||
canvas
|
||||
.remove(_items.h)
|
||||
.remove(_items.v)
|
||||
.renderAll();
|
||||
return this;
|
||||
};
|
||||
|
||||
this.getTracks = function () {
|
||||
return _items;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {DragbarHandler}
|
||||
*/
|
||||
this.init = function () {
|
||||
this.clear();
|
||||
|
||||
_items.h = new fabric.Rect({ axis: 'h', fill: '#bbb', width: canvas.image.width, height: 20 })
|
||||
.addTo(canvas)
|
||||
.centerH().set({top: canvas.height - 30}).setCoords();
|
||||
|
||||
_items.v = new fabric.Rect({ axis: 'v', fill: '#bbb', width: 20, height: canvas.image.height })
|
||||
.addTo(canvas)
|
||||
.set({left: canvas.width - 30}).setCoords();
|
||||
|
||||
canvas.image.on('moving', this.sync);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {DragbarHandler}
|
||||
*/
|
||||
this.sync = function () {
|
||||
_items.h.set({left: canvas.image.left}).setCoords();
|
||||
_items.v.set({top: canvas.image.top}).setCoords();
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = DragbarHandler;
|
||||
@@ -0,0 +1,37 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('./Util');
|
||||
|
||||
/**
|
||||
* @param {fabric.Image} img
|
||||
* @param {fabric.Rect} boundingRect
|
||||
*/
|
||||
function Draggable(img, boundingRect) {
|
||||
var _bounds = boundingRect;
|
||||
|
||||
/**
|
||||
* Triggers when object is moved
|
||||
*/
|
||||
function onMove() {
|
||||
this.__moved = true;
|
||||
util.setPositionInside(this, _bounds);
|
||||
}
|
||||
|
||||
// Attach onMove event to image
|
||||
img.on('moving', onMove);
|
||||
|
||||
/**
|
||||
* @param {fabric.Rect} localBoundingRect
|
||||
* @return {Draggable}
|
||||
*/
|
||||
this.enable = function (localBoundingRect) {
|
||||
if (localBoundingRect) {
|
||||
_bounds = localBoundingRect;
|
||||
}
|
||||
img.lockMovementX = img.lockMovementY = false;
|
||||
img.selectable = true;
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = Draggable;
|
||||
@@ -0,0 +1,70 @@
|
||||
'use strict';
|
||||
|
||||
function GoreHandler(viewport) {
|
||||
var _enabled = false;
|
||||
var _lines = [];
|
||||
|
||||
/**
|
||||
* @return {fabric.Line}
|
||||
*/
|
||||
function getLine(left) {
|
||||
return new fabric.Line([0, 0, 0, viewport.data.height], {
|
||||
evented: false,
|
||||
strokeDashArray: [5, 5],
|
||||
stroke: '#000',
|
||||
strokeWidth: 1,
|
||||
left: left,
|
||||
top: viewport.getBounds().top
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {GoreHandler}
|
||||
*/
|
||||
this.clear = function () {
|
||||
_lines.forEach(function (o) {
|
||||
viewport.canvas.remove(o);
|
||||
});
|
||||
_lines = [];
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Boolean} enabled
|
||||
* @return {GoreHandler}
|
||||
*/
|
||||
this.enable = function (enabled) {
|
||||
_enabled = enabled;
|
||||
this.clear();
|
||||
|
||||
if (!_enabled) {
|
||||
viewport.canvas.renderAll();
|
||||
return;
|
||||
}
|
||||
|
||||
var bounds = viewport.getBounds();
|
||||
var step = viewport.data.ppmm * 450;
|
||||
var count = Math.ceil(bounds.width / step);
|
||||
|
||||
for (var i = 1; i < count; i++) {
|
||||
_lines.push(getLine(bounds.left + step * i));
|
||||
}
|
||||
|
||||
_lines.forEach(function (o) {
|
||||
viewport.canvas.add(o);
|
||||
});
|
||||
|
||||
viewport.canvas.renderAll();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {GoreHandler}
|
||||
*/
|
||||
this.reset = function () {
|
||||
return this.enable(_enabled);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = GoreHandler;
|
||||
@@ -0,0 +1,110 @@
|
||||
'use strict';
|
||||
|
||||
var Canvas = require('./Canvas');
|
||||
var util = require('./Util');
|
||||
|
||||
function ImageEditor(args) {
|
||||
var _canvas;
|
||||
|
||||
var _settings = $.extend({
|
||||
'type': 'wallpaper'
|
||||
}, args);
|
||||
|
||||
// Initialize canvas
|
||||
_canvas = new Canvas('canvas');
|
||||
|
||||
_canvas.topMenu
|
||||
.addItem(['Show Murals Panel', 'Hide Murals Panel'], function () {
|
||||
_canvas.viewport.gores.enable(this.isActive());
|
||||
})
|
||||
.addItem(['Show Ruler', 'Hide Ruler'], function () {
|
||||
_canvas.viewport.rulers.enable(this.isActive());
|
||||
})
|
||||
.addItem(['Fullscreen', 'Exit Fullscreen'], function () {
|
||||
util.toggleFullScreen(_canvas.getSelectionElement().parentNode);
|
||||
})
|
||||
.render();
|
||||
|
||||
/**
|
||||
* Crops image to desired dimensions
|
||||
* @param {int} width [description]
|
||||
* @param {int} height [description]
|
||||
* @return {ImageEditor}
|
||||
*/
|
||||
this.crop = function (width, height) {
|
||||
_canvas.viewport.set(width, height);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string|object} key
|
||||
* @param {object} defaultValue
|
||||
* @return {object}
|
||||
*/
|
||||
this.get = function (key, defaultValue) {
|
||||
var value = _settings[key];
|
||||
return typeof value === 'undefined' ? defaultValue : value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Number|String} url
|
||||
* @param {Function} callback
|
||||
* @return {ImageEditor}
|
||||
*/
|
||||
this.loadImage = function (url, callback) {
|
||||
callback = typeof callback === 'function' ? callback : function () {};
|
||||
fabric.Image.fromURL(url, function (img) {
|
||||
_canvas.setImage(img);
|
||||
callback(img);
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string|object} key
|
||||
* @param {object} value
|
||||
* @return {ImageEditor}
|
||||
*/
|
||||
this.set = function (key, value) {
|
||||
$.extend(_settings, util.assertKeyValuePair(key, value));
|
||||
return this;
|
||||
};
|
||||
|
||||
util.setProperties(this, {
|
||||
canvas: {
|
||||
get: function () {
|
||||
return _canvas;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(function () {
|
||||
// Inputs for the editor
|
||||
var $input = {
|
||||
w: $('#form-control input[name="w"]'),
|
||||
h: $('#form-control input[name="h"]'),
|
||||
image_id: $('#form-control input[name="image_id"]'),
|
||||
mirror: $('#form-control input[name="mirror"]')
|
||||
};
|
||||
|
||||
var imageUrl = '//images.photowall.com/products/' + $input.image_id.val() + '.jpg?h=450';
|
||||
|
||||
var editor = new ImageEditor({ 'type': 'canvas' })
|
||||
.loadImage(imageUrl, function () {
|
||||
$input.w.trigger('keyup');
|
||||
});
|
||||
|
||||
var Event = {
|
||||
DimensionChange: function () {
|
||||
editor.crop($input.w.val(), $input.h.val());
|
||||
},
|
||||
Mirror: function () {
|
||||
editor.canvas.image.transformation.set('mirror', this.checked);
|
||||
}
|
||||
};
|
||||
|
||||
$input.w.keyup(Event.DimensionChange);
|
||||
$input.h.keyup(Event.DimensionChange);
|
||||
$input.mirror.click(Event.Mirror);
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
function ImageTransformationHandler(img) {
|
||||
var _transformations = {};
|
||||
|
||||
/**
|
||||
* @param {String} name
|
||||
* @param {*} args
|
||||
* @return {ImageTransformationHandler}
|
||||
*/
|
||||
this.set = function (name, args) {
|
||||
switch (name) {
|
||||
case 'mirror':
|
||||
_transformations.mirror = (img.flipX = args);
|
||||
}
|
||||
img.setCoords().canvas.renderAll();
|
||||
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = ImageTransformationHandler;
|
||||
@@ -0,0 +1,119 @@
|
||||
'use strict';
|
||||
var util = require('./Util');
|
||||
var TextButton = require('./TextButton');
|
||||
|
||||
function RulerHandler(viewport) {
|
||||
var _enabled = false;
|
||||
var _lines = { h: null, v: null };
|
||||
var _rect = { h: null, v: null };
|
||||
|
||||
var Event = {
|
||||
/**
|
||||
* Triggers when handlebar is moved
|
||||
*/
|
||||
onMove: function () {
|
||||
var axis = this.axis;
|
||||
var bounds = viewport.getBounds();
|
||||
var pos = util.assertBetween(this[axis], bounds.min[axis], bounds.max[axis]);
|
||||
this.marker[axis] = this[axis] = pos;
|
||||
var dim = (this[axis] - bounds[axis]) / (viewport.data.ppmm * 10);
|
||||
|
||||
if (axis === 'left') {
|
||||
dim = viewport.data.dim.width - dim;
|
||||
}
|
||||
|
||||
if (axis === 'top') {
|
||||
dim = viewport.data.dim.height - dim;
|
||||
}
|
||||
|
||||
this.setText(Math.round(dim * 100) / 100 + ' cm');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {fabric.Line}
|
||||
*/
|
||||
function getLine(axis) {
|
||||
var bounds = viewport.getBounds();
|
||||
return new fabric.Line([
|
||||
0, 0,
|
||||
axis === 'h' ? bounds.width : 0,
|
||||
axis === 'v' ? bounds.height : 0
|
||||
], {
|
||||
evented: false,
|
||||
strokeDashArray: [5, 5],
|
||||
stroke: '#000',
|
||||
strokeWidth: 1,
|
||||
top: axis === 'h' ? bounds.top + bounds.height / 2 : bounds.top,
|
||||
left: axis === 'v' ? bounds.left + bounds.width / 2 : bounds.left
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {RulerHandler}
|
||||
*/
|
||||
this.clear = function () {
|
||||
[].concat(_rect.h, _rect.v, _lines.h, _lines.v).forEach(function (o) {
|
||||
viewport.canvas.remove(o);
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Boolean} enabled
|
||||
* @return {RulerHandler}
|
||||
*/
|
||||
this.enable = function (enabled) {
|
||||
_enabled = enabled;
|
||||
this.clear();
|
||||
|
||||
if (!_enabled) {
|
||||
viewport.canvas.renderAll();
|
||||
return;
|
||||
}
|
||||
|
||||
var bounds = viewport.getBounds();
|
||||
|
||||
_lines = { h: getLine('h'), v: getLine('v') };
|
||||
|
||||
viewport.canvas.add(_lines.h);
|
||||
viewport.canvas.add(_lines.v);
|
||||
|
||||
var textSettings = {
|
||||
width: 75,
|
||||
height: 20,
|
||||
color: '#3f3',
|
||||
};
|
||||
|
||||
_rect.h = new TextButton('H', textSettings).set({
|
||||
axis: 'left',
|
||||
marker: _lines.v,
|
||||
top: Math.ceil(bounds.top + bounds.height + 5),
|
||||
left: _lines.v.left,
|
||||
originX: 'center',
|
||||
lockMovementY: true,
|
||||
}).addTo(viewport.canvas).on('moving', Event.onMove).trigger('moving');
|
||||
|
||||
_rect.v = new TextButton('V', textSettings).set({
|
||||
axis: 'top',
|
||||
marker: _lines.h,
|
||||
top: _lines.h.top,
|
||||
left: Math.ceil(bounds.left + bounds.width + 5),
|
||||
originY: 'center',
|
||||
lockMovementX: true,
|
||||
}).addTo(viewport.canvas).on('moving', Event.onMove).trigger('moving');
|
||||
|
||||
viewport.canvas.renderAll();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {RulerHandler}
|
||||
*/
|
||||
this.reset = function () {
|
||||
return this.enable(_enabled);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = RulerHandler;
|
||||
@@ -0,0 +1,120 @@
|
||||
'use strict';
|
||||
|
||||
var defaults = {
|
||||
activeBackground: '#000',
|
||||
background: '#000',
|
||||
color: '#fff',
|
||||
fontFamily: 'breuer',
|
||||
fontSize: 12,
|
||||
padding: 10,
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} text
|
||||
* @param {Object} settings
|
||||
*/
|
||||
function TextButton(text, settings) {
|
||||
fabric.Group.call(this);
|
||||
|
||||
var _callback = function () {};
|
||||
|
||||
var _rect = null;
|
||||
var _text = null;
|
||||
|
||||
settings = $.extend({}, defaults, settings);
|
||||
|
||||
settings.text = Array.isArray(text) ? text[0] : text;
|
||||
settings.textActive = Array.isArray(text) ? text[1] : text;
|
||||
|
||||
var _rectSettings = {
|
||||
fill: settings.background,
|
||||
width: settings.width,
|
||||
height: settings.height,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
};
|
||||
|
||||
var _textSettings = {
|
||||
fill: settings.color,
|
||||
fontFamily: settings.fontFamily,
|
||||
fontSize: settings.fontSize,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
};
|
||||
|
||||
// If width or height is omitted, the size for this button needs to be
|
||||
// calculated when setting Text.
|
||||
// An initial value for width and height needs to be set, else we won't
|
||||
// render correctly.
|
||||
if ((settings.dynamicW = !settings.width)) {
|
||||
_rectSettings.width = 1;
|
||||
}
|
||||
|
||||
if ((settings.dynamicH = !settings.height)) {
|
||||
_rectSettings.height = 1;
|
||||
}
|
||||
|
||||
// Make sure we're interactive
|
||||
this.selectable = true;
|
||||
|
||||
this.hoverCursor = 'default';
|
||||
|
||||
// Initialize text and rectangle
|
||||
_text = new fabric.Text('', _textSettings);
|
||||
_rect = new fabric.Rect(_rectSettings);
|
||||
this.addWithUpdate(_rect)
|
||||
.addWithUpdate(_text);
|
||||
|
||||
var Event = {
|
||||
mouseDown: function (e) {
|
||||
this.__active = !this.__active;
|
||||
_rect.setFill(this.__active ? settings.activeBackground : settings.background);
|
||||
this.setText(settings[this.isActive() ? 'textActive' : 'text']);
|
||||
_callback.call(this, e);
|
||||
|
||||
if (this.__group) {
|
||||
this.__group.render();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {Boolean}
|
||||
*/
|
||||
this.isActive = function () {
|
||||
return this.__active;
|
||||
};
|
||||
|
||||
this.onClick = function (callback) {
|
||||
_callback = callback || function () {};
|
||||
this.on('mousedown', Event.mouseDown);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} text
|
||||
* @return {TextButton}
|
||||
*/
|
||||
this.setText = function (text) {
|
||||
_text.setText((text || '').toString()).setCoords();
|
||||
|
||||
if (settings.dynamicW) {
|
||||
this.width = _rect.width = _text.width + settings.padding;
|
||||
}
|
||||
|
||||
if (settings.dynamicH) {
|
||||
this.height = _rect.height = _text.height + settings.padding;
|
||||
}
|
||||
|
||||
return this.setCoords();
|
||||
};
|
||||
|
||||
if (settings.text) {
|
||||
this.setText(settings.text);
|
||||
}
|
||||
}
|
||||
|
||||
TextButton.prototype = Object.create(fabric.Group.prototype);
|
||||
TextButton.prototype.constructor = TextButton;
|
||||
|
||||
module.exports = TextButton;
|
||||
@@ -0,0 +1,124 @@
|
||||
/* jshint -W097 */
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
assertKeyValuePair: function (key, value) {
|
||||
if (typeof key === 'object') {
|
||||
return key;
|
||||
}
|
||||
|
||||
var returnValue = {};
|
||||
returnValue[key] = value;
|
||||
|
||||
return returnValue;
|
||||
},
|
||||
|
||||
assertBetween: function (value, min, max) {
|
||||
if (value < min) {
|
||||
return min;
|
||||
}
|
||||
if (value > max) {
|
||||
return max;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Integer} width
|
||||
* @param {Integer} height
|
||||
* @return {Object}
|
||||
* axis: STRING,
|
||||
* dim: OBJECT( width: NUMBER, height: NUMBER),
|
||||
* width: NUMBER,
|
||||
* height: NUMBER,
|
||||
* ppmm: NUMBER
|
||||
*/
|
||||
calcCrop: function (obj, width, height) {
|
||||
var cropRatio = width / height;
|
||||
var objRatio = obj.width / obj.height;
|
||||
|
||||
var returnValue = {
|
||||
image: obj,
|
||||
axis: objRatio > cropRatio ? 'x' : 'y',
|
||||
dim: { width: width, height: height },
|
||||
width: obj.width,
|
||||
height: obj.height
|
||||
};
|
||||
|
||||
if (objRatio > cropRatio) {
|
||||
returnValue.width *= cropRatio / objRatio;
|
||||
} else {
|
||||
returnValue.height /= cropRatio / objRatio;
|
||||
}
|
||||
|
||||
// Pixels per milimeter
|
||||
returnValue.ppmm = returnValue.width / (returnValue.dim.width * 10);
|
||||
|
||||
return returnValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {fabric.Object} obj
|
||||
* @param {Object} bounds
|
||||
* @return {fabric.Object}
|
||||
*/
|
||||
setPositionInside: function (obj, bounds) {
|
||||
['left', 'top'].forEach(function (v) {
|
||||
if (obj[v] < bounds[v].min) {
|
||||
obj.set(v, bounds[v].min).setCoords();
|
||||
}
|
||||
|
||||
if (obj[v] > bounds[v].max) {
|
||||
obj.set(v, bounds[v].max).setCoords();
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Object} obj
|
||||
* @param {Object} properties
|
||||
*/
|
||||
setProperties: function (obj, properties) {
|
||||
for (var o in properties) {
|
||||
if (properties.hasOwnProperty(o)) {
|
||||
Object.defineProperty(obj, o, properties[o]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles the full screen state for passed DOM object
|
||||
* @param {HTMLElement} elm
|
||||
*/
|
||||
toggleFullScreen: function (elm) {
|
||||
var isFullScreen =
|
||||
document.fullscreenElement ||
|
||||
document.mozFullScreenElement ||
|
||||
document.webkitFullscreenElement ||
|
||||
document.msFullscreenElement;
|
||||
|
||||
if (isFullScreen) {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen();
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
} else if (document.webkitExitFullscreen) {
|
||||
document.webkitExitFullscreen();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(elm.requestFullScreen) {
|
||||
elm.requestFullScreen();
|
||||
}
|
||||
else if(elm.webkitRequestFullScreen) {
|
||||
elm.webkitRequestFullScreen();
|
||||
}
|
||||
else if(elm.mozRequestFullScreen) {
|
||||
elm.mozRequestFullScreen();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,148 @@
|
||||
'use strict';
|
||||
|
||||
var GoreHandler = require('./GoreHandler');
|
||||
var RulerHandler = require('./RulerHandler');
|
||||
var util = require('./Util');
|
||||
|
||||
function Viewport(canvas) {
|
||||
var _beams = [];
|
||||
var _borderWidth = 2;
|
||||
var _data = null;
|
||||
var _rect;
|
||||
|
||||
/**
|
||||
* Applies viewport to page
|
||||
*/
|
||||
function apply() {
|
||||
canvas.remove(_rect);
|
||||
|
||||
_rect = new fabric.Rect({
|
||||
evented: false,
|
||||
fill: 'transparent',
|
||||
width: _data.width,
|
||||
height: _data.height,
|
||||
stroke: '#fff',
|
||||
strokeWidth: _borderWidth,
|
||||
});
|
||||
|
||||
_rect.width += _borderWidth;
|
||||
_rect.height += _borderWidth;
|
||||
_rect.addTo(canvas).center().setCoords();
|
||||
|
||||
canvas.image
|
||||
.center()
|
||||
.drag.enable(calcMinMaxBoundsForRect(_rect.getInsideBoundingRect(), canvas.image));
|
||||
canvas.aperture.apply(_data.axis, _rect.getBoundingRect());
|
||||
|
||||
drawBeams();
|
||||
canvas.dragbars.apply();
|
||||
|
||||
// Apertures sometimes overlaps the viewports bounding rect.
|
||||
// Solve this by bringing it to the front after apertures are applied.
|
||||
_rect.bringToFront();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render the diagonal lines from viewport to edge of the canvas
|
||||
*/
|
||||
function drawBeams() {
|
||||
_beams.forEach(function (o) {
|
||||
canvas.remove(o);
|
||||
});
|
||||
|
||||
_beams = [];
|
||||
|
||||
// TOP LEFT
|
||||
_beams.push(new fabric.Line(
|
||||
[_rect.left, _rect.top, _rect.left - _rect.top, -1], {
|
||||
stroke: '#fff',
|
||||
strokeWidth: 2,
|
||||
}
|
||||
));
|
||||
|
||||
// TOP RIGHT
|
||||
_beams.push(_beams[0].clone().set({ flipX: true, left: _rect.left + _rect.width }));
|
||||
// BOTTOM RIGHT
|
||||
_beams.push(_beams[1].clone().set({ flipY: true, top: _rect.top + _rect.height }));
|
||||
// BOTTOM LEFT
|
||||
_beams.push(_beams[0].clone().set({ flipY: true, top: _rect.top + _rect.height }));
|
||||
|
||||
_beams.forEach(function (o) {
|
||||
canvas.add(o);
|
||||
o.bringToFront();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an object with min / max values for each axis, based on the bounds
|
||||
* of passed fabric.Rect
|
||||
* @param {fabric.Rect} rect
|
||||
* @return {Object}
|
||||
*/
|
||||
function calcMinMaxBoundsForRect(rect, img) {
|
||||
return {
|
||||
left: {
|
||||
min: rect.left + rect.width - img.width,
|
||||
max: rect.left
|
||||
},
|
||||
top: {
|
||||
min: rect.top + rect.height - img.height,
|
||||
max: rect.top
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
this.canvas = canvas;
|
||||
|
||||
this.getBounds = function () {
|
||||
return _rect.getInsideBoundingRect();
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {Viewport}
|
||||
*/
|
||||
this.reset = function () {
|
||||
if (_data) {
|
||||
return this.set(_data.dim.width, _data.dim.height);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Number} width
|
||||
* @param {Number} height
|
||||
* @return {Viewport}
|
||||
*/
|
||||
this.set = function (width, height) {
|
||||
_data = util.calcCrop(canvas.image, width, height);
|
||||
apply();
|
||||
this.gores.reset();
|
||||
this.rulers.reset();
|
||||
canvas.aperture.setTransparent(true);
|
||||
canvas.image.__moved = false;
|
||||
canvas.topMenu.bringToFront();
|
||||
};
|
||||
|
||||
util.setProperties(this, {
|
||||
data: {
|
||||
get: function () {
|
||||
return _data;
|
||||
}
|
||||
},
|
||||
gores: {
|
||||
get: function () {
|
||||
return this.__goreHandler ||
|
||||
(this.__goreHandler = new GoreHandler(this));
|
||||
}
|
||||
},
|
||||
rulers: {
|
||||
get: function () {
|
||||
return this.__rulerHandler ||
|
||||
(this.__rulerHandler = new RulerHandler(this));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = Viewport;
|
||||
@@ -0,0 +1,61 @@
|
||||
'use strict';
|
||||
|
||||
var Draggable = require('../Draggable');
|
||||
var ImageTransformationHandler = require('../ImageTransformationHandler');
|
||||
var util = require('../Util');
|
||||
|
||||
$.extend(fabric.Object.prototype, {
|
||||
cornerSize: 0,
|
||||
hasBorders: false,
|
||||
hasControls: false,
|
||||
padding: 0,
|
||||
selectable: false,
|
||||
strokeWidth: 0,
|
||||
addTo: function (canvas) {
|
||||
canvas.add(this);
|
||||
return this;
|
||||
},
|
||||
});
|
||||
|
||||
util.setProperties(fabric.Image.prototype, {
|
||||
drag: {
|
||||
get: function () {
|
||||
return this.__draggable || (this.__draggable = new Draggable(this));
|
||||
}
|
||||
},
|
||||
|
||||
transformation: {
|
||||
get: function () {
|
||||
return this.__ImageTransformationHandler ||
|
||||
(this.__ImageTransformationHandler = new ImageTransformationHandler(this));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$.extend(fabric.Rect.prototype, {
|
||||
/**
|
||||
* Gets the inner bounds of this fabric.Rect
|
||||
* @return {Object}
|
||||
*/
|
||||
getInsideBoundingRect: function () {
|
||||
var bounds = this.getBoundingRect();
|
||||
var returnValue = {
|
||||
left: bounds.left + this.strokeWidth,
|
||||
top: bounds.top + this.strokeWidth,
|
||||
width: bounds.width - this.strokeWidth * 2,
|
||||
height: bounds.height - this.strokeWidth * 2
|
||||
};
|
||||
|
||||
returnValue.min = {
|
||||
left: returnValue.left,
|
||||
top: returnValue.top
|
||||
};
|
||||
|
||||
returnValue.max = {
|
||||
left: returnValue.left + returnValue.width,
|
||||
top: returnValue.top + returnValue.height
|
||||
};
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
activeBackground: '#000',
|
||||
background: '#444',
|
||||
fontSize: 14,
|
||||
height: 30,
|
||||
padding: 20
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
require('./components/ImageEditor/fabric.ext/ObjectDefaults');
|
||||
//require('./components/ImageEditor/fabric.ext/BaseEventHandlers');
|
||||
require('./components/ImageEditor/ImageEditor');
|
||||
}());
|
||||
Reference in New Issue
Block a user