1. 程式人生 > >Raphaël的動態線條新增,節點拖拽

Raphaël的動態線條新增,節點拖拽

大部分參考:原文地址

首先定義幾個變數:

var paper =null;

var dragger=null;

var move=null;

var up=null;

var shapes=null;

var mouseX=null;//儲存頁面中滑鼠的X軸座標

var mouseY=null;//儲存頁面中滑鼠的Y軸座標

var r=null;

var objCrr=null;

var mouse=null;//儲存頁面中滑鼠的屬性

var connections=[];//用來儲存節點的順序

$(function(){

$("#holder").mousemove(function(obj){

moush=obj;

moushX=obj.clientX;

moushY=obj.clientY;

if(objCrr!=null){

r.drawArr(objCrr);

}

})

//拖動節點開始時的事件
            var dragger = function () {
                this.ox = this.attr("x");
                this.oy = this.attr("y");
                this.animate({ "fill-opacity": .2 }, 500);
            };

 //拖動事件
            var move = function (dx, dy) {
                var att = { x: this.ox + dx, y: this.oy + dy };
                this.attr(att);
                $("#test" + this.id).offset({ top: this.oy + dy + 10, left: this.ox + dx + 10 });
                for (var i = connections.length; i--; ) {
                    r.drawArr(connections[i]);
                }
            };
            //拖動結束後的事件
            var up = function () {
                this.animate({ "fill-opacity": 0 }, 500);
            };
            //建立繪圖物件
            var r = Raphael("holder", $(window).width(), $(window).height());
            //繪製節點
            var shapes = [
                        r.rect(190, 100, 60, 40, 4),
                        r.rect(290, 80, 60, 40, 4),
                        r.rect(290, 180, 60, 40, 4),
                        r.rect(450, 100, 60, 40, 4)
                     ];
            //定位節點上的文字
            $("#test1").offset({ top: 100 + 10, left: 190 + 10 });
            $("#test2").offset({ top: 80 + 10, left: 290 + 10 });
            $("#test3").offset({ top: 180 + 10, left: 290 + 10 });
            $("#test4").offset({ top: 100 + 10, left: 450 + 10 });
            //為節點新增樣式和事件,並且繪製節點之間的箭頭
            for (var i = 0, ii = shapes.length; i < ii; i++) {
                var color = Raphael.getColor();
                shapes[i].attr({ fill: color, stroke: color, "fill-opacity": 0, "stroke-width": 2, cursor: "move" });
                shapes[i].id = i + 1;
                shapes[i].drag(move, dragger, up);

shapes[i].click(click);
shapes[i].dblclick(function () { alert(this.id) })

}

 //儲存節點間的順序
   connections.push(r.drawArr({ obj1: shapes[0], obj2: shapes[1] }));
   connections.push(r.drawArr({ obj1: shapes[1], obj2: shapes[2] }));
   connections.push(r.drawArr({ obj1: shapes[2], obj2: shapes[3] }));     

})

var startNode=null;//兩個節點連線時,儲存開始的節點

var saveNode=new Array();//儲存兩個節點

var tempArrPath=[];//兩個點連線時用於暫時儲存起始節點到滑鼠的線段

function click(){

svaeNode.push(this);

if(saveNode.length==1){

startNode=this;

}

if(saveNode.length==2){

if(tempArrPath[0]!=undefined){

tempArrPath[0].arrPath.remove();

saveNode.splice(0,2);

objCrr={obj1:startNode,obj2:this};

connections.push(r.drawArr(objCrr));

}else{

startNode=this;

saveNode.splice(0,2);

saveNode.push(this);

}

}

}

在拖動事件中,動態改變了節點文字元素的位置

並且重繪了節點和箭頭

drawArr是一個自定義方法,負責修改箭頭的方向,程式碼如下

//隨著節點位置的改變動態改變箭頭
        Raphael.fn.drawArr = function (obj) {

if(obj.ibj2==null){

           var point = getStartEnd(obj.obj1, obj.obj2);
            var path1 = getArr(point.start.x, point.start.y, mouseX, mouseY-10, 8);
            for(var i=0;i<tempArrPath.Length;i++){

                tempArrPath[i].arrPath.remove();

            }

   tempArrPath=[];

  obj.arrPath=this.path(path2);

obj.arrPath.attr({"stroke-width":2});

tempArrPath.push(obj);

return;

}else{

            tempArrPath.splice(0,tempArrPath.Length);

            var point = getStartEnd(obj.obj1, obj.obj2);
            var path1 = getArr(point.start.x, point.start.y, point.end.x, point.end.y, 8);
            if (obj.arrPath) {
                obj.arrPath.attr({ path: path1 });
            } else {
                obj.arrPath = this.path(path1);
            }
            return obj;

}
        

};

首先需要確定箭頭的起始位置,

point包含兩個點,

point.start為起點,

point.end為終點,

然後需要確定箭頭的繪圖路徑

一個箭頭包含三個線段,四個點

1:起點,2:終點,3:箭頭終點1,4:箭頭終點2

image

在此函式中,判斷如果箭頭已經被繪製過,

只要修改屬性即可

如果沒有被繪製過,則需要重新繪製

下面來看一下動態確定起點和終點的程式碼

function getStartEnd(obj1, obj2) {
            var bb1 = obj1?bj1.getBBox():null;
                bb2 = obj2?j2.getBBox():null;
            var p = [
                    bb1?{ x: bb1.x + bb1.width / 2, y: bb1.y - 1 }:{},
                    bb1?{ x: bb1.x + bb1.width / 2, y: bb1.y + bb1.height + 1 }:{},
                    bb1?{ x: bb1.x - 1, y: bb1.y + bb1.height / 2 }:{},
                    bb1?{ x: bb1.x + bb1.width + 1, y: bb1.y + bb1.height / 2 }:{},
                    bb2?{ x: bb2.x + bb2.width / 2, y: bb2.y - 1 }:{},
                    bb2?{ x: bb2.x + bb2.width / 2, y: bb2.y + bb2.height + 1 }:{},
                    bb2?{ x: bb2.x - 1, y: bb2.y + bb2.height / 2 }:{},
                    bb2?{ x: bb2.x + bb2.width + 1, y: bb2.y + bb2.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 {
                res = d[Math.min.apply(Math, dis)];
            }
            var result = {};
            result.start = {};
            result.end = {};
            result.start.x = p[res[0]].x;
            result.start.y = p[res[0]].y;
            result.end.x = p[res[1]].x;
            result.end.y = p[res[1]].y;
            return result;
        }
//新增線條的方法  function addLine(){
if(startNode==null){
alert("還沒有選擇節點"); return -1;
}else{
objCrr={obj1:startNode,obj2:null};
}
}

//獲取組成箭頭的三條線段的路徑
        function getArr(x1, y1, x2, y2, size) {
            var angle = Raphael.angle(x1, y1, x2, y2);//得到兩點之間的角度
            var a45 = Raphael.rad(angle - 45);//角度轉換成弧度
            var a45m = Raphael.rad(angle + 45);
            var x2a = x2 + Math.cos(a45) * size;
            var y2a = y2 + Math.sin(a45) * size;
            var x2b = x2 + Math.cos(a45m) * size;
            var y2b = y2 + Math.sin(a45m) * size;
            var result = ["M", x1, y1, "L", x2, y2, "L", x2a, y2a, "M", x2, y2, "L", x2b, y2b];
            return result;
        }

頁面

<input type="button" onclick="addLine()" value="新增線條"/>

<div id="holder"></div>

<div id="test1" class="test">測試1</div>

<div id="test2" class="test">測試2</div>

<div id="test3" class="test">測試3</div>

<div id="test4" class="test">測試4</div>



相關推薦

Raphaël動態線條新增,節點

大部分參考:原文地址 首先定義幾個變數: var paper =null; var dragger=null; var move=null; var up=null; var shapes=null; var mouseX=null;//儲存頁面中滑鼠的X軸座標 var

DevExpress XtraTreeList 節點

using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data;

element-ui dialog元件新增位置 可寬高

有幾個點需要注意一下 每個彈窗都要有唯一dom可操作 指令可以做到 拖拽時要新增可拖拽區塊 header 由於element-ui dialog元件在設計時寬度用了百分比, 這裡不同瀏覽器有相容性問題 實現拖拽寬高時 獲取邊緣問題 div定位 設定模擬邊緣 <t

原生js實現節點

var Drags = function (element, callback) { callback = callback || function () {}; var params = {

仿QQ訊息導航欄RadioGroup裡新增的TextView(未讀訊息)

效果圖: MainActivity: 主要是放置拖拽的TextView的位置setTextView(); 設定未讀訊息 textView.setText(“10”); public class MainActivity extends AppCompatActivity

Js動態給表格節點tbody新增<td>資料

/** * 動態<td>填充當前頁 */ function fillPage() { // 根據記錄數確定要生成的行數 for (var i = 0; i != dataArray.length; ++i) { // 建立一個行元素

解決 jQuery 動態新增節點無法觸發 onclick 點選事件的問題

     問題: 當我們在網頁載入完成後, 使用 JQuery 給頁面動態增加增加節點時, 會發現新增節點無法觸發點選事件      處理: 使用 live() 或 on() 方法給新增節點新增點選事件    !

js中 ajax動態新增節點無法觸發點選事件

在寫ajax載入資料的時候發現,後面新增進來的demo節點元素,失去了之前的點選事件。 其實最簡單的方法就是直接在標籤中寫onclick="",但是這樣寫有些場景的是實現不了的,最好的方式還是通過給類名繫結一個click事件。 方法一:使用live: live()函式會給被選的元素繫結上一個或者多個事件

C# TreeView 節點到另一個容器Panel中簡單實現

C# TreeView 拖拽節點到另一個容器Panel中簡單實現 用了這麼久C#拖拽功能一直沒有用到也就沒用過,今天因為專案需要,領導特地給我簡單講解了下拖拽功能,真是的大師講解一點通啊。特地寫一篇部落格記錄下,分享給大家!也方便以後自己檢視。 1.拖拽功能分析 拖拽功能分析其實就三個字:選-->

js仿百度地圖、縮放、新增圖層功能(原創)

最近專案中完成的需求,仿百度地圖中的功能: 要求:1.底層圖可以拖拽、縮放。       2.拖拽一個圖示,在底層圖上對應位置新增一個標註點,該標註點位置要隨底層圖移動。    3.新增的標註點,可以拖動,刪除。 主要知識點和難點就是各個瀏覽器的點選、拖拽、縮放事件相容性,對js運動屬性、運動偏移位置的瞭解,

動態新增和刪除hadoop叢集中的節點

一:新增節點 A:新節點中新增賬戶,設定無密碼登陸 B:Name節點中設定到新節點的無密碼登陸 ssh-copy-id slave4 C:在Name節點slaves檔案中新增新節點 D:在所有節點/etc/hosts檔案中增加新節點(所有節點保持一致)

d3滑鼠、放大縮小後動態載入頁面資料demo

d3滑鼠拖拽、放大縮小後動態載入頁面資料demo index.html <!DOCTYPE html> <html> <head>     <meta charset="UTF-8">     <style

【前端】利用Canvas給圖片新增水印,支援、編輯、縮放與刪除

利用Canvas給圖片新增水印,支援拖拽、編輯、縮放與刪除。 難點一: 如何在偽元素after“刪除按鈕“上新增點選事件。 通過滑鼠點選位置event中offsetX屬性獲得其偏離元素距離,與元素寬度做比較。若大於元素寬度,則點選在了偽元素上,否則點選到正常元

Js動態給表格節點tbody新增資料

/** * 動態<td>填充當前頁 */ function fillPage() { // 根據記錄數確定要生成的行數 for (var i = 0; i != dataArray.length; ++i) { // 建立一個

動態配置模組實現模組效果

需要用到js,gridster html程式碼如下<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="Gener

為bootstrap模態視窗新增(draggable )事件

</pre><pre name="code" class="html"><!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <lin

為Bootstrap模態對話方塊新增移動功能

<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge">

DevExpress使用經驗分享:Treelist節點

本篇要實現的目標,簡單來說就是把一個的節點用滑鼠拖到另外的節點(自身或其他的listview)上,如下圖: (圖一) (圖二) (圖三) 首先,在視窗中拉入兩個listview,第一個建立三列(上),第二個建立兩列(下),如下圖: 為第一個listview建立一些節點:

easyu tree節點(1)

<div id="treediv"><ul id='tt'></ul></div> <script> var treedata = [{"id":"0","text":"根節點","state":"open",

jquery動態新增節點

<1> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xh