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