Руководство по перетаскиванию в svelte с нуля

Читайте, если:

  • Хотите узнать о перетаскивании в svelte с использованием апи браузера.
  • Хотите изучить пользовательскую анимацию в svelte.

Пример

  • Вот ссылка на демонстрацию на stackblitz

Введение
У нас всегда есть что-то, что мы перетаскиваем, и в веб-разработке это события перетаскивания.
Здесь я собираюсь поделиться базовым примером перетаскивания в svelte с использованием браузерного apis с нуля, и вы можете использовать его svelteKit.

Что нам нужно?
Сначала вам нужно настроить ваш проект svelte, и в этом руководстве я не буду фокусироваться на дизайне/css. Это зависит от вас, как вы будете его использовать.

  • Настройка проекта svelte
  • Установите внутренние зависимости
  • Откройте ваш проект и откройте файл index.svelte.

Это ваша обычная настройка svelte.

Объяснение кода

<script>
    import {flip} from 'svelte/animate';
    import { send, receive } from './transition.js';
    let RandomStack = [
        {
            "name": "Random",
            "items": ["React", "Angular", "Solid", "Rails", "Express", "Flask", "VPS"]
        },
    {
      "name": "Frontend Stack",
      "items": ["Svelte", "SvelteKit"]
    },
    {
      "name": "Backend Stack",
      "items": ["Django"]
    },
        {
      "name": "Server Stack",
      "items": ["Vercel"]
    }
  ];

    let stackHover;

    function dragStart(event, stackIndex, itemIndex) {
        const data = {stackIndex, itemIndex};
    event.dataTransfer.setData('text/plain', JSON.stringify(data));
    }

    function drop(event, stackIndex) {
        event.preventDefault();
    const json = event.dataTransfer.getData("text/plain");
        const data = JSON.parse(json);
        const [item] = RandomStack[data.stackIndex].items.splice(data.itemIndex, 1);
        RandomStack[stackIndex].items.push(item);
        RandomStack = RandomStack;

        stackHover = null;
    }
</script>

<p>Drag a framework/library from random to respected drop</p>

{#each RandomStack as stack, stackIndex (stack)}
  <div animate:flip>
    <b>{stack.name}</b>
    <p
        class:hovering={stackHover === stack.name}
        on:dragenter={() => stackHover = stack.name}
      on:dragleave={() => stackHover = null}
        on:drop={event => drop(event, stackIndex)}
        ondragover="return false"
    >
        {#each stack.items as item, itemIndex (item)}
              <div class="item" in:receive={{ key: itemIndex }}
        out:send={{ key: itemIndex }}
        animate:flip={{ duration: 500 }}>
            <li
                draggable={true}
                  on:dragstart={event => dragStart(event, stackIndex, itemIndex)}
                >
                {item}
              </li>
              </div>
        {/each}
    </p>
  </div>
{/each}

<style>
    .hovering {
        border-color: orange;
    }
    .item {
        display: inline; /* required for flip to work */
    }
    li {
        background-color: lightgray;
        cursor: pointer;
        display: inline-block;
        margin-right: 10px;
        padding: 10px;
    }
    li:hover {
        background: orange;
        color: white;
    }
  p {
        border: solid lightgray 1px;
        display: flex; /* required for drag & drop to work when .item display is inline */
        height: 40px; /* needed when empty */
        padding: 10px;
    }
</style>
Войти в полноэкранный режим Выйти из полноэкранного режима

Здесь выше я начал с RandomStack, я назначил ему свой объект и элементы на основе того, что он будет показывать элементы в списке перетаскивания.

<p>Drag a framework/library from random to respected drop</p>

{#each RandomStack as stack, stackIndex (stack)}
  <div animate:flip>
    <b>{stack.name}</b>
    <p
        class:hovering={stackHover === stack.name}
        on:dragenter={() => stackHover = stack.name}
      on:dragleave={() => stackHover = null}
        on:drop={event => drop(event, stackIndex)}
        on:dragover="return false"
    >
        {#each stack.items as item, itemIndex (item)}
              <div class="item" in:receive={{ key: itemIndex }}
        out:send={{ key: itemIndex }}
        animate:flip={{ duration: 500 }}>
            <li
                draggable={true}
                  on:dragstart={event => dragStart(event, stackIndex, itemIndex)}
                >
                {item}
              </li>
              </div>
        {/each}
    </p>
  </div>
{/each}
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь я сначала настраиваю элементы #each loop для легкого шаблонирования. Вот как это будет выглядеть

  • Выше я использую события браузера dragstart, dragenter, dragleave, drop, чтобы заставить элементы перетаскиваться.

  • dragstart: определяет, какой элемент и из какого стека мы начали перетаскивать.

// function called
on:dragstart={event => dragStart(event, stackIndex, itemIndex)}

// dragStart function
function dragStart(event, stackIndex, itemIndex) {
        const data = { stackIndex, itemIndex };
        event.dataTransfer.setData('text/plain', JSON.stringify(data));
    }
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь мы устанавливаем наши данные в событие, чтобы мы могли получить доступ к тем же данным в событии drop.

  • dragenter : Это событие происходит, когда перетаскиваемый элемент или текстовое выделение попадает в допустимую цель падения.

  • dragleave: Это событие происходит, когда перетаскиваемый элемент или текстовое выделение покидает допустимую цель падения.

  • drop: Это событие принимает информацию о том, из какой зоны перетаскивания он появился, чтобы мы могли удалить элемент из последней зоны перетаскивания и добавить его в новую зону перетаскивания.

\ html function call 
on:drop={(event) => drop(event, stackIndex)}

\ function which is called while drop
    function drop(event, stackIndex) {
        event.preventDefault();
        const json = event.dataTransfer.getData('text/plain');
        const data = JSON.parse(json);
        const [item] = RandomStack[data.stackIndex].items.splice(data.itemIndex, 1);
        RandomStack[stackIndex].items.push(item);
        RandomStack = RandomStack;

        stackHover = null;
    }
Вход в полноэкранный режим Выход из полноэкранного режима

В функции мы получаем доступ к переданным данным от начала перетаскивания и с их помощью удаляем элемент из последней зоны перетаскивания и добавляем его в новую зону.

Вот так можно сделать перетаскивание с использованием апи браузера. Теперь я приведу фрагмент кода, который я узнал от Svelte Learn

import { crossfade } from 'svelte/transition';
import { quintOut } from 'svelte/easing';

export const [send, receive] = crossfade({
    duration: (d) => Math.sqrt(d * 200),

    fallback(node, params) {
        const style = getComputedStyle(node);
        const transform = style.transform === 'none' ? '' : style.transform;

        return {
            duration: 600,
            easing: quintOut,
            css: (t) => `
                transform: ${transform} scale(${t});
                opacity: ${t}
            `
        };
    }
});
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь мы расширяем наш стандартный переход crossfade с помощью функций получателя и отправителя, которые принимают ваш узел и анимируют в соответствии с вашими потребностями. Вы можете определить пользовательские css и стили. Более подробное объяснение вы можете найти на сайте learn.svelte.dev.

Это я пишу для вас. Если вы хотите что-то спросить или предложить, пожалуйста, напишите это в комментариях.

Оцените статью
devanswers.ru
Добавить комментарий