sortablejs、vuedraggable實現拖拽排序,在android、iOS、chrome模擬移動設備的情況下,拖拽元素有SVG存在時,可能會卡住,不觸發end事件

背景

在做一個拖動應用圖片排序的場景下,androidiOSchrome模擬移動設備 的情況,應用圖片用的是svg,大概率會出現ghost元素不消失,也不觸發end事件的詭異情況。
注意
PC端使用chrome 調試模式下,不開啓模擬移動設備不會出現這種情況,開啓來模擬移動設備也會出現。

使用的是vue + vuedraggable實現。效果如下圖:

解決辦法

svg元素設置一個css樣式,即可;

svg {
    pointer-events: none;
}

原因分析

根據上面出現,沒有觸發end事件,查看sortablejs源代碼,可以看到sortablejs是通過監聽類似:touchend,mouseup,pointerup類似這樣的事件,認爲拖動結束,從而完成後續動作,移除ghost元素,並觸發end事件。
分析步驟:

  1. 在chrome 調試下監聽上面的三個touchend,mouseup,pointerup,發現只要出現上面的情況,這些事件都不會觸發。從而可以判斷是原來瀏覽器沒有觸發事件
  2. 在頁面是移除圖標,再此拖動,發現可以正常拖動排序。從而判斷問題出現在圖標上,圖標使用的svg。
  3. 看瀏覽器性能面板,是不是拖動svg會造成大量渲染,從而導致瀏覽器卡頓,從而沒有觸發上面的事件,經過實驗,並不是這個原因
  4. 猜測鼠標移動svg上,因爲svg本身就具有動畫的效果,是不是和外面的事件衝突,阻擋了事件觸發,實驗在svg上用絕對定位放了一個空白的元素,發現問題解決。在這個思路上繼續找相關的答案,找到css屬性 pointer-events

pointer-events

【 CSS 屬性指定在什麼情況下 (如果有) 某個特定的圖形元素可以成爲鼠標事件的 target" 】。具體參考 pointer-events MDN的說明

語法:
pointer-events屬性被指定爲從下面的值列表中選擇的一個關鍵字。

  1. auto
    與pointer-events屬性未指定時的表現效果相同,對於SVG內容,該值與visiblePainted效果相同
  2. none
    元素永遠不會成爲鼠標事件的target。但是,當其後代元素的pointer-events屬性指定其他值時,鼠標事件可以指向後代元素,在這種情況下,鼠標事件將在捕獲或冒泡階段觸發父元素的事件偵聽器。
  3. visiblePainted
    只適用於SVG。元素只有在以下情況纔會成爲鼠標事件的目標:
    visibility屬性值爲visible,且鼠標指針在元素內部,且fill屬性指定了none之外的值
    visibility屬性值爲visible,鼠標指針在元素邊界上,且stroke屬性指定了none之外的值
  4. visibleFill
    只適用於SVG。只有在元素visibility屬性值爲visible,且鼠標指針在元素內部時,元素纔會成爲鼠標事件的目標,fill屬性的值不影響事件處理。
  5. visibleStroke
    只適用於SVG。只有在元素visibility屬性值爲visible,且鼠標指針在元素邊界時,元素纔會成爲鼠標事件的目標,stroke屬性的值不影響事件處理。
  6. visible
    只適用於SVG。只有在元素visibility屬性值爲visible,且鼠標指針在元素內部或邊界時,元素纔會成爲鼠標事件的目標,fill和stroke屬性的值不影響事件處理。
  7. painted
    只適用於SVG。元素只有在以下情況纔會成爲鼠標事件的目標:
    鼠標指針在元素內部,且fill屬性指定了none之外的值
    鼠標指針在元素邊界上,且stroke屬性指定了none之外的值
    visibility屬性的值不影響事件處理。
  8. fill
    只適用於SVG。只有鼠標指針在元素內部時,元素纔會成爲鼠標事件的目標,fill和visibility屬性的值不影響事件處理。
  9. stroke
    只適用於SVG。只有鼠標指針在元素邊界上時,元素纔會成爲鼠標事件的目標,stroke和visibility屬性的值不影響事件處理。
  10. all
    只適用於SVG。只有鼠標指針在元素內部或邊界時,元素纔會成爲鼠標事件的目標,fill、stroke和visibility屬性的值不影響事件處理。

根據上面的屬性說明,可以看到默認的情況下,svg:visiblePainted,我們使用的svg是從sketch 軟件導出的,裏面確實包含fill, stroke屬性,最終我們選擇粗暴的方式,設置爲 “none” 解決。

示例svg

<?xml version="1.0" encoding="UTF-8"?>
<svg width="60px" height="60px" viewBox="0 0 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 63.1 (92452) - https://sketch.com -->
    <title>形狀結合</title>
    <desc>Created with Sketch.</desc>
    <g id="工作臺" stroke="none" stroke-width="1" fill-rule="evenodd">
        <g id="3-1工作臺" transform="translate(-626.000000, -568.000000)">
            <g id="編組-36" transform="translate(43.000000, 549.000000)">
                <g id="編組-20" transform="translate(3.000000, 0.000000)">
                    <g id="youjian" transform="translate(562.000000, 1.000000)">
                        <g id="編組-21">
                            <g id="youjian" transform="translate(18.000000, 18.000000)">
                                <path d="M4.99995326,20.244 L28.3583213,31.4139931 C28.8205574,31.6350244 29.3264899,31.6819953 29.7962042,31.5752545 C30.3767838,31.8438191 31.0647942,31.8560532 31.6763236,31.563633 L31.6763236,31.563633 L55.0339533,20.394 L55.0346,45.252 C55.0346,49.8911919 51.2737919,53.652 46.6346,53.652 L13.4,53.652 C8.7608081,53.652 5,49.8911919 5,45.252 L4.99995326,20.244 Z M46.6346,6 C51.2737919,6 55.0346,9.7608081 55.0346,14.4 L55.0349184,17.0342857 C54.4239245,16.6890913 53.664156,16.6447522 52.9957553,16.964367 L52.9957553,16.964367 L30.1739533,27.8765471 L7.03888956,16.8147272 C6.37077757,16.4952504 5.61137681,16.5394132 5.00051835,16.8841987 L5,14.4 C5,9.7608081 8.7608081,6 13.4,6 L46.6346,6 Z" id="形狀結合"></path>
                            </g>
                        </g>
                    </g>
                </g>
            </g>
        </g>
    </g>
</svg>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章