簡體   English   中英

svg拖放

[英]svg drag and drop

我有一個帶有外部foreignObject的svg元素,其中包含一些div。 我希望能夠拖動該對象。 唯一的問題:我無法正常工作。

我找到了幾個SO答案並嘗試實現它們。 但是它們都不起作用,因為我一遍又一遍地得到相同的錯誤:

Uncaught TypeError: undefined is not a function 

要么

evt is not defined

我必須從網站上遵循以下代碼(由SO答案指出):

<svg id="bewaar_holder" xmlns="http://www.w3.org/2000/svg" width="800" height="500" onload="Init(evt)" onmousedown="Grab(evt)" onmousemove="Drag(evt)" onmouseup="Drop(evt)"></svg>

var SVGDocument = null;
var SVGRoot = null;

var TrueCoords = null;
var GrabPoint = null;
var BackDrop = null;
var DragTarget = null;

function Init(evt) {
    SVGDocument = evt.target.ownerDocument;
    SVGRoot = SVGDocument.documentElement;

    // these svg points hold x and y values...
    //    very handy, but they do not display on the screen (just so you know)
    TrueCoords = SVGRoot.createSVGPoint();
    GrabPoint = SVGRoot.createSVGPoint();

    // this will serve as the canvas over which items are dragged.
    //    having the drag events occur on the mousemove over a backdrop
    //    (instead of the dragged element) prevents the dragged element
    //    from being inadvertantly dropped when the mouse is moved rapidly
    BackDrop = SVGDocument.getElementById('BackDrop');
}

function Grab(evt) {
    // find out which element we moused down on
    var targetElement = evt.target;

    // you cannot drag the background itself, so ignore any attempts to mouse down on it
    if (BackDrop != targetElement) {
        //set the item moused down on as the element to be dragged
        DragTarget = targetElement;

        // move this element to the "top" of the display, so it is (almost)
        //    always over other elements (exception: in this case, elements that are
        //    "in the folder" (children of the folder group) with only maintain
        //    hierarchy within that group
        DragTarget.parentNode.appendChild(DragTarget);

        // turn off all pointer events to the dragged element, this does 2 things:
        //    1) allows us to drag text elements without selecting the text
        //    2) allows us to find out where the dragged element is dropped (see Drop)
        DragTarget.setAttributeNS(null, 'pointer-events', 'none');

        // we need to find the current position and translation of the grabbed element,
        //    so that we only apply the differential between the current location
        //    and the new location
        var transMatrix = DragTarget.getCTM();
        GrabPoint.x = TrueCoords.x - Number(transMatrix.e);
        GrabPoint.y = TrueCoords.y - Number(transMatrix.f);

    }
};


function Drag(evt) {
    // account for zooming and panning
    GetTrueCoords(evt);

    // if we don't currently have an element in tow, don't do anything
    if (DragTarget) {
        // account for the offset between the element's origin and the
        //    exact place we grabbed it... this way, the drag will look more natural
        var newX = TrueCoords.x - GrabPoint.x;
        var newY = TrueCoords.y - GrabPoint.y;

        // apply a new tranform translation to the dragged element, to display
        //    it in its new location
        DragTarget.setAttributeNS(null, 'transform', 'translate(' + newX + ',' + newY + ')');
    }
};


function Drop(evt) {
    // if we aren't currently dragging an element, don't do anything
    if (DragTarget) {
        // since the element currently being dragged has its pointer-events turned off,
        //    we are afforded the opportunity to find out the element it's being dropped on
        var targetElement = evt.target;

        // turn the pointer-events back on, so we can grab this item later
        DragTarget.setAttributeNS(null, 'pointer-events', 'all');
        if ('Folder' == targetElement.parentNode.id) {
            // if the dragged element is dropped on an element that is a child
            //    of the folder group, it is inserted as a child of that group
            targetElement.parentNode.appendChild(DragTarget);
            alert(DragTarget.id + ' has been dropped into a folder, and has been inserted as a child of the containing group.');
        } else {
            // for this example, you cannot drag an item out of the folder once it's in there;
            //    however, you could just as easily do so here
            alert(DragTarget.id + ' has been dropped on top of ' + targetElement.id);
        }

        // set the global variable to null, so nothing will be dragged until we
        //    grab the next element
        DragTarget = null;
    }
};


function GetTrueCoords(evt) {
    // find the current zoom level and pan setting, and adjust the reported
    //    mouse position accordingly
    var newScale = SVGRoot.currentScale;
    var translation = SVGRoot.currentTranslate;
    TrueCoords.x = (evt.clientX - translation.x) / newScale;
    TrueCoords.y = (evt.clientY - translation.y) / newScale;
};

但是我得到這個錯誤:

Uncaught TypeError: undefined is not a function 
on line: TrueCoords = SVGRoot.createSVGPoint();

當我記錄evt值時,Chrome調試器會提供以下輸出: 在此處輸入圖片說明

還有一些我不明白的地方...在第一行srcElement確實有一個值,但是當我擴展事件時,它不再有srcElement了...

所以我沒有頭緒。 我以前從未使用過svg,而且我不是JS專家。 所以我希望你們知道我做錯了...

這是一個JSFiddle

不太確定它應該做什么,但是這將消除錯誤...您可以拖放,如果它是同一svg或其他內容,則我不確定該背景應該是什么。

問題似乎是SV​​GRoot變成了html元素而不是svg(也許是因為它擺在擺弄的位置,不確定),所以我將其更改為通過其ID選擇。

 SVGRoot = document.getElementById('bewaar_holder');

  BackDrop = document.getElementById('BackDrop');

您可能需要更改這些。

的jsfiddle

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM