英文:
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:...
)
<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 '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 }}>
(If in/out animations are the same, you can just use transition:...
)
答案2
得分: 2
一种方法是通过内部宽度绑定(教程链接)来监视窗口宽度,并相应地设置 x
和 y
。
<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
<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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论