最近看了一下excanvas.js,感觉是个好东西。
一直想用js实现拓扑功能,正好试一下。我用的是最新版的excanvas.js,还使用到了jquery和jquery ui的最新版。
效果图如下
四个节点都可以用鼠标拖拽,之间的连接线会跟着重画。
js代码如下
$.jvChart = $.jvChart || {};
$.extend($.jvChart,{
createElement : function(tag, attribs, styles, parent, nopad) {
var el = document.createElement(tag);
if (attribs) $(el).attr(attribs);
if (nopad) $(el).css({padding: 0, border: 'none', margin: 0});
if (styles) $(el).css(styles);
if (parent) parent.appendChild(el);
return el;
},
drawEllipse : function(paper, x, y, rx, ry, color, width, fill, shadow, image){
var ctx = paper.ctx;
ctx.beginPath();
var div = document.createElement("<div id='" + paper.getId() + "' style='position:absolute; cursor:move; left:" + x + "; top:" + y +
"; width:" + rx + "; height:" + ry + "; '></div>");
$(paper.canvas).append(div);
ctx.element_ = div;
$(div).draggable({
stop : function(event, ui){
$.jvChart.reDrawConnections(paper);
}
});
x = y = 0;
var hB = (rx / 2) * .5522848,
vB = (ry / 2) * .5522848,
eX = x + rx,
eY = y + ry,
mX = x + rx / 2,
mY = y + ry / 2;
ctx.moveTo(x, mY);
ctx.bezierCurveTo(x, mY - vB, mX - hB, y, mX, y);
ctx.bezierCurveTo(mX + hB, y, eX, mY - vB, eX, mY);
ctx.bezierCurveTo(eX, mY + vB, mX + hB, eY, mX, eY);
ctx.bezierCurveTo(mX - hB, eY, x, mY + vB, x, mY);
ctx.closePath();
if (color && width){
ctx.strokeStyle = color || "rgb(100, 100, 255)";
ctx.lineWidth = width || 2;
}
if (fill) {
ctx.fillStyle = setColor(fill, ctx);
ctx.fill();
}
ctx.stroke();
ctx.element_ = paper.canvas;
return div;
},
/* drawCircle : function(paper, x, y, rx, color, width, fill, shadow, image){
var ctx = paper.getCtx();
var div = document.createElement("<div style='position:absolute; cursor:move; left:" + x + "; top:" + y +
"; width:" + rx + "; height:" + rx + "; '></div>");
$(paper.canvas).append(div);
ctx.element_ = div;
$(div).draggable();
x = y = 0;
ctx.beginPath();
ctx.arc(x, y, rx, 0, 2*Math.PI, true);
if (color && width){
ctx.strokeStyle = color || "rgb(100, 100, 255)";
ctx.lineWidth = width || 2;
}
if (fill) {
ctx.fillStyle = setColor(fill, ctx);
ctx.fill();
}
ctx.stroke();
},*/
drawRect: function(paper, x, y, w, h, radius, color, width, fill, shadow, image) {
function drawPath() {
ctx.beginPath();
if (!radius) {
ctx.rect(x, y, w, h);
} else {
ctx.moveTo(x, y + radius);
ctx.lineTo(x, y + h - radius);
ctx.quadraticCurveTo(x, y + h, x + radius, y + h); // change: use bezier
ctx.lineTo(x + w - radius, y + h);
ctx.quadraticCurveTo(x + w, y + h, x + w, y + h - radius);
ctx.lineTo(x + w, y + radius);
ctx.quadraticCurveTo(x + w, y , x + w - radius, y);
ctx.lineTo(x + radius, y);
ctx.quadraticCurveTo(x , y, x, y + radius);
}
ctx.closePath();
};
var ctx = paper.ctx, normalizer = (width || 0) % 2 / 2;
var div = document.createElement("<div id='" + paper.getId() + "' style='position:absolute; cursor:move; left:" + x + "; top:" + y +
"; width:" + w + "; height:" + h + "; '></div>");
$(paper.canvas).append(div);
ctx.element_ = div;
$(div).draggable({
stop : function(event, ui){
$.jvChart.reDrawConnections(paper);
}
});
x = y = 0;
x = Math.round(x) + normalizer;
y = Math.round(y) + normalizer;
w = Math.round(w);
h = Math.round(h);
// apply the drop shadow
if (shadow) for (var i = 1; i <= 3; i++) {
drawRect(paper, x + 1, y + 1, w, h, radius, 'rgba(0, 0, 0, '+ (0.05 * i) +')',
6 - 2 * i);
}
// apply the background image behind everything
if (image) ctx.drawImage(image, x, y, w, h);
drawPath();
if (fill) {
ctx.fillStyle = setColor(fill, ctx);
ctx.fill();
// draw path again
if (win.G_vmlCanvasManager) drawPath();
}
if (width) {
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.stroke();
}
ctx.element_ = paper.canvas;
return div;
},
drawConnection : function (paper, obj1, obj2, color, width){
var ctx = paper.ctx;
var p = [{x: parseInt($(obj1).css('left')) + $(obj1).width() / 2, y: parseInt($(obj1).css('top')) - 1},
{x: parseInt($(obj1).css('left')) + $(obj1).width() / 2, y: parseInt($(obj1).css('top')) + $(obj1).height() + 1},
{x: parseInt($(obj1).css('left')) - 1, y: parseInt($(obj1).css('top')) + $(obj1).height() / 2},
{x: parseInt($(obj1).css('left')) + $(obj1).width() + 1, y: parseInt($(obj1).css('top')) + $(obj1).height() / 2},
{x: parseInt($(obj2).css('left')) + $(obj2).width() / 2, y: parseInt($(obj2).css('top')) - 1},
{x: parseInt($(obj2).css('left')) + $(obj2).width() / 2, y: parseInt($(obj2).css('top')) + $(obj2).height() + 1},
{x: parseInt($(obj2).css('left')) - 1, y: parseInt($(obj2).css('top')) + $(obj2).height() / 2},
{x: parseInt($(obj2).css('left')) + $(obj2).width() + 1, y: parseInt($(obj2).css('top')) + $(obj2).height() / 2}];
var d = {}, dis = [];
for (var i = 0; i < 4; i++) {
for (var j = 4; j < 8; j++) {
var dx = Math.abs(p[i].x - p[j].x),
dy = Math.abs(p[i].y - p[j].y);
if ((i == j - 4) || (((i != 3 && j != 6) || p[i].x < p[j].x) && ((i != 2 && j != 7) || p[i].x > p[j].x) && ((i != 0 && j != 5) || p[i].y > p[j].y) && ((i != 1 && j != 4) || p[i].y < p[j].y))) {
dis.push(dx + dy);
d[dis[dis.length - 1]] = [i, j];
}
}
}
if (dis.length == 0) {
var res = [0, 4];
} else {
var res = d[Math.min.apply(Math, dis)];
}
var x1 = p[res[0]].x,
y1 = p[res[0]].y,
x4 = p[res[1]].x,
y4 = p[res[1]].y/*,
dx = Math.max(Math.abs(x1 - x4) / 2, 10),
dy = Math.max(Math.abs(y1 - y4) / 2, 10),
x2 = [x1, x1, x1 - dx, x1 + dx][res[0]].toFixed(3),
y2 = [y1 - dy, y1 + dy, y1, y1][res[0]].toFixed(3),
x3 = [0, 0, 0, 0, x4, x4, x4 - dx, x4 + dx][res[1]].toFixed(3),
y3 = [0, 0, 0, 0, y1 + dy, y1 - dy, y4, y4][res[1]].toFixed(3)*/;
ctx.beginPath();
ctx.strokeStyle = color;
ctx.lineWidth = width;
ctx.moveTo(x1, y1);
ctx.lineTo(x4, y4);
ctx.closePath();
ctx.stroke();
},
reDrawConnections : function (paper){
paper.edgePaper.ctx.clearRect(0, 0, paper.width, paper.height);
$(paper.edgePaper.edges).each(function(i){
$.jvChart.drawConnection(paper.edgePaper, document.getElementById(paper.edgePaper.edges[i][0]), document.getElementById(paper.edgePaper.edges[i][1]), 'rgb(0,0,0)', 2);
});
}
});
(function($) {
$.fn.jvChart = function(width, height) {
var paper = {
idCounter : 0,
idPrefix : "jvChart-element-",
getId : function() { return this.idPrefix + this.idCounter++; }
};
var edgePaper = {
idCounter : 0,
idPrefix : "jvChart-edge-",
getId : function() { return this.idPrefix + this.idCounter++; },
edges : []
};
function getCtx(paper){
var cvs = $.jvChart.createElement('canvas', {
id: paper.getId(),
width: $(paper.canvas).width(),
height: $(paper.canvas).height()
}, {position: 'absolute'}, paper.canvas);
if ($.browser.msie) {
G_vmlCanvasManager.initElement(cvs);
cvs = document.getElementById(cvs.id);
$('div', cvs).first().attr('id', paper.idPrefix + 'div');
}
return cvs.getContext('2d');
}
return this.each( function() {
paper.canvas = this;
edgePaper.canvas = this;
$(this).css({overflow:'hidden', position:'relative'});
paper.ctx = getCtx(paper);
edgePaper.ctx = getCtx(edgePaper);
paper.edgePaper = edgePaper;
paper.width = $(paper.canvas).width();
paper.height = $(paper.canvas).height();
this.paper = paper;
this.edgePaper = edgePaper;
});
};
$.fn.extend({
circle : function (x, y, r, color, width, fill, shadow, image) {
return $.jvChart.drawCircle($(this).attr('paper'), x || 0, y || 0, r || 0, color, width, fill, shadow, image);
},
ellipse : function (x, y, rx, ry, color, width, fill, shadow, image) {
return $.jvChart.drawEllipse($(this).attr('paper'), x || 0, y || 0, rx || 0, ry || 0, color, width, fill, shadow, image);
},
rectangle : function (x, y, w, h, r, color, width, fill, shadow, image) {
return $.jvChart.drawRect($(this).attr('paper'), x || 0, y || 0, w || 0, h || 0, r || 0, color, width, fill, shadow, image);
},
connection : function(obj1, obj2, color, width){
var p = $(this).attr('edgePaper');
$.jvChart.drawConnection(p, obj1, obj2, color, width);
p.edges.push([$(obj1).attr('id'), $(obj2).attr('id')]);
}
});
})(jQuery);
调用的js如下
$(document).ready(function(){
$("#container").jvChart(600, 400);
var v1 = $("#container").ellipse(0, 120, 80, 40, 'rgb(0,0,0)', 2);
var v2 = $("#container").rectangle(100, 20, 80, 40, 10, 'rgb(0,0,0)', 2);
var v4 = $("#container").ellipse(300, 100, 50, 50, 'rgb(0,0,0)', 2);
var v3 = $("#container").rectangle(290, 180, 60, 40, 2, 'rgb(0,0,0)', 2);
$("#container").connection(v1, v2, 'rgb(0,0,0)', 2);
$("#container").connection(v2, v3, 'rgb(0,0,0)', 2);
$("#container").connection(v2, v4, 'rgb(0,0,0)', 2);
});
container是一个div:<div id="container" style="width: 600px; height: 400px; background-color:rgb(255,255,255); "></div>
时间很仓促,还有很多需要改进和优化的地方,以后有空了再写吧。这个脚本也可以用来画流程图。
- 大小: 10.1 KB
分享到:
相关推荐
excanvas.js下载 希望可以帮到有需要的朋友
excanvas.js免费下载 希望可以帮到有需要的朋友
excanvas.js js画图插件。
该js由本人混合,将jquery.qrcode.min.js与excanvas.compiled.js完美结合,提供了IE8等低版本浏览器不兼容canvas控件生成二维码的解决方案。解决了jquery.qrcode.min.js使用table模式生成二维码时打印不显示的问题。...
配合html5.js使用,可以再低版本浏览器使用canvas进行绘图,支持IE6~8浏览器。
html5版本支持合集,包含excanvas.min.js html5.js html5shiv.js respond.min.js,让IE(包括IE6)支持HTML5元素和特性
excanvas.js--图形JS 配合jqplot 使用--在jqplot 前线加载这个JS
IE浏览器报错promise未定义,该js文件可以使IE浏览器兼容promise。excanvas.js使浏览器兼容HTML5 Canvas画布
excanvas.compiled.js相关
excanvas.js jQuery 曲线绘制(图表)插件.excanvas 使得 IE 能通过 VML 支持 Canvas 标签
NULL 博文链接:https://wj45.iteye.com/blog/692189
只需一个JS让万恶的IE5、IE6、IE7、IE8全都支持H5原生Canvas绘图
使用ecotree.js,不用excanvas.js,实现组织机构树,不能拖拽,只能展示。
excanvas-modified.js
excanvas.compiled.js 兼容ie个版本浏览器插件,内涵excanvas和html5.js