263 lines
9.6 KiB
JavaScript
263 lines
9.6 KiB
JavaScript
/**
|
|
* @author Szymon Działowski
|
|
* @homepage https://bitbucket.org/stopsopa/jquery.line
|
|
* @ver 1.0 2014-07-06
|
|
* @ver 1.1 2014-07-07 upgrades, corrections
|
|
* @ver 1.2 2015-05-01 drawing line by rad/ang and distance from point x and x, fix manual
|
|
*/
|
|
|
|
(function( factory ) {
|
|
if ( typeof define === "function" && define.amd ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
define([ "jquery" ], factory );
|
|
} else {
|
|
|
|
// Browser globals
|
|
factory( jQuery );
|
|
}
|
|
})((function (name, pi) {
|
|
return function ($) {
|
|
function log(l) {try {console.log(l);}catch (e) {}};
|
|
function error(l) {try {console.error(l);}catch (e) {}};
|
|
function _thw(message) {throw "plugin jQuery(...)."+name+"() : "+message};
|
|
function _a(a) {
|
|
return Array.prototype.slice.call(a, 0);
|
|
}
|
|
function isFunction (a) { // taken from underscore.js
|
|
return typeof a == 'function' || false;
|
|
};
|
|
function isObject(obj) {
|
|
var type = typeof obj;
|
|
return type === 'function' || type === 'object' && !!obj;
|
|
};
|
|
function angToRad(ang) {
|
|
return ang * (pi / 180);
|
|
}
|
|
function radToAng(rad) {
|
|
return rad * (180 / pi) ;
|
|
}
|
|
// calc distance between two points
|
|
function calcDistance(x1, y1, x2, y2) { // http://www.gwycon.com/calculating-the-distance-between-two-pixels/
|
|
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
|
|
}
|
|
// count angle in radians
|
|
function calcAngleRad(x1, y1, x2, y2) {
|
|
return Math.atan2( (y2 - y1) , (x2 - x1) );
|
|
}
|
|
// count angle in degrees
|
|
function calcAngle(x1, y1, x2, y2) {
|
|
var a = calcAngleRad(x1, y1, x2, y2) * (180 / pi);
|
|
return (a < 0) ? (a += 360) : a;
|
|
}
|
|
function calcXYOffsetByVectorAngleRad(rad, dis) {
|
|
return { // http://stackoverflow.com/a/10962780
|
|
x : Math.cos(rad) * dis,
|
|
y : Math.sin(rad) * dis
|
|
}
|
|
}
|
|
function calcXYOffsetByVectorAngle(ang, dis) {
|
|
return calcXYOffsetByVectorAngleRad(angToRad(ang), dis);
|
|
}
|
|
// count correction
|
|
function correct(x1, y1, x2, y2, o, ang) {
|
|
ang || (ang = calcAngle(x1, y1, x2, y2));
|
|
|
|
var hw = o.width/2;
|
|
var hwo = hw // originial
|
|
|
|
var sw = false;
|
|
|
|
if ($.isNumeric(o.correct)) {
|
|
var c = o.correct;
|
|
switch(true) {
|
|
case o.correctpos == 'normal':
|
|
hw += c;
|
|
break;
|
|
case o.correctpos == 'top' && (ang > 90 && ang < 270) :
|
|
sw = true;
|
|
c = - Math.abs(c);
|
|
break;
|
|
case o.correctpos == 'bottom' && (ang < 90 || ang > 270) :
|
|
sw = true;
|
|
c = - Math.abs(c);
|
|
break;
|
|
case o.correctpos == 'left' && (ang > 0 && ang < 180) :
|
|
sw = true;
|
|
c = - Math.abs(c);
|
|
break;
|
|
case o.correctpos == 'right' && (ang < 0 || ang > 180) :
|
|
sw = true;
|
|
c = - Math.abs(c);
|
|
break;
|
|
}
|
|
hw += c;
|
|
}
|
|
|
|
var rad = calcAngleRad(x1, y1, x2, y2); // radians
|
|
var radminhalf = (rad - (pi / 2)); // radians minus half radian
|
|
|
|
var c = {};
|
|
if (o.correct === false) {
|
|
c.x = c.y = c.oy = c.ox = 0;
|
|
}
|
|
else {
|
|
c.y = Math.sin(radminhalf) * hw;
|
|
c.x = Math.cos(radminhalf) * hw;
|
|
c.oy = Math.sin(radminhalf) * hwo; // without correction
|
|
c.ox = Math.cos(radminhalf) * hwo; // without correction
|
|
}
|
|
c.ang = ang;
|
|
c.rad = rad
|
|
c.ox2 = c.ox * 2;
|
|
c.oy2 = c.oy * 2;
|
|
c.x1 = x1;
|
|
c.y1 = y1;
|
|
c.x2 = x2;
|
|
c.y2 = y2;
|
|
|
|
if (sw) {
|
|
c.ax = c.x1 - c.ox2;
|
|
c.ay = c.y1 - c.oy2;
|
|
|
|
c.bx = c.ax + c.x;
|
|
c.by = c.ay + c.y;
|
|
|
|
c.cx = c.x2 + c.x
|
|
c.cy = c.y2 + c.y;
|
|
|
|
c.dx = c.cx - c.ox2;
|
|
c.dy = c.cy - c.oy2;
|
|
}
|
|
else {
|
|
c.bx = c.x1 + c.x;
|
|
c.by = c.y1 + c.y;
|
|
|
|
c.ax = c.bx - c.ox2;
|
|
c.ay = c.by - c.oy2;
|
|
|
|
c.dx = c.x2 + c.x;
|
|
c.dy = c.y2 + c.y;
|
|
|
|
c.cx = c.dx - c.ox2
|
|
c.cy = c.dy - c.oy2;
|
|
}
|
|
|
|
return c;
|
|
}
|
|
/**
|
|
* @returns jQuery object representing line
|
|
* var linediv = $.line(x1, y1, x2, y2, opt, callback);
|
|
* var linediv = $('parent element').line(x1, y1, x2, y2, opt, callback);
|
|
* var linediv = $('parent element').line(x1, y1, {ang: 45, dis: 200}, opt, callback);
|
|
* var linediv = $.line(x1, y1, {ang: 45, dis: 200}, opt, callback);
|
|
*/ //0 1 2 3 4 5
|
|
$.fn[name] = function (x1, y1, x2, y2, opt, callback) {
|
|
|
|
if (isObject(x2)) {
|
|
var k = 0, a = _a(arguments);
|
|
|
|
if (typeof x2.ang != 'undefined')
|
|
k = calcXYOffsetByVectorAngle(x2.ang, x2.dis);
|
|
|
|
else if (typeof x2.rad != 'undefined')
|
|
k = calcXYOffsetByVectorAngleRad(x2.rad, x2.dis);
|
|
|
|
else _thw("Arguments incomplete: "+JSON.stringify(a));
|
|
|
|
a[5] = a[4];
|
|
a[4] = a[3];
|
|
a[2] = x1 + k.x;
|
|
a[3] = y1 + k.y;
|
|
log(a);
|
|
|
|
return $.fn[name].apply(this, a);
|
|
}
|
|
|
|
if (isFunction(opt)) {
|
|
callback = opt;
|
|
}
|
|
else if (isFunction(callback)) {
|
|
opt = callback;
|
|
}
|
|
|
|
opt || (opt = {});
|
|
|
|
if ($(this).length > 1)
|
|
throw "$(this) is more then one element";
|
|
|
|
var o = {
|
|
style: 'solid',
|
|
width: 1,
|
|
color: 'black',
|
|
|
|
cls: 'jqline',
|
|
id: false,
|
|
correct: true, // bool|int - corection of position, give integer to move
|
|
correctpos: 'normal', // normal, top, bottom, left, right
|
|
css: {
|
|
height: '0',
|
|
zIndex: '999',
|
|
zoom: 1
|
|
}
|
|
}
|
|
|
|
if (opt.css) {
|
|
$.extend(o.css, opt.css);
|
|
opt.css = o.css;
|
|
}
|
|
|
|
o = $.extend(true, o, opt || {});
|
|
o.create = opt.create ? $(opt.create) : $('<div></div>');
|
|
var ang = calcAngle(x1, y1, x2, y2); // degrees
|
|
var c = correct(x1, y1, x2, y2, o/* half of line width */, ang);
|
|
c.distance = calcDistance(x1, y1, x2, y2);
|
|
|
|
o.create
|
|
.css({
|
|
borderTop: o.width+'px '+o.style+' '+o.color,
|
|
position: 'absolute',
|
|
width: c.distance + 'px',
|
|
'-webkit-transform': 'rotate(' + ang + 'deg)',
|
|
'-moz-transform': 'rotate(' + ang + 'deg)',
|
|
'-ms-transform': 'rotate(' + ang + 'deg)',
|
|
'-o-transform': 'rotate(' + ang + 'deg)',
|
|
transform: 'rotate(' + ang + 'deg)',
|
|
|
|
'transform-origin' : '0 0',
|
|
'-ms-transform-origin' : '0 0', /* IE 9 */
|
|
'-webkit-transform-origin' : '0 0', /* Chrome, Safari, Opera */
|
|
|
|
left : (x1 + c.x)+'px',
|
|
top : (y1 + c.y)+'px'
|
|
})
|
|
.css(o.css)
|
|
;
|
|
|
|
o.cls && o.create.addClass(o.cls);
|
|
o.id && o.create.attr('id', o.id);
|
|
|
|
o.create.appendTo(this);
|
|
|
|
(isFunction(callback)) && callback(o.create, o, c);
|
|
|
|
return o.create;
|
|
};
|
|
/**
|
|
* @returns jQuery object representing line
|
|
*/
|
|
$[name] = function () {
|
|
var b = $('body');
|
|
return b[name].apply(b, arguments);
|
|
};
|
|
|
|
// expose tools to use outside
|
|
$[name].radToAng = radToAng;
|
|
$[name].angToRad = angToRad;
|
|
$[name].calcDistance = calcDistance;
|
|
$[name].calcAngleRad = calcAngleRad;
|
|
$[name].calcAngle = calcAngle;
|
|
$[name].calcXYOffsetByVectorAngle = calcXYOffsetByVectorAngle;
|
|
$[name].calcXYOffsetByVectorAngleRad = calcXYOffsetByVectorAngleRad;
|
|
}
|
|
})('line', Math.PI)); // to change name of plugin simply change it in this place
|