You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

327 lines
10 KiB
JavaScript

"use strict";
var ruler = function (options) {
this.api = this.builder();
this.api.constructRulers.call(this, options);
};
ruler.prototype.builder = function(){
var VERTICAL = 1,
HORIZONTAL = 2,
CUR_DELTA_X = 0,
CUR_DELTA_Y = 0,
CUR_SCALE = 1;
var options,
rulerz = {},
guides = [],
theRulerDOM = document.createElement('div'),
corners = [],
defaultOptions = {
rulerHeight: 15,
fontFamily: 'arial',
fontSize: '8px',
strokeStyle: 'gray',
sides: ['top', 'left'],
cornerSides: ['TL'],
lineWidth: 1,
enableMouseTracking: true,
enableToolTip: true
};
var rotateRuler = function (curRuler, angle) {
var rotation = 'rotate(' + angle + 'deg)';
var origin = ruler.prototype.utils.pixelize(Math.abs(parseInt(curRuler.canvas.style.left))) + ' 100%';
curRuler.canvas.style.webkitTransform = rotation;
curRuler.canvas.style.MozTransform = rotation;
curRuler.canvas.style.OTransform = rotation;
curRuler.canvas.style.msTransform = rotation;
curRuler.canvas.style.transform = rotation;
curRuler.canvas.style.webkitTransformOrigin = origin;
curRuler.canvas.style.MozTransformOrigin = origin;
curRuler.canvas.style.OTransformOrigin = origin;
curRuler.canvas.style.msTransformOrigin = origin;
curRuler.canvas.style.transformOrigin = origin;
};
var positionRuler = function (curRuler, alignment) {
curRuler.canvas.style.left = ruler.prototype.utils.pixelize(-((curRuler.canvas.width / 2) - curRuler.canvas.height));
switch (alignment) {
case 'top':
curRuler.orgPos = parseInt(curRuler.canvas.style.left);
break;
case 'left':
curRuler.canvas.style.top = ruler.prototype.utils.pixelize(-curRuler.canvas.height - 1);
curRuler.orgPos = parseInt(curRuler.canvas.style.top);
rotateRuler(curRuler, 90);
break;
}
};
var attachListeners = function (container, curRul) {
var mousedown = function (e) {
constructGuide(curRul.dimension, e.clientX, e.clientY, e);
};
curRul.canvas.addEventListener('mousedown', mousedown);
curRul.clearListeners = function () {
curRul.canvas.removeEventListener('mousedown', mousedown);
}
};
var constructGuide = function (dimension, x, y, e, isSet) {
var guideIndex;
var moveCB = function (line, x, y) {
var coor = line.dimension === VERTICAL ? x : y;
if (!line.assigned()) {
if (coor > options.rulerHeight) {
line.assigned(true);
}
return;
}
if (coor < options.rulerHeight) {
guides.some(function (guideLine, index) {
if (guideLine.line === line) {
guideIndex = index;
return true;
}
});
line.destroy();
guides.splice(guideIndex, 1);
}
};
var guide = document.createElement('div'),
guideStyle = dimension === VERTICAL ? 'rul_lineVer' : 'rul_lineHor',
curDelta = dimension === VERTICAL ? CUR_DELTA_X : CUR_DELTA_Y;
guide.title = 'Double click to delete';
ruler.prototype.utils.addClasss(guide, ['rul_line', guideStyle]);
guide = theRulerDOM.appendChild(guide);
if (dimension === VERTICAL) {
guide.style.left = ruler.prototype.utils.pixelize(x - options.container.getBoundingClientRect().left);
if (isSet) guide.style.left = ruler.prototype.utils.pixelize( Math.round( x / CUR_SCALE ) + options.rulerHeight );
}
else {
guide.style.top = ruler.prototype.utils.pixelize(y - options.container.getBoundingClientRect().top);
if (isSet) guide.style.top = ruler.prototype.utils.pixelize( Math.round( y / CUR_SCALE ) + options.rulerHeight );
}
guides.push({
dimension: dimension,
line: ruler.prototype.guideLine(guide, options.container.querySelector('.rul_wrapper'), dimension, options, curDelta, moveCB, e)
});
};
var constructRuler = function (container, alignment) {
var canvas,
dimension = alignment === 'left' || alignment === 'right' ? VERTICAL : HORIZONTAL,
rulerStyle = dimension === VERTICAL ? 'rul_ruler_Vertical' : 'rul_ruler_Horizontal',
element = document.createElement('canvas');
ruler.prototype.utils.addClasss(element, ['rul_ruler', rulerStyle, 'rul_align_' + alignment]);
canvas = container.appendChild(element);
rulerz[alignment] = ruler.prototype.rulerConstructor(canvas, options, dimension);
rulerz[alignment].drawRuler(container.offsetWidth, options.rulerHeight);
positionRuler(rulerz[alignment], alignment);
attachListeners(container, rulerz[alignment]);
};
var constructCorner = (function () {
function cornerDraw(container, side) {
var corner = document.createElement('div'),
cornerStyle = 'rul_corner' + side.toUpperCase();
corner.title = 'Clear Guide lines';
ruler.prototype.utils.addClasss(corner, ['rul_corner', cornerStyle]);
corner.style.width = ruler.prototype.utils.pixelize(options.rulerHeight + 1);
corner.style.height = ruler.prototype.utils.pixelize(options.rulerHeight);
return container.appendChild(corner);
}
function mousedown(e) {
e.stopPropagation();
clearGuides();
}
return function (container, cornerSides) {
cornerSides.forEach(function (side) {
var corner = cornerDraw(container, side);
corner.addEventListener('mousedown', mousedown);
corner.destroy = function () {
corner.removeEventListener('mousedown', mousedown);
corner.parentNode.removeChild(corner);
};
corners.push(corner);
})
}
})();
var mouseup = function (e) {
guides.forEach(function (guide) {
guide.line.stopDrag();
})
};
var constructRulers = function (curOptions) {
theRulerDOM = ruler.prototype.utils.addClasss(theRulerDOM, 'rul_wrapper');
options = ruler.prototype.utils.extend(defaultOptions, curOptions);
theRulerDOM = options.container.appendChild(theRulerDOM);
options.sides.forEach(function (side) {
constructRuler(theRulerDOM, side);
});
constructCorner(theRulerDOM, options.cornerSides);
options.container.addEventListener('mouseup', mouseup);
};
var forEachRuler = function (cb) {
var index = 0;
for (var rul in rulerz) {
if (rulerz.hasOwnProperty(rul)) {
cb(rulerz[rul], index++);
}
}
};
var setPos = function (values) {
var orgX = 0,
orgY,
deltaX = 0,
deltaY = 0;
forEachRuler(function (curRul) {
if (curRul.dimension === VERTICAL) {
orgY = curRul.canvas.style.top;
curRul.canvas.style.top = ruler.prototype.utils.pixelize(curRul.orgPos + (parseInt(values.y)));
deltaY = parseInt(orgY) - parseInt(curRul.canvas.style.top);
}
else {
orgX = curRul.canvas.style.left;
curRul.canvas.style.left = ruler.prototype.utils.pixelize(curRul.orgPos + (parseInt(values.x)));
deltaX = parseInt(orgX) - parseInt(curRul.canvas.style.left);
}
});
guides.forEach(function (guide) {
if (guide.dimension === HORIZONTAL) {
guide.line.guideLine.style.top = ruler.prototype.utils.pixelize(parseInt(guide.line.guideLine.style.top) - deltaY);
guide.line.curPosDelta(parseInt(values.y));
}
else {
guide.line.guideLine.style.left = ruler.prototype.utils.pixelize(parseInt(guide.line.guideLine.style.left) - deltaX);
guide.line.curPosDelta(parseInt(values.x));
}
});
CUR_DELTA_X = parseInt(values.x);
CUR_DELTA_Y = parseInt(values.y);
};
var setScale = function (newScale) {
var curPos, orgDelta, curScaleFac;
forEachRuler(function (rul) {
rul.context.clearRect(0, 0, rul.canvas.width, rul.canvas.height);
rul.context.beginPath();
rul.setScale(newScale);
rul.context.stroke();
CUR_SCALE = newScale;
});
guides.forEach(function (guide) {
if (guide.dimension === HORIZONTAL) {
curPos = parseInt(guide.line.guideLine.style.top);
orgDelta = options.rulerHeight + 1;
curScaleFac = (parseFloat(newScale) / guide.line.curScale());
guide.line.guideLine.style.top = ruler.prototype.utils.pixelize(((curPos - orgDelta - CUR_DELTA_Y ) / curScaleFac) + orgDelta + CUR_DELTA_Y);
guide.line.curScale(newScale);
}
else {
curPos = parseInt(guide.line.guideLine.style.left);
orgDelta = options.rulerHeight + 1;
curScaleFac = (parseFloat(newScale) / guide.line.curScale());
guide.line.guideLine.style.left = ruler.prototype.utils.pixelize(((curPos - orgDelta - CUR_DELTA_X) / curScaleFac) + orgDelta + CUR_DELTA_X);
guide.line.curScale(newScale);
}
});
};
var clearGuides = function () {
guides.forEach(function (guide) {
guide.line.destroy();
});
guides = [];
};
var toggleGuideVisibility = function (val) {
var func = val ? 'show' : 'hide';
guides.forEach(function (guide) {
guide.line[func]();
});
};
var toggleRulerVisibility = function (val) {
var state = val ? 'block' : 'none';
theRulerDOM.style.display = state;
var trackers = options.container.querySelectorAll('.rul_tracker');
if (trackers.length > 0) {
trackers[0].style.display = state;
trackers[1].style.display = state;
}
};
var getGuides = function () {
return guides.map(function (guide) {
return {
posX: Math.round((parseInt(guide.line.guideLine.style.left) - CUR_DELTA_X - options.rulerHeight) * CUR_SCALE),
posY: Math.round((parseInt(guide.line.guideLine.style.top) - CUR_DELTA_Y - options.rulerHeight) * CUR_SCALE),
dimension: guide.dimension
}
});
};
var setGuides = function (_guides) {
if(!_guides){return}
_guides.forEach(function (guide) {
constructGuide(guide.dimension, guide.posX, guide.posY, null, true)
})
};
var destroy = function () {
clearGuides();
forEachRuler(function (ruler) {
ruler.destroy();
});
corners.forEach(function (corner) {
corner.destroy();
});
options.container.removeEventListener('mouseup', mouseup);
theRulerDOM.parentNode.removeChild(theRulerDOM);
};
return {
VERTICAL: VERTICAL,
HORIZONTAL: HORIZONTAL,
setPos: setPos,
setScale: setScale,
clearGuides: clearGuides,
getGuides: getGuides,
setGuides: setGuides,
constructRulers: constructRulers,
toggleRulerVisibility: toggleRulerVisibility,
toggleGuideVisibility: toggleGuideVisibility,
destroy: destroy
}
};