作用力和小球

作用力和小球

最终效果
测试地址
上面的这种神奇的效果是使用D3.js实现的,d3的是代码库和教程请参见这里。d3是一个极其强大的数据图表库,尤其擅长操作svg,虽然被设计用来展示数据,但是其丰富的svg操作方法还有物理引擎可以被我们用来制作页面的展示。例子中的展示页面就是目前我们公司主要的产品,采用此种展示方式其效果自然是不言而喻。

分析下效果,主要是一些节点与连线,再加上节点间相互的引力与斥力还有重力效果。节点与连接线好说,使用d3绘制出svg即可;相互作用力可以使用d3提供的force中相应的方法实现。关于d3详细教程请参见其官网,这里只介绍使用到的部分。
首先将节点数据储存到数据文件中data.json

{
  "nodes":[
    {"name":"买房邦","group":1,"class":"node","tourl":"http://www.iloushi.cn/m/maifangbang/","img":"...","imgx":"-54","imgy":"-54","w":"88","h":"88"},
    {"name":"楼盘码","group":2,"class":"node","tourl":"http://www.iloushi.cn/m/loupanma/","img":"...","imgx":"-28","imgy":"-28","w":"56","h":"56"},
    {"name":"i楼市","group":3,"class":"node","tourl":"http://www.iloushi.cn/m/iloushi/","img":"...","imgx":"-34","imgy":"-34","w":"68","h":"68"},
    {"name":"乐生活","group":4,"class":"node","tourl":"http://www.iloushi.cn/m/leshenghuo/","img":"...","imgx":"-48","imgy":"-48","w":"83","h":"83"},
    {"name":"卖房邦","group":5,"class":"node","tourl":"http://www.iloushi.cn/m/maifangbangv/","img":"...","imgx":"-35","imgy":"-37","w":"97","h":"97"},
    {"name":"多媒体楼书","group":6,"class":"node","tourl":"http://www.iloushi.cn/m/ebook/","img":"...","imgx":"-34","imgy":"-34","w":"63","h":"63"},
    {"name":"房产智能TV","group":7,"class":"node","tourl":"http://www.iloushi.cn/m/tv/","img":"...","imgx":"-36","imgy":"-36","w":"72","h":"72"},
    {"name":"微客智慧WIFI","group":7,"class":"node","tourl":"http://www.iloushi.cn/m/wifi/","img":"...","imgx":"-35","imgy":"-35","w":"71","h":"70"},
    {"group":1,"class":"fs drops","img":"...","imgx":"-7","imgy":"-7","w":"14","h":"14"},
    {"group":1,"class":"fs drops","img":"...","imgx":"-4","imgy":"-4","w":"9","h":"9"},
    {"group":1,"class":"fs drops","img":"...","imgx":"-5","imgy":"-5","w":"10","h":"10"},
    {"group":1,"class":"fs drops","img":"...","imgx":"-7","imgy":"-7","w":"14","h":"14"},
    {"group":1,"class":"fs drops","img":"...","imgy":"-3","w":"6","h":"6"}
  ],
  "links":[
    {"source":0,"target":2},
    {"source":1,"target":2},
    {"source":4,"target":2},
    {"source":6,"target":7},
    {"source":5,"target":7},
    {"source":3,"target":7},
    {"source":7,"target":1},
    {"source":8,"target":6},
    {"source":9,"target":3},
    {"source":4,"target":10},
    {"source":2,"target":11},
    {"source":3,"target":1}
  ]
}

这个json的结构是d3的规范,其中分为nodes和links。nodes即效果中的圆球,包括大的彩色球和小的蓝色球,links即圆球间的连线。
links数组中元素的属性比较简单,sourcetarget,source即连线开始与哪个节点(小球),target是结束与哪个个节点。其值表示nodes数组中节点的索引,即第几个元素。
nodes数组中元素属性比较复杂,下面解释下。

{
  "nodes":[
    {
        "name":"楼盘码",//自定义属性,节点名称
        "group":2,//分组,暂时没明白做什么用的
        "class":"node",//节点的class属性
        "tourl":"http://www.iloushi.cn/m/loupanma/",//自定义属性,节点点击后跳转的url
        "img":"...",//自定义属性,节点的图片地址,这里可以把图片base64加密后直接复制在这里
        "imgx":"-28",//自定义属性,节点的坐标x,这里取节点宽度一半的负值是为了让图片居中
        "imgy":"-28",//自定义属性,节点的坐标y,这里取节点高度一半的负值是为了让图片居中
        "w":"56",//节点的宽度
        "h":"56"//节点的高度
    },
  ]
}

数据文件中定义了有几个节点几条线,哪两个节点相连,节点的图片。至于连接线的长短是根据节点之间的作用力强弱自动算出来的,所以如果连线过于集中导致最终小球都挤在一起的话,可以调整小球之间的连线。下面就是用过d3读出数据文件,然后根据数据绘制页面了。
再读数据之前先初始化作用力,利用d3.layout.force中的方法设置作用力。

var wWidth = window.innerWidth,
wHeight = window.innerHeight;
//在body下新建svg元素并设置宽高为屏幕宽高
var svg = d3.select("body").append("svg").attr("width", wWidth).attr("height", wHeight).attr("style", "margin: 0 auto;display: block;");
//初始化作用力并设置参数
var force = d3.layout.force()
              .gravity(.05)//引力强度
              .distance(100)
              .charge( - 250)//节点的电荷数.(电荷数决定结点是互相排斥还是吸引)
              .theta(.01)//电荷间互相作用的强度
              .size([wWidth, wHeight]);//作用力的布局宽高

设置好引力、引力和斥力后就要读取数据了。

//从data.json中读取节点数据
d3.json("data.json",function(error,data) {
    //绘制节点间连线
    var links = svg.selectAll(".link")
                   .data(data.links)//将data.json中的连线数据传入svg中
                   .enter()//进入每条连接线
                   .append("line")//将连接线绘制成line元素
                   .attr("class", "link");
    //绘制节点
    var nodes = svg.selectAll(".node")
                   .data(data.nodes)//将data.json中的节点数据传入svg中
                   .enter()//进入每个节点
                   .append("g")//将节点绘制成g(分组)元素
                   .attr("class", "node")
                   .call(force.drag)//让节点相应作用力中的拖拽
                   .append("image")//在每个g元素下新建image元素
                   .attr("xlink:href",function(e) {return e.img})//将image元素的href属性设置为data.json中的img
                   .attr("tourl",function(e) {return e.tourl})//将image元素的tourl属性设置为data.json中的tourl
                   .attr("x",function(e) {return e.imgx})//将image元素的x属性设置为data.json中的imgx
                   .attr("y",function(e) {  return e.imgy})//将image元素的y属性设置为data.json中的imgy
                   .attr("width",function(e) {return e.w})//将image元素的width属性设置为data.json中的w
                   .attr("height",  function(e) {return e.h });//将image元素的height属性设置为data.json中的h
});

运行代码:

由于还没有将数据填入force(作用力),所有的球都挤在了一起。我们用d3.json从文件中读取数据,回调中的data即为文件中的数据。svg为我们新建的svg画布,d3的链式调用很神奇,比如在还没有将node添加进去之前就可以使用svg.selectAll(".node")选择节点了,看起来是先选择节点再建立节点,根据官方的api应该是调用data()后再调用enter()可以选择按照data新建元素的占位符,也就是说只是占位符还没有真的建立元素。可能运行时不一定是按顺序执行,其内部采用回调的方式执行,如果熟悉d3的朋友可以给我留言这是什么原理,十分感谢。还有一个神奇的地方是attr()方法,第一个参数是属性名称,第二个参数是回调函数,在回调中调用函数的参数e就可以获得这个节点的信息,即nodes数组中单个元素,这样就省去了遍历数组。所以整个代码没有循环也把数据中的数组一一添加到了svg画布中,整段代码显得十分整洁。在链式调用中可以使用append()添加svg标签,然后使用attr()设置属性,这样就可以在节点中任意添加元素了。
上面只是把节点添加到svg中绘制出来,为了让节点可以移动我们还要把节点添加到force里面去,这样物理引擎与渲染引擎一一对应就可以联动起来了。

//将节点传入作用力
force.nodes(data.nodes)
     .links(data.links)
     .start();
//让节点在每一帧都根据作用力的变化重新绘制
force.on("tick",function() {
    links.attr("x1",function(e) {return e.source.x})//将x1设置为前节点的x
         .attr("y1",    function(e) {return e.source.y})//将y1设置为前节点的y
         .attr("x2",    function(e) {return e.target.x})//将x2设置为后节点的x
         .attr("y2",    function(e) {return e.target.y});//将y2设置为后节点的y
    nodes.attr("transform",function(e) {return "translate(" + e.x + "," + e.y + ")"});//更新节点的x,y
});

其中的tick事件表示每一帧类似于requestAnimationFrame。这样整个页面就根据作用力的约束动起来了。

时间仓促未作详细测试,如有任何bug请在Issues中提出。

项目地址github
如有问题或者建议请微博@UED天机。我会及时回复
更多教程请关注ued.sexy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图像识别技术在病虫害检测中的应用是一个快速发展的领域,它结合了计算机视觉和机器学习算法来自动识别和分类植物上的病虫害。以下是这一技术的一些关键步骤和组成部分: 1. **数据收集**:首先需要收集大量的植物图像数据,这些数据包括健康植物的图像以及受不同病虫害影响的植物图像。 2. **图像预处理**:对收集到的图像进行处理,以提高后续分析的准确性。这可能包括调整亮度、对比度、去噪、裁剪、缩放等。 3. **特征提取**:从图像中提取有助于识别病虫害的特征。这些特征可能包括颜色、纹理、形状、边缘等。 4. **模型训练**:使用机器学习算法(如支持向量机、随机森林、卷积神经网络等)来训练模型。训练过程中,算法会学习如何根据提取的特征来识别不同的病虫害。 5. **模型验证和测试**:在独立的测试集上验证模型的性能,以确保其准确性和泛化能力。 6. **部署和应用**:将训练好的模型部署到实际的病虫害检测系统中,可以是移动应用、网页服务或集成到智能农业设备中。 7. **实时监测**:在实际应用中,系统可以实时接收植物图像,并快速给出病虫害的检测结果。 8. **持续学习**:随着时间的推移,系统可以不断学习新的病虫害样本,以提高其识别能力。 9. **用户界面**:为了方便用户使用,通常会有一个用户友好的界面,显示检测结果,并提供进一步的指导或建议。 这项技术的优势在于它可以快速、准确地识别出病虫害,甚至在早期阶段就能发现问题,从而及时采取措施。此外,它还可以减少对化学农药的依赖,支持可持续农业发展。随着技术的不断进步,图像识别在病虫害检测中的应用将越来越广泛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值