svg + d3
为了实现元素的添加,删除,拖拽,左键点击,右键单击,悬浮等功能,使用了d3 + svg 的技术来实现界面。
最开始是采用canvas,但是由于功能原因放弃了该技术,可以看下 canvas简介
另附:canvas和svg区别
首先,下载d3.min.js和snap.svg-min.js
如果使用的是bower,
安装d3,bower --allow-root install -S d3
安装svg,bower --allow-root install -S snap.svg
然后页面再引入。
新建画布主要有两种方式,
(1)html页面中
<svg id="svg_order" xmlns="http://www.w3.org/2000/svg" version="1.1" width="622px" height="417px"> </svg>
js中
var svg = Snap("#svg_order"); var rect = svg.paper.rect(hengwidth*widthOffest,shuwidth*heightOffest,imageWidth,imageHeight,imageRadius); var text = svg.paper.text((hengwidth*widthOffest)+imageWidth/2-5, (shuwidth*heightOffest)+imageHeight/2, i+1); var group = svg.paper.g(rect, text).attr({id:"groupId"+i,class:"groupClass"});
(2)html页面中
<div id="main_client_order"> </div>
js中
var svg = null; /*构建基础画布*/ function drawPanel(screenWidth, screenHeight) { svg = d3.select('#main_client_order') .append('svg:svg') .attr('width', screenWidth+100) .attr('height', screenHeight+100) .style("margin-left", "20px") .style("margin-top", "20px") .attr("id", "orderId"); } var addRect = svg.append("g"); addRect.append("rect"); addRect.append("text");
在画布上面开始画图
var addRect = svg.append("g"); addRect.append("rect"); addRect.append("text"); addRect.append("rect").style('visibility', 'hidden');(标记1) addRect = addRect.call(drag);//给元素添加拖拽事件,拖拽事件需要定义在此代码之前。
给元素添加事件
悬浮事件和右键事件
addRect.on("contextmenu", function (data, index) { //右键事件 d3.event.preventDefault(); }).on("mouseover", function (data, index) { //悬浮事件 over }).on('mouseleave', function () { //悬浮事件 leave });
拖拽事件(此方法要放在元素添加拖拽事件之前)
var drag = d3.behavior.drag() .on('dragstart', function (d) { //拖拽开始事件,需要通过标志位区分点击按下时和拖拽开始。 }).on('drag', function (d) { //拖拽中事件,此时可以限制拖拽的边缘范围。 }).on('dragend', function (d) { //拖拽结束事件,需要通过标志位区分点击松起时和拖拽结束。 });
事件实现概述
在界面中画图时,需要边画边在页面存入数据,我存入的数据是一个二维数组,a[i][j] i表示的是行 j表示的是列
var rect = "{id:'inner_" + id + "',x:" + startX + ",y:" + startY + ",type:" + colortype + ",highlight:"+highlighttype+"}"; var jsonRect = eval('(' + rect + ')'); var a1 = startX / widthOffset; var a2 = startY / heightOffset; if (gData[a2] == null) { gData[a2] = new Array(); }
//存储元素的id,x,y gData[a2][a1] = jsonRect; //存储id备份值 只存储id (标记2) var rect_id_bak = "{id:'inner_" + id + "'}"; var jsonRect_id_bak = eval('(' + rect_id_bak + ')'); if (gDataId_bak[a2] == null) { gDataId_bak[a2] = new Array(); } gDataId_bak[a2][a1] = jsonRect_id_bak;
只所以存储一个备份id,是为了保存行列元素与id值的对应。也就是第几行第几列的元素的id值。
针对以上的两次标记,解释如下:
1.g元素是空元素,无法捕捉悬浮,点击,拖拽等事件。需要在等位置填充一个元素。目前是采用相同位置,相同长宽的方块来填充该位置。(对应标记1)
The g element is just an empty container which cannot capture click events,then appending an invisible rectangle to it as a place to hover over 来源:d3-js-mouseover-event-not-working-properly-on-svg-group
2.g元素没有x,y值,移动g元素只能用transform(x,y)的方式。(对应标记2)
The <g>-element doesn't have x and y attributes. To move the contents of a <g>-element you can only do so using the transform attribute, using the "translate" function, like this: transform="translate(x,y)".来源:SVG g element
鼠标点击的mouse()方法只能获取在画布中的位置,根据该位置的行列,x除以长得到i,y除以宽得到j,然后再从备份数据gDataId_bak中,找到对应的id,然后再根据id在html中获取该元素的偏移量,也就是transform(x,y)中的x,y,相加之后得到实际位置的x,y,x除以长得到i,y除以宽得到j,然后再从gData中获取真正的元素。
需要注意几点:
1.拖拽中,d3.event.x d3.event.y可以获取真实位置信息。
2.d3.event.sourceEvent.button 可以区分左右键点击事件,0 是左键 2是右键
3.另附d3文档