我这个配色的云主机能玩游戏吗,要改那些硬件或者软件才能玩绝地求生!

用d3.js实现基于SVG的线形图 - 为程序员服务
用d3.js实现基于SVG的线形图
12272 阅读
D3全称Data-Driven-Documents,这里说的不是暗黑 III,d3是一款可视化js库,其主要用途是用HTML或者SVG生动地展现数据。
相信网站开发者大都接入过ga来分析各种数据,例如pv图。ga的图都是基于SVG的,下面笔者就用d3来一步一步实现类似ga的pv线形图,并假设读者具有一定的SVG基础(没有?没关系,帮你快速上手)。
step1:引入d3.js
到下载最新版d3,然后在html代码增加标签
&script src="/imgr?src=http%3A%2F%%2F%2Fd3-line-chart%2Fpath%2Fto%2Fd3.js&r=http%3A%2F%%2F%2Fd3-line-chart%2F"&&/script&
step2:创建SVG容器
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = document.body.clientWidth - margin.left - margin.right,
height = 500 - margin.top - margin.
var container = d3.select('body')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom);
var svg = container.append('g')
.attr('class', 'content')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
margin、width、height定义了svg节点的位置和尺寸,后面会用到。d3.select类似jquery的选择器,并且d3的语法也支持串联调用,append(‘svg’)将svg追加到body的尾部,同时为svg节点设置了宽度和高度值,attr也有get和set两种用法。
svg的g元素类似于div,在这里作为一组元素的容器,后面加入的元素都放在g里面,g可以设置统一的css,里面的子元素会继承可继承css属性。margin和position对g的定位不起作用,只能使用translate通过位移来定位。
step3:定位坐标轴
既然d3是数据驱动的,那必须要有数据啊,没有数据肿么能搞呢。好吧,首先模拟一份数据,就模拟本月的pv数据吧,即12月每天的pv数据,日期采用yy-mm-dd的格式,pv随机一个100以内的整数。
var data = Array.apply(0, Array(31)).map(function(item, i) {
// 产生31条数据
return {date: '2013-12-' + (i & 10 ? '0' + i : i), pv: parseInt(Math.random() * 100)}
然后定义坐标轴的一些参数
var x = d3.time.scale()
.domain(d3.extent(data, function(d) { return d. }))
.range([0, width]);
var y = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d. })])
.range([height, 0]);
横坐标是日期,这里使用d3.time自动帮我们在时间和字符串之间做转换。y轴使用普通的线性缩放坐标轴。其实这里的x和y也是一个function,后续会用到。
domain规定了坐标轴上值的范围,d3.extent从数组里选出最小值和最大值,d3.max选数组里面最大值。range规定了坐标轴端点的位置,svg的坐标原点是左上角,向右为正,向下为正,而y轴正方向为由下向上,所以(0, height)才是图表的坐标原点。
然后使用d3的axis定制坐标轴
var xAxis = d3.svg.axis()
.orient('bottom')
.ticks(30);
var yAxis = d3.svg.axis()
.orient('left')
.ticks(10);
orient有四个参数(left、right、top、bottom)定义了坐标轴的位置,这里很好理解。
ticks定义了坐标轴上除最小值和最大值以外最多有多少个刻度,因为一个月最多有31天,ticks(30)就足以展示每天的刻度了。
然后就可以把坐标轴加进svg容器了
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis)
// 增加坐标值说明
.append('text')
.text('日期')
.attr('transform', 'translate(' + width + ', 0)');
svg.append('g')
.attr('class', 'y axis')
.call(yAxis)
.append('text')
.text('次/天');
加上坐标轴之后的效果图应该是这样
step4:画线
有了坐标轴之后我们可以加上图表的主体部分了,pv图应该是一条折线图。怎么加折线呢,d3提供了丰富的图表元素,需要折线只需要append(‘path’)即可,了解svg的都知道,path的d属性是最重要的,决定了折线的“路径”,这里就不详细讲解path了。
我们只有一个数组的数据,怎么转化成需要的d呢,别担心,d3帮我们做了这部分工作。首先需要用d3.svg.line生成一个“线条函数”,然后将数据传给该函数即可生成我们想要的d,我们需要做的就是定制这个“线条函数”的两条坐标轴分别由数据的哪部分决定。
下面看代码
var line = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.pv); })
.interpolate('monotone');
上面的代码很好理解,设置了x坐标轴由date属性决定,y坐标轴由pv属性决定,最后还调用了interpolate,该方法会改变线条相邻两点之间的链接方式以及是否闭合,接受的参数有linear,step-before,step-after,basis,basis-open,basis-closed,bundle,cardinal,cardinal-open,cardinal-closed,monotone,读者可以一一尝试,看看线条有什么不一样。
“线条函数”生成好了,可以应用到path上了
var path = svg.append('path')
.attr('class', 'line')
.attr('d', line(data));
此时的图应该是这样了
step5:打点
到这里其实基本的图形已经实现了,只用了应该不到20行代码,不过这也太丑了点吧,而且完全木有交互啊。
别急,ga的pv图在每个数据点都会有一个小点来占位,其实本来我们的数据就是离散的,图上也应该是离散的一些点,不过为了图表好看,也为了方便查看数据的走势,折线图显然更形象一些。
下面就在折线上增加相应的点,点我们可以用circle,要增加元素用append即可
var g = svg.selectAll('circle')
.data(data)
.append('g')
.append('circle')
.attr('class', 'linecircle')
.attr('cx', line.x())
.attr('cy', line.y())
.attr('r', 3.5)
.on('mouseover', function() {
d3.select(this).transition().duration(500).attr('r', 5);
.on('mouseout', function() {
d3.select(this).transition().duration(500).attr('r', 3.5);
这里的代码可能复杂一点,因为circle不止一个,需要使用selectAll,而circle现在是还不存在的。selectAll(‘circle’)的作用可以理解成先预定若干个circle的位置,等有数据了再插入svg容器里。
enter就表明有数据来了,将每个circle放到单独的g里面,这里没有特殊的用意,就像html里面习惯用div来装其他元素一样。
为circle设置一些属性,cx、cy代表圆心x、y坐标,line.x()和line.y()会返回折线上相应点的x、y坐标,这样添加的circle就依附在折线上了。r表示圆半径,同时为circle添加了两个鼠标事件,这样鼠标在circle上移动和移出的时候增加了圆半径变化的一个动画。
step6:增加tips
现在看整体数据倒是可以了,不过看某天的具体数据还是太不方便了,如果在circle上直接标注出具体的数据又太挫了。
咋办?嘿嘿,参考ga呗。ga在鼠标经过某点的纵坐标所在的直线的时候就会在改点附近出现具体的数据tips,赞,既能清晰地看到整体的走势又能看到每天的具体数据。
先上效果图
图中用一个圆角矩形和两行文字组成了一个简单的tips
var tips = svg.append('g').attr('class', 'tips');
tips.append('rect')
.attr('class', 'tips-border')
.attr('width', 200)
.attr('height', 50)
.attr('rx', 10)
.attr('ry', 10);
var wording1 = tips.append('text')
.attr('class', 'tips-text')
.attr('x', 10)
.attr('y', 20)
.text('');
var wording2 = tips.append('text')
.attr('class', 'tips-text')
.attr('x', 10)
.attr('y', 40)
.text('');
为啥要用矩形呢,为啥不直接在g上设置圆角效果呢?实践证明对g设置的width、height、border-radius均无效,无赖只能使用svg的rect元素了。
rx、ry是圆角两个方向的半径,原理同border-radius。展示文字用text元素即可,这里的x和y还是坐标,不过是相对于父元素g的坐标。
最后的关键是怎么让tips出现在该出现的位置和展示对的数据,即鼠标经过某个点的纵坐标所在的直线是tips出现在改点附近,且展示改点的数据。
.on('mousemove', function() {
var m = d3.mouse(this),
cx = m[0] - margin.
var x0 = x.invert(cx);
var i = (d3.bisector(function(d) {
}).left)(data, x0, 1);
var d0 = data[i - 1],
d1 = data[i] || {},
d = x0 - d0.date & d1.date - x0 ? d1 : d0;
function formatWording(d) {
return '日期:' + d3.time.format('%Y-%m-%d')(d.date);
wording1.text(formatWording(d));
wording2.text('PV:' + d.pv);
var x1 = x(d.date),
y1 = y(d.pv);
// 处理超出边界的情况
var dx = x1 & width ? x1 - width + 200 : x1 + 200 & width ? 200 : 0;
var dy = y1 & height ? y1 - height + 50 : y1 + 50 & height ? 50 : 0;
d3.select('.tips')
.attr('transform', 'translate(' + x1 + ',' + y1 + ')');
d3.select('.tips').style('display', 'block');
.on('mouseout', function() {
d3.select('.tips').style('display', 'none');
这段长长的代码需要重点解释一下,首先是d3.mouse(this),这个方法会返回当前鼠标的坐标,是一个数组,分别是x和y坐标。
下面这一步最重要的一点来了,x.invert(cx)跟据传入的横坐标数值返回该横坐标的实际数据上的值,在本例中返回一个日期。
下面的i是根据返回的日期反向得到data数组中的元素位置。有了这个i一切都好办了,接下来的代码是为了判断鼠标在两个日期之间离哪个更近。
后面的代码都很简单了,拿到了tips应该出现的x、y坐标之后设置tips的transform即可,再控制tips的display属性就达到了最后的效果。
查看最后的代码请移步
That‘s all.
腾讯全端 AlloyTeam 团队 Blog
原文地址:, 感谢原作者分享。
您可能感兴趣的代码d3可视化实战03:神奇的superformula_博客园
当前位置: >
>d3可视化实战03:神奇的superformula
d3可视化实战03:神奇的superformula
& 作者:CUC张迪 & 来源: 博客园-zhangdi &
需求驱动实现
前文讲过了D3的数据驱动机制,中间所举的例子都很简单。例如那个里面,绑定的数据是一个简单的数组,实现的图元也仅仅是一堆用SVG画的circle。但是现实世界中我们往往会遇到复杂的需求,例如我就遇到了这样一个需求:数据是一个复杂的对象数组,而与之绑定的图元是一个可变图形。该图形可以根据与他绑定的数据中的具体参数,在圆形、方块、三角之间切换,并且要求过渡自然。
面对这个需求,最直接的做法是把圆形、方块、三角用SVG的&circle&圆形标签,&rect&矩形标签以及&polygon&多边形标签来分别实现。具体用D3实现,就是创建一个&g&集合标签作为数据绑定对象,根据数据参数的变化,remove里面的原有图形,add新的图形,从而实现数据驱动的图形更新。但是这种方法有一个很难解决的问题,就是图形切换时的过渡动画很难平滑。因为每个图形都是独立的标签,除了采用淡入淡出之类的过渡方法外,很难想到有什么更好的过渡效果。并且出于对代码简化的考虑,g标签内包裹其他的图形标签的方式,也增加了复杂度。
那么还有其他方案吗?如果能有一个万能图形标签来来实现各种图形,把数据直接绑定给它,那就再好不过了。事实上SVG的&path&路径标签就可以实现这一点。在我之前的文章”“中已经提到,路径功能非常强大几乎可以描绘任何图形。唯一的问题是,如何指定Path的具体参数。对于一般情况,我们可以自己设定参数。而在这里,我打算用一个数学模型来指定path的具体参数,那就是超级方程式。最终实现的效果果然非常好,动画过渡非常平滑,图元本身也很简单。下面让我们看看这个究竟是何方神圣吧。
about超级方程式
我们知道,很多数学函数都可以用解析式的方式表示,亦可根据变此文来自: 马开东博客
转载请注明出处 网址:
量和自变量的值在不同坐标系下绘成各种图形。Johan Gielis博士提出了一个函数,可以描述自然界中发现的众多复杂图形和曲线,它就是超级方程式。
超级方式的解析式如下:
在极坐标系下,r代表半径,代表角度,a,b,m,n1,n2,n3是可变参数。通过调整参数的值,就可以绘出各种图形。下图展示了a=b=1的情况下,m,n1,n2,n3取不同值的时候所展示的图形:
只通过控制这些参数,就能在极坐标系下绘制如此不同的各种2D图形,是不是很神奇?这就是数学这一自然科学的王冠学科的魅力。
关于superfomula的更多介绍:
的发表者博士(1962-)原本的研究方向是园艺工程和生物学。在他的早期研究阶段他就感兴趣于使用数学模型表征生物生长性状。1994年发表的论文中他就开始开始使用曲线描述自然形状,在1997年的论文中他发现广义的曲线模型适用于任何对称形状。在2003年发表于美国植物学杂志上的论文中,他提出了。是超级椭圆公式的扩展,但具有更广泛的实用性。此后数百篇论文都引用了superfomula,并且以superfomula为指导的计算机绘图程序也随之出现。2004年johan Gielis博士收到了InterTech技术创新卓越奖,该奖主要颁发给对平面艺术及相关产业产生重大影响的技术发明。superfomula从生物技术研究中诞生,在数学领域中升华,并最终应用到计算机、平面设计等领域。可谓是跨学科研究应用的最好案例之一。
superfomula也可以扩展到3维,4维甚至更多维度。例如3维情况下,图形可以通过两个superfomula r1, r2来生成。其极坐标系与笛卡尔坐标系之间转换关系为:
其中,&变量值域为[&-π/2&,&π/2]&(维度),&θ变量值域为&[&-π,&π]&(精度).
案例及代码实现
在github上,已经有人用D3实现了基于superfomula的图形绘制程序。大家请点击这里:. 该程序的关键是基于D3的superfomula开源插件。本着学习的目的,这里保存了该插件的源码,你可以复制它然后保存为d3-superfomula.js来使用:
(function() {
var _symbol = d3.svg.symbol(),
_line = d3.svg.line();
d3.superformula = function() {
var type = _symbol.type(),
size = _symbol.size(),
segments = size,
params = {};
function superformula(d, i) {
var n, p = _superformulaTypes[type.call(this, d, i)];
for (n in params) p[n] = params[n].call(this, d, i);
return _superformulaPath(p, segments.call(this, d, i), Math.sqrt(size.call(this, d, i)));
superformula.type = function(x) {
if (!arguments.length) return type;
type = d3.functor(x);
return superformula;
superformula.param = function(name, value) {
if (arguments.length & 2) return params[name];
params[name] = d3.functor(value);
return superformula;
// size of superformula in square pixels
superformula.size = function(x) {
if (!arguments.length) return size;
size = d3.functor(x);
return superformula;
// number of discrete line segments
superformula.segments = function(x) {
if (!arguments.length) return segments;
segments = d3.functor(x);
return superformula;
return superformula;
function _superformulaPath(params, n, diameter) {
var i = -1,
dt = 2 * Math.PI / n,
points = [];
while (++i & n) {
t = params.m * (i * dt - Math.PI) / 4;
t = Math.pow(Math.abs(Math.pow(Math.abs(Math.cos(t) / params.a), params.n2)
+ Math.pow(Math.abs(Math.sin(t) / params.b), params.n3)), -1 / params.n1);
if (t & r) r = t;
points.push(t);
r = diameter * Math.SQRT1_2 / r;
i = -1; while (++i & n) {
x = (t = points[i] * r) * Math.cos(i * dt);
y = t * Math.sin(i * dt);
points[i] = [Math.abs(x) & 1e-6 ? 0 : x, Math.abs(y) & 1e-6 ? 0 : y];
return _line(points) + &Z&;
var _superformulaTypes = {
asterisk: {m: 12, n1: .3, n2: 0, n3: 10, a: 1, b: 1},
bean: {m: 2, n1: 1, n2: 4, n3: 8, a: 1, b: 1},
butterfly: {m: 3, n1: 1, n2: 6, n3: 2, a: .6, b: 1},
circle: {m: 4, n1: 2, n2: 2, n3: 2, a: 1, b: 1},
clover: {m: 6, n1: .3, n2: 0, n3: 10, a: 1, b: 1},
cloverFour: {m: 8, n1: 10, n2: -1, n3: -8, a: 1, b: 1},
cross: {m: 8, n1: 1.3, n2: .01, n3: 8, a: 1, b: 1},
diamond: {m: 4, n1: 1, n2: 1, n3: 1, a: 1, b: 1},
drop: {m: 1, n1: .5, n2: .5, n3: .5, a: 1, b: 1},
ellipse: {m: 4, n1: 2, n2: 2, n3: 2, a: 9, b: 6},
gear: {m: 19, n1: 100, n2: 50, n3: 50, a: 1, b: 1},
heart: {m: 1, n1: .8, n2: 1, n3: -8, a: 1, b: .18},
heptagon: {m: 7, n1: 1000, n2: 400, n3: 400, a: 1, b: 1},
hexagon: {m: 6, n1: 1000, n2: 400, n3: 400, a: 1, b: 1},
malteseCross: {m: 8, n1: .9, n2: .1, n3: 100, a: 1, b: 1},
pentagon: {m: 5, n1: 1000, n2: 600, n3: 600, a: 1, b: 1},
rectangle: {m: 4, n1: 100, n2: 100, n3: 100, a: 2, b: 1},
roundedStar: {m: 5, n1: 2, n2: 7, n3: 7, a: 1, b: 1},
square: {m: 4, n1: 100, n2: 100, n3: 100, a: 1, b: 1},
star: {m: 5, n1: 30, n2: 100, n3: 100, a: 1, b: 1},
triangle: {m: 3, n1: 100, n2: 200, n3: 200, a: 1, b: 1}
d3.superformulaTypes = d3.keys(_superformulaTypes);
相关阅读:
来源:(微信/QQ:,微信公众号:makaidong-com) &&&&&& 欢迎分享本文,转载请保留出处!
&&&&&& 【原文阅读】:
上一篇:没有了
【相关文章】
每日最新文章
每日最热文章
本周最热文章
本月最热文章
本年最热文章
Powered by
Copyright &
, All Rights Reserveddefine('keepsoft/gis/extlayers/D3AnnoLayer',
'dojo/_base/declare',
'dojo/_base/lang',
'dojo/on',
'esri/Evented',
'esri/geometry/screenUtils'
function(declare,&lang,&d3js,&on,&Evented,&screenUtils){
var&d&=&declare([Evented],&{
declaredClass:'keepsoft.gis.extlayers.D3AnnoLayer',
_eventMap:{
labelFields:[
'stcd','stnm'
labelPrifixes:[
'编码:','名称:'
labelSuffixes:[
rectRadius:5,
rectWidth:120,
rectOffsetX:0,
rectOffsetY:16,
rectFillColor:'rgba(20,20,20,0.4)',
rectStrokeColor:'rgba(255,255,255,1)',
rectStrokeWidth:2,
labelHeigth:23,
labelVerticalAlign:4,
labelsPaddingTop:2,
labelsPaddingBottom:2,
labelsPaddingLeft:2,
labelsPaddingRight:2,
fontSize:24,
fontColor:'rgba(220,20,20,1)',
labelDx:20
constructor:function(map,&graphicsLayer,&opt){
//1.全局参数
this.map&=&
this.graphicsLayer&=&graphicsL
//2.合并参数
lang.mixin(this.option,&opt);
//3.创建svg&group
this.domId&=&this.graphicsLayer.id+'-d3anno';
d3js.select('#'+this.map.id+'_gc')
.append('g')
'id':this.domId
init:function(){
var&map&=&this.
on(map,&'pan',&lang.hitch(this,&this._pan));
on(map,&'zoom-start',&lang.hitch(this,&this._zoomStart));
on(map,&'zoom-end',&lang.hitch(this,&this._zoomEnd));
this._initialize();
_initialize:function(){
this._removeAllChildren();
this._draw();
_removeAllChildren:function(){
dojo.empty(this.domId);
_draw:function(){
if&(!this.option.labelFields){
for&(var&i&=0;&i&&&this.graphicsLayer.graphics.&i++){
var&g&=&this.graphicsLayer.graphics[i];
this._drawBgShape(g);
this._drawText(g);
_drawBgShape:function(graphic){
var&geometry&=&graphic.
var&o&=&this.
var&labelNum&=&o.labelFields.
var&shapeHeight&=&o.labelsPaddingTop&+&(o.fontSize+o.labelVerticalAlign)*labelNum&+&o.labelsPaddingB
var&shapeWidth&=&o.rectW
var&x&=&0,&y=0;
var&map&=&this.
var&mapExtent&=&map.
var&mapWidth&=&map.
var&mapHeight&=&map.
var&xy&=&screenUtils.toScreenPoint(mapExtent,&mapWidth,&mapHeight,&geometry);
var&_mvr&=&map.__visibleR
x&=&xy.x&-&_mvr.x&-&shapeWidth/2&+&o.rectOffsetX;
y&=&xy.y&-&_mvr.y&+&o.rectOffsetY;
console.log(xy);
console.log(_mvr);
console.log(shapeHeight);
d3js.select('#'+this.domId)
.append('rect')
'width':shapeWidth,
'height':shapeHeight,
'fill':o.rectFillColor,
'stroke':o.rectStrokeColor,
'stroke-width':o.rectStrokeWidth,
'rx':o.rectRadius,
'ry':o.rectRadius
_drawText:function(graphic){
var&geometry&=&graphic.
var&o&=&this.
var&labelNum&=&o.labelFields.
var&shapeHeight&=&o.labelsPaddingTop&+&(o.fontSize+o.labelVerticalAlign)*labelNum&-&o.labelAlign&+&o.labelsPaddingB
var&shapeWidth&=&o.rectW
var&x&=&0,&y=0;
var&map&=&this.
var&mapExtent&=&map.
var&mapWidth&=&map.
var&mapHeight&=&map.
var&xy&=&screenUtils.toScreenPoint(mapExtent,&mapWidth,&mapHeight,&geometry);
var&_mvr&=&map.__visibleR
x&=&xy.x&-&_mvr.x&-shapeWidth/2&+&o.rectOffsetX;
y&=&xy.y&-&_mvr.y&+&o.rectOffsetY;
var&node&=&d3js.select('#'+this.domId);
var&labelNum&=&o.labelFields.
for&(var&i=0;&i&&&labelN&i++){
var&labelX&=&x&+&o.labelsPaddingLeft&||&0;
var&labelY&=&y&+&o.labelsPaddingTop+o.fontSize+(o.fontSize+o.labelVerticalAlign)*i&||&0;
var&fstring&=&graphic.attributes[o.labelFields[i]]&||&'';
var&prefix&=&o.labelPrifixes[i]&||&'';
var&suffix&=&o.labelSuffixes[i]&||&'';
var&text&=&prefix&+&fstring&+&
node.append('text')
'x':labelX,
'y':labelY,
'fill':o.fontColor,
'font-size':o.fontSize,
'dx':o.labelDx
.text(text);
_pan:function(e){
//console.log(e);
var&dx&=&e.delta.x;
var&dy&=&e.delta.y;
var&_dx&=&this.map.__visibleRect.x+
var&_dy&=&this.map.__visibleRect.y+
d3.select('#'+this.domId)
'transform':'matrix(1,0,0,1,'+_dx+','+_dy+')'
_zoomStart:function(){
this._removeAllChildren();
_zoomEnd:function(){
d3.select('#'+this.domId)
'transform':'matrix(1,0,0,1,0,0)'
this._draw();
&&&&&div&id=&mapDiv&&
&&&&&/div&
&script&src=&http://localhost:3000/content/public/webgit/jslib/esri/api/init.js&&&/script&
&script&type=&text/javascript&&
&&&&'esri/map',
&&&&'esri/layers/GraphicsLayer',
&&&&'esri/geometry/Point',
&&&&'esri/symbols/TextSymbol',
&&&&'esri/graphic',
&&&&'esri/symbols/SimpleFillSymbol',
&&&&'esri/Color',
&&&&'esri/symbols/SimpleMarkerSymbol',
&&&&'dojo/on',
&&&&'esri/SpatialReference',
&&&&'keepsoft/gis/extlayers/D3AnnoLayer',
&&&&'dojo/domReady!'
],&function(Map,&GraphicsLayer,&Point,&TextSymbol,&Graphic,&SimpleFillSymbol,&Color,&SimpleMarkerSymbol,&on,&SpatialReference,&AnnoLayer){
&&&&var&map&=&new&Map('mapDiv',
&&&&&&&&{&basemap:&&topo&,&center:&[120,30],&zoom:&4,&sliderStyle:&&small&&});
&&&&var&lyr&=&new&GraphicsLayer({
&&&&&&&&id:'textGraphicsLayer'
&&&&map.addLayer(lyr);
&&&&on(map,&'load',&function(){
&&&&&&&&var&point&=&new&Point(120,&30,&new&SpatialReference(4326));
&&&&&&&&var&symbol&=&new&SimpleMarkerSymbol('circle');
&&&&&&&&var&g&=&new&Graphic(point,&symbol,&{
&&&&&&&&&&&&stcd:'aaa',
&&&&&&&&&&&&stnm:'bbb'
&&&&&&&&});
&&&&&&&&lyr.add(g);
&&&&&&&&var&d3AnnoLayer&=&new&AnnoLayer(map,&lyr,&{
&&&&&&&&&&&&rectWidth:160,
&&&&&&&&&&&&labelDx:10
&&&&&&&&});
&&&&&&&&d3AnnoLayer.init();
使用d3创建svg,侦听map事件,实现对graphic的attributes进行标注。
希望能有用。
csdn一直审核 呵呵了。先贴出效果图:这里我们解释下js:test() :作为数据源函数并调用d3画图
drawApply() :画图函数,负责画图
具体解释看代码,如下:&html&
&title&&/title&
&meta http-equiv="Content-Type" content="text/ charset=utf-8"&
&div id="metrics"&&/div&
&script src="http://d3js.org/d3.v3.min.js" charset="utf-8"&&/script&
&script type="text/javascript"&
function test(){
var appStatus = {
lineageSatus:1,
impactStatus:1,
sameServerAppStatus:1,
sameRackAppStatus:0.1,
appDbStatus:1,
appRedisStatus:1,
appMqStatus:1,
appHaproxyStatus:1
var dymicInfo = {
switchPercent : 1,
machineRoomPercent : 1
var basicInfo ={
appName : 'test',
departmentName : 'test',
businessName : 'test',
connectPerson : 'test',
appLevel : 'test',
serviceNum : 'test',
machineRoomNum : 'test',
machineNum : 'test'
drawApply(basicInfo, dymicInfo,appStatus);
function drawApply(basicInfo, dymicInfo,appStatus){
var maxdepth=3;
var width = 420,height = 420;
var margin = {top: 10, right: 50, bottom: 10, left: 50}
var cluster = d3.layout.cluster()
.size([height, width/2]);
var maxScaleX = 0;
appStatus =eval(appStatus);
var newnode
svg.append("rect")
.attr("width", "500px")
.attr("height", "500px")
.attr("fill", "#ffffff")
.attr("stroke", "#0000ff")
.attr("stroke-width", "2px")
.attr("stroke-opacity", "0.1");*/
var nodePositionDictionary = {};
var root = {children:[], name:"a","pos":"mid"};
var rootLeft = {children:[], name:"a","pos":"mid"};
var rootRight = {children:[], name:"a","pos":"mid"};
dymicInfo = eval(dymicInfo);
newnode = {"name":"血缘","value":appStatus.lineageSatus};
rootRight.children.push(newnode);
root.children.push(newnode);
newnode = {"name":"影响","value":appStatus.impactStatus};
rootRight.children.push(newnode);
root.children.push(newnode);
newnode = {"name":"同服务器","value":appStatus.sameServerAppStatus};
rootRight.children.push(newnode);
root.children.push(newnode);
newnode = {"name":"同机柜","value":appStatus.sameRackAppStatus};
rootRight.children.push(newnode);
root.children.push(newnode);
newnode = {"name":"数据库","value":appStatus.appDbStatus};
rootRight.children.push(newnode);
root.children.push(newnode);
newnode = {"name":"Redis","value":appStatus.appRedisStatus};
rootRight.children.push(newnode);
root.children.push(newnode);
newnode = {"name":"MQ","value":appStatus.appMqStatus};
rootRight.children.push(newnode);
root.children.push(newnode);
newnode = {"name":"Haproxy","value":appStatus.appHaproxyStatus};
rootRight.children.push(newnode);
root.children.push(newnode);
var nodesRight = cluster.nodes(rootRight);
maxScaleX = d3.max(nodesRight,function(d){return d.x;});
for (var j = 0; j & nodesRight. j++) {
var node = nodesRight[j];
node.right =
nodePositionDictionary[node.name + (node.parent?node.parent.name:"") + node.pos] =
newnode = {"name":"RT","value":dymicInfo.rt};
rootLeft.children.push(newnode);
root.children.push(newnode);
newnode = {"name":"TPS","value":dymicInfo.tps};
rootLeft.children.push(newnode);
root.children.push(newnode);
var cpu =Math.floor(dymicInfo.cpu*100)
newnode = {"name":"CPU","value":cpu+"%"};
rootLeft.children.push(newnode);
root.children.push(newnode);
var mem =Math.floor(dymicInfo.mem*100)
newnode = {"name":"MEM","value":mem+"%"};
rootLeft.children.push(newnode);
root.children.push(newnode);
newnode = {"name":"LOAD","value":"10"};
rootLeft.children.push(newnode);
root.children.push(newnode);
newnode = {"name":"硬盘","value":dymicInfo.disk+"%"};
rootLeft.children.push(newnode);
root.children.push(newnode);
var switchPercent =Math.floor(dymicInfo.switchPercent*100)
newnode = {"name":"机柜","value":switchPercent+"%"};
rootLeft.children.push(newnode);
root.children.push(newnode);
var machineRoomPercent =Math.floor(dymicInfo.machineRoomPercent*100)
newnode = {"name":"机房","value":machineRoomPercent+"%"};
rootLeft.children.push(newnode);
root.children.push(newnode);
var nodesLeft = cluster.nodes(rootLeft);
var maxLeft = d3.max(nodesLeft,function(d){return d.x;});
console.log(maxLeft);
if(maxLeft&maxScaleX)
maxScaleX = maxL
for (var j = 0; j & nodesLeft. j++) {
var node = nodesLeft[j];
node.right =
nodePositionDictionary[node.name + (node.parent?node.parent.name:"")
+ node.pos] =
var svg = d3.select("#metrics").append("svg")
.attr("width", width+margin.left+margin.right)
.attr("height", height+margin.top+margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + ",0)");
addSymbol(svg);
basicInfo = eval(basicInfo);
var basicInfoJson = [];
newnode = {"name":"英文名","value":basicInfo.appName};
basicInfoJson.push(newnode);
newnode = {"name":"部门","value":basicInfo.departmentName};
basicInfoJson.push(newnode);
newnode = {"name":"业务域","value":basicInfo.businessName};
basicInfoJson.push(newnode);
newnode = {"name":"负责人","value":basicInfo.connectPerson};
basicInfoJson.push(newnode);
newnode = {"name":"等 级","value":basicInfo.appLevel+"级"};
basicInfoJson.push(newnode);
newnode = {"name":"服务数","value":basicInfo.serviceNum};
basicInfoJson.push(newnode);
newnode = {"name":"机房数","value":basicInfo.machineRoomNum};
basicInfoJson.push(newnode);
newnode = {"name":"机器数","value":basicInfo.machineNum};
basicInfoJson.push(newnode);
// manually create nodes with their positions instead of doing cluster.nodes because
// i want them to be drawn left and right
var nodes = [];
updateNodePositions(root);
var diagonalRight = d3.svg.diagonal().projection(function(d) { return [d.y, d.x]; });
var diagonalLeft = d3.svg.diagonal().projection(function(d) { return [-d.y, d.x]; });
var links = cluster.links(nodes);
var link = svg.append("g")
.attr("transform", "translate(" + width/2+ "," + 0+ ")")
.selectAll(".link")
.data(links)
.enter().append("path")
.attr("stroke",function(d){return d.target.})
.attr("stroke-width", 2)
.attr("fill", "none")
.attr("d", function(d){
return d.target.right || d.source.right?diagonalRight(d):diagonalLeft(d);
var nodeEnter =svg.append("g")
.attr("transform", "translate(" + width/2+ "," + 0+ ")")
.selectAll(".node")
.data(nodes)
console.log(nodeEnter);
var node = nodeEnter.append("circle")
.attr("class", "node")
.attr("r", 25)
.attr("cx",function(d) {
if((d.right==null)||(d.right)){
return d.y;
return -d.y;
.attr("cy",function(d) { return d.x;})
.style("display", function(d) {
if (d.pos == 'mid') {
return 'none';
.style("fill", function(d) {
if(d.right==true){
if(d.value=="1"){
//return "#FF0000"; //右边颜色
return "red";
// 报警颜色
return "green"; // 正常颜色
if(d.name=="TPS" ||
d.name=="RT"){
return "#E6E6E6";
}else if(d.name=="CPU" ||
d.name=="MEM"){
return "#E6E6E6";
}else if(d.name=="入带宽" ||
d.name=="出带宽"){
return "#E6E6E6";
return "#E6E6E6";
.on("click", function(d){
showDetailInfo(d);
var textn1 = nodeEnter.append("text")
.attr("x",function(d) { if((d.right==null)||(d.right)){
return d.y;
return -d.y;
.attr("y",function(d) {
if(d.right==false){
return d.x-4;
return d.x+10
.text(function(d) {
return d.})
.style("display", function(d) {
if (d.pos == 'mid') {
return 'none';
.style('cursor', 'pointer')
.attr("text-anchor", function(d) {
return "middle";
.on("click", function(d){
showDetailInfo(d);
var textn2 = nodeEnter.append("text")
.attr("x",function(d) { if((d.right==null)||(d.right)){
return d.y;
return -d.y;
.attr("y",function(d) {
if(d.right==false){
return d.x+14;
return d.x+10
.text(function(d) {
console.log(d);
if(d.right==true){
return "";
.style("display", function(d) {
if (d.pos == 'mid') {
return 'none';
.attr("text-anchor", function(d) {
return "middle";
var centerN
for(var i=0;i&nodes.i++){
var nodet=nodes[i];
if(nodet.pos=='mid'){
centerNode =
svg.append("use")
.attr("xlink:href", "#tableSymbol")
.attr("x",centerNode.y+width/2-110)
.attr("y",centerNode.x-112.5);
svg.append("text")
.attr("x",centerNode.y+width/2)
.attr("y",centerNode.x-112.5+17)
.attr("text-anchor","middle")
.text(basicInfo.appChnName);
for(var i=0;i&basicInfoJson.i++){
svg.append("use")
.attr("xlink:href", "#columnSymbol")
.attr("x",centerNode.y+width/2-110)
.attr("y",centerNode.x-(112.5-(i+1)*25));
svg.append("text")
.attr("x",centerNode.y+width/2-110)
.attr("y",centerNode.x-(112.5-(i+1)*25)+17)
.attr("text-anchor","left")
.text("  "+basicInfoJson[i].name+" : "+basicInfoJson[i].value);
svg.append("use")
.attr("xlink:href", "#columnSymbol")
.attr("x",centerNode.y+width/2-110)
.attr("y",centerNode.x-(112.5-(i+1)*25));
svg.append("text")
.attr("x",centerNode.y+width/2-110)
.attr("y",centerNode.x-(112.5-(i+1)*25)+17)
.attr("text-anchor","left")
.text("  "+basicInfoJson[i].value);
// 删除不显示的图例
var us = svg.selectAll("use");
us[0].forEach(function(o) {
if (o.style['display'] == 'none') {
o.remove();
function updateNodePositions(n){
var nodePosition = nodePositionDictionary[n.name + (n.parent?n.parent.name:"") + n.pos];
if(nodePosition){
n.x = nodePosition.x;
n.y = nodePosition.y;
n.depth = nodePosition.
nodes.push(n);
for(var i=0; i& n.children.i++)
var node = n.children[i];
node.parent =
nodes.push(node);
var childNodePosition = nodePositionDictionary[node.name + (node.parent?node.parent.name:"") + node.pos];
if(childNodePosition){
node.x = childNodePosition.x;
node.y = childNodePosition.y;
node.depth = childNodePosition.
node.right = childNodePosition.
if(node.name=="TPS" ||
node.name=="RT"){
node.fillcolor="#E6E6E6";
}else if(node.name=="CPU" ||
node.name=="MEM"){
node.fillcolor="#E6E6E6";
}else if(node.name=="入带宽" ||
node.name=="出带宽"){
node.fillcolor="#E6E6E6";
node.fillcolor="#E6E6E6";
if(node.children){
updateNodePositions(node);
function showDetailInfo(d) {
console.log(d);
if (d.name == '影响') {
window.open(getContextPath() +'/smAllImpact/app/'+ appId);
} else if (d.name == '血缘') {
window.open(getContextPath() +'/smAllLineage/app/'+ appId);
} else if (d.name == '同服务器') {
window.open(getContextPath() +'/server/index?sapp='+ appId);
} else if (d.name == '同机柜') {
window.open(getContextPath() +'/rack/index?sapp='+ appId);
} else if (d.name == '数据库') {
window.open(getContextPath() +'/db/index?sapp='+ appId);
} else if (d.name == 'Redis') {
window.open(getContextPath() +'/redis/index?sapp='+ appId);
} else if (d.name == 'MQ') {
window.open(getContextPath() +'/mq/index?sapp='+ appId);
} else if (d.name == 'Haproxy') {
window.open(getContextPath() +'/haproxy/index');
function addSymbol(svg) {
var tableSymbol = svg.append("symbol").attr('id', 'tableSymbol');
tableSymbol.append("rect")
.attr('x', 0)
.attr('y', 0)
.attr('width', '220')
.attr('height', '25')
.attr("fill", "#eeeeee")
.attr("fill-opacity", 1)
.attr("stroke-width", 0.2)
.attr("stroke", "#000000");
svg.append("defs").append("filter")
.attr("id", "clippy")
.attr("x", "0")
.attr("y", "1")
.attr("height", "18")
.attr("width","202")
.append("feColorMatrix")
.attr("type", "identity");
var columnSymbol = svg.append("symbol").attr('id', 'columnSymbol');
columnSymbol.append("rect")
.attr('x', 0)
.attr('y', 0)
.attr('width', '220')
.attr('height', '25')
.attr("fill", "#ffffff")
.attr("fill-opacity", 1)
.attr("stroke-width", 0.2)
.attr("stroke", "#000000");
这里可以参考对应d3js的Concept network browser}

我要回帖

更多关于 云主机能玩游戏吗 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信