Sveltekit: different in|out FLY transition (vertical and horizontal) based on screen width

huangapple go评论51阅读模式
英文:

Sveltekit: different in|out FLY transition (vertical and horizontal) based on screen width

问题

我正在学习Sveltekit,并试图弄清楚如何根据屏幕宽度(例如移动设备和显示器)来实现两种不同方向的进入/退出动画。

类似以下的方式:
如果在显示器屏幕上(最小宽度:640px),则从左侧进入
否则(如果在移动手机上),则从顶部进入

这是我目前的代码示例:

<script lang="ts">
	import { fade, fly } from 'svelte/transition';

	/* 导航菜单 */
	const navigation = [
		{
			title: '主页',
			href: '/'
		},
		{
			title: '关于',
			href: '/about'
		},
		{
			title: '项目',
			href: '/projects'
		},
		{
			title: '联系',
			href: '/contact'
		}
	];
</script>
<nav class="navigation" in:fade={{ duration: 100 }} out:fade={{ duration: 100 }}>
	<ul
		class="navigation__content"
		in:fly={{ x: -1000, duration: 300 }}
		out:fly={{ x: -1000, duration: 300 }}
	>
		{#each navigation as navItem}
			<li class="navigation__page">
				<a href={navItem.href}>{navItem.title}</a>
			</li>
		{/each}
	</ul>
</nav>

我不太确定如何实现这样的效果,我考虑使用#if语句。我在网上搜索了一下,但没有找到有用的信息。

英文:

I'm learning Sveltekit and i am trying to figure out how i can implent two differently oriented in:fly/out:fly based on the width of the screen (mobile and monitor for example).

Something like:
IF on monitor screen (min-width: 640px) then in:fly from the left
ELSE (if on mobile phone) in:fly from the top

This is an example of my code at the moment:

<script lang="ts">
	import { fade, fly } from 'svelte/transition';

	/* Navigation menu */
	const navigation = [
		{
			title: 'Home',
			href: '/'
		},
		{
			title: 'About',
			href: '/about'
		},
		{
			title: 'Projects',
			href: '/projects'
		},
		{
			title: 'Contact',
			href: '/contact'
		}
	];
</script>
<nav class="navigation" in:fade={{ duration: 100 }} out:fade={{ duration: 100 }}>
	<ul
		class="navigation__content"
		in:fly={{ x: -1000, duration: 300 }}
		out:fly={{ x: -1000, duration: 300 }}
	>
		{#each navigation as navItem}
			<li class="navigation__page">
				<a href={navItem.href}>{navItem.title}</a>
			</li>
		{/each}
	</ul>
</nav>

I am not quite sure how i could implement something like this, i was thinking about a #if statement.
I searched the web but couldn't find anything useful.

答案1

得分: 2

你可以创建一个存储以编程方式匹配媒体查询并相应地切换过渡参数例如

```js
import { onMount } from 'svelte';
import { writable } from 'svelte/store';

export function mediaQueryStore(query) {
    const store = writable(false);

    onMount(() => {
        const mediaQueryList = window.matchMedia(query);

        const onChange = () => store.set(mediaQueryList.matches);
        mediaQueryList.addEventListener('change', onChange);
        onChange();

        return () => mediaQueryList.removeEventListener('change', onChange);
    });

    return { subscribe: store.subscribe };
}
const small = mediaQueryStore('(max-width: 600px)');
<div transition:fly={$small ?
  { x: -1000, duration: 300 } : 
  { y: -1000, duration: 300 }}>

(如果进出动画相同,你可以只使用 transition:...

REPL


<details>
<summary>英文:</summary>

You can create a store that programmatically matches a media query and switch out the transition arguments accordingly, e.g.

```js
import { onMount } from &#39;svelte&#39;;
import { writable } from &#39;svelte/store&#39;;

export function mediaQueryStore(query) {
	const store = writable(false);
	
	onMount(() =&gt; {
		const mediaQueryList = window.matchMedia(query);

		const onChange = () =&gt; store.set(mediaQueryList.matches);
		mediaQueryList.addEventListener(&#39;change&#39;, onChange);
		onChange();

		return () =&gt; mediaQueryList.removeEventListener(&#39;change&#39;, onChange);
	});

	return { subscribe: store.subscribe };
}
const small = mediaQueryStore(&#39;(max-width: 600px)&#39;);
&lt;div transition:fly={$small ?
  { x: -1000, duration: 300 } : 
  { y: -1000, duration: 300 }}&gt;

(If in/out animations are the same, you can just use transition:...)

REPL

答案2

得分: 2

一种方法是通过内部宽度绑定(教程链接)来监视窗口宽度,并相应地设置 xy

REPL链接

<script>
	import {fly} from 'svelte/transition';

	let innerWidth;
	const threshold = 640;
	$: x = innerWidth >= threshold ? -100 : 0;
	$: y = innerWidth < threshold ? -100 : 0;

	let nrs = [0,1,2,3,4,5,6,7];

	function add() {
		nrs = [...nrs, nrs.length];
	}
</script>

<svelte:window bind:innerWidth />

<div id="page">
	<button on:click={add}>add one</button>
	<button on:click={() => nrs = [0,1,2,3]}>reset</button>
	innerWidth: {innerWidth}
	<div id="nrs">
		{#each nrs as nr (nr)}
		<div class="nr"
			 in:fly="{{x, y}}"
			 >
			{nr}
		</div>
		{/each}
	</div>
</div>

<style>
	#page {
		width: 100%;
		height: 100%;
		padding: 2rem;
		background: lightgrey;
	}
	#nrs {
		display: flex;
		align-items: flex-start;
		flex-wrap: wrap;
		gap: .5rem;
	}
	.nr {
		width: 4rem;
		height: 4rem;
		display: grid;
		place-content: center;
		background: black;
		color: white;
	}
	:global(body) {
		padding: 0;
	}
	:global(*) {
		box-sizing: border-box;
	}
</style>
英文:

One way would be to watch the window width via the innerWidth binding (tutorial) and set x and y accordingly

REPL

&lt;script&gt;
import {fly} from &#39;svelte/transition&#39;
let innerWidth
const threshold = 640
$: x = innerWidth &gt;= threshold ? -100 : 0
$: y = innerWidth &lt; threshold ? -100 : 0
let nrs = [0,1,2,3,4,5,6,7]
function add() {
nrs = [...nrs, nrs.length] 
}
&lt;/script&gt;
&lt;svelte:window bind:innerWidth /&gt;
&lt;div id=&quot;page&quot;&gt;
&lt;button on:click={add}&gt;add one&lt;/button&gt;
&lt;button on:click={() =&gt; nrs = [0,1,2,3]}&gt;reset&lt;/button&gt;
innerWidth: {innerWidth}
&lt;div id=&quot;nrs&quot;&gt;
{#each nrs as nr (nr)}
&lt;div class=&quot;nr&quot;
in:fly=&quot;{{x, y}}&quot;
&gt;
{nr}
&lt;/div&gt;
{/each}
&lt;/div&gt;
&lt;/div&gt;
&lt;style&gt;
#page {
width: 100%;
height: 100%;
padding: 2rem;
background: lightgrey;
}
#nrs {
display: flex;
align-items: flex-start;
flex-wrap: wrap;
gap: .5rem;
}
.nr {
width: 4rem;
height: 4rem;
display: grid;
place-content: center;
background: black;
color: white;
}
:global(body) {
padding: 0;
}
:global(*) {
box-sizing: border-box;
}
&lt;/style&gt;

huangapple
  • 本文由 发表于 2023年6月19日 18:13:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76505639.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定