问题的出现
我在使用d3js开发项目过程中,遇到了这样的需求,将鼠标hover到某些元素上时,将该元素的detail信息逐条展示出来,而且为了将detail框与其他元素区别开来,需要给detail展示区域添加边框或增加底色,想要的效果大概是下面的图那样的。
预期效果图
问题解决思路
普通的HTML元素有很多方法来获得其宽高等其他位置属性的方法。如果是一组元素,可以用div标签将他们组合起来,指定div的border颜色和宽度,div的边框会根据元素的宽高动态改变大小。
SVG中,将元素成组的标签是g元素,之前使用它是将元素进行分组,然后统一进行平移和旋转之类的功能变换。毫无意外的,普通DOM元素获取宽高和位置属性的方法offsetWidth、ClientWidth全部失效,返回值均为undefined。我的初步想法是获得这些元素,然后绘制矩形,这样就有了类似div的边框效果。
在Stack Overflow中,找到了问题的答案,有两个原生的JS方法可以作为候选。
getBBox
document.getElementById(“g1”).getBBox()的返回结果如下:
getBBox返回值
getBoundingClientRect()
而document.getElementById(“g1”).getBoundingClientRect()的返回结果如下:
getBoundingClientRect返回值
区别
发现两个方法的返回结果是不一样的,主要是因为getBBox()获得的是元素在当前SVG坐标中的数据,而getBoundingClientRect()则是浏览器的坐标。
显然,getBBox()方法更贴合我们的需求。
添加背景色
getBBox方法可以让我们知道矩形该如何绘制,如果让矩形fill none的话,是可以看到底层的文字的,但设计师比较执拗,死磕我需要背景色。而正确获取矩形位置大小是需要先将detail信息绘制到svg画板上的,因此后面再绘制矩形的时候,矩形就盖住了底层的detail信息文字。
对于这个先有鸡还是先有蛋的问题,我采取了一个比较tricky的方法,即在绘制完矩形之后,再绘制一遍deatil信息,这样后绘制的detail信息就处在了矩形的上层,从而可以被用户看到,而底层的detail信息实际上是存在的,只不过是被矩形这遮挡住了。
给设计师看过效果之后,他露出了满意的微笑☺。
代码
12345678910111213141516171819202122232425262728
function drawDeatilBorder(data){ vis.selectAll('.detailBorder').remove(); var position = document.getElementById("detailInfoBorder").getBBox(); vis.append('rect').attr('class','detailBorder').style('fill','#f0f0f0').attr('x',position.x-20).attr('y',position.y-20).attr('width',position.width+40) .attr('height',position.height+40).attr('fill','red').attr('rx','3px').attr('ry','3px').attr('stroke','none'); var i = 0; for(var key in data) { if (typeof(data[key]) !== "object") { i++; vis.append("text").attr('class', 'detailInfo').attr("x", function () { return 850 }).attr("y", function () { return i * 20 + 30; }).attr("dy", ".35em").attr("text-anchor", function () { return "start"; }).text(function (d) { return key + " : " + data[key]; }) .style("fill-opacity", 1); } } }
项目开源地址,供参考。
原文作者: Chih-Hao
原文链接: http://zhihaozhang.github.io/2017/10/11/gInSVG/
发表日期: October 11th 2017, 9:11:38 pm
版权声明: 本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可
-
Next PostSwift4字典和集合的新特性
-
Previous PostmouseSync后续功能完善心得