Initial commit

This commit is contained in:
Rikard Bartholf
2017-05-09 12:18:29 +02:00
commit c73e1ed9b4
29 changed files with 1481 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
node_modules
dist
+30
View File
@@ -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
}
+1
View File
@@ -0,0 +1 @@
# My project's README
+35
View File
@@ -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);
};
+24
View File
@@ -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
View File
@@ -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']);
+31
View File
@@ -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>
+28
View File
@@ -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;
}
+39
View File
@@ -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;
+102
View File
@@ -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;
+120
View File
@@ -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;
+124
View File
@@ -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();
}
}
};
+148
View File
@@ -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
};
+7
View File
@@ -0,0 +1,7 @@
(function () {
'use strict';
require('./components/ImageEditor/fabric.ext/ObjectDefaults');
//require('./components/ImageEditor/fabric.ext/BaseEventHandlers');
require('./components/ImageEditor/ImageEditor');
}());