'use strict'; var FrameHandler = require('./FrameHandler'); 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; var self = this; /** * Applies viewport to page */ function apply() { var cropData = canvas.getImageData().getCropData(); canvas.remove(_rect); _rect = new fabric.Rect({ evented: false, fill: 'transparent', width: _data.width, height: _data.height, stroke: '#fff', strokeWidth: canvas.__type === 'canvas' ? 0 : _borderWidth }); _rect.width += _borderWidth; _rect.height += _borderWidth; _rect.addTo(canvas).center().setCoords(); if (cropData) { // Calculate the new position after screenresize and when the // image already has been cropped to a certain position. var left = _rect.left + _rect.strokeWidth - (canvas.getImage().width * canvas.getImage().scaleX * cropData.x); var top = _rect.top + _rect.strokeWidth - (canvas.getImage().height * canvas.getImage().scaleY * cropData.y); canvas.getImage().set({ left: left, top: top }).setCoords(); } else { canvas.getImage().center().setCoords(); } canvas.getImage().drag.enable(calcMinMaxBoundsForRect(_rect.getInsideBoundingRect(), canvas.getImage())) canvas.getApertures().apply(_data.axis, _rect.getBoundingRect()); if (canvas.__type !== 'canvas') { drawBeams(); } else { self.setFrame(self.getFrameHandler().getFrameType()); } canvas.getDragbars().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 (beam) { canvas.remove(beam); }); _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 * img.scaleX), max: rect.left }, top: { min: rect.top + rect.height - (img.height * img.scaleY), 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, _data.dim.units); } return this; }; /** * @param {Number} width * @param {Number} height * @param {string} units * @return {Viewport} */ this.set = function (width, height, units) { var oldData = _data; _data = util.calcCrop(canvas.getImage(), width, height, units); var keepCropping = (oldData && !util.isAspectChanged(oldData.dim.width, oldData.dim.height, width, height)); if (keepCropping) { canvas.getImageData().setCropData(); } apply(); this.getGores().reset(); this.getRulers().reset(); if (canvas.getImage().__cropped && !keepCropping) { canvas.getApertures().setTransparent(true); // Trigger event to tell the image needs to be dragged. $(document).trigger('PIE:needs-dragging', { axis: _data.axis }); } canvas.getButtonMenu().bringToFront(); }; /** * @param {string} frameType white|black|image|none * @return {Viewport} */ this.setFrame = function (frameType) { this.getFrameHandler().setFrames(frameType); var buttons = canvas.getButtonMenu().getItems(); if (frameType === 'none') { buttons[0].setDisabled(true); } else { buttons[0].setDisabled(false); } canvas.getButtonMenu().bringToFront(); canvas.refresh3dView(); }; this.getData = function () { return _data; }; var _frameHandler = null; this.getFrameHandler = function () { return _frameHandler || (_frameHandler = new FrameHandler(this)); }; this.getGores = function () { return this.__goreHandler || (this.__goreHandler = new GoreHandler(this)); }; this.getRulers = function () { return this.__rulerHandler || (this.__rulerHandler = new RulerHandler(this)); }; } module.exports = Viewport;