feat: tiltcard component
This commit is contained in:
		
							parent
							
								
									b7f951b9c7
								
							
						
					
					
						commit
						2e7009fef2
					
				
					 1 changed files with 74 additions and 0 deletions
				
			
		
							
								
								
									
										74
									
								
								src/routes/tiltcard.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/routes/tiltcard.svelte
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,74 @@
 | 
				
			||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
						export let imageSrc: string;
 | 
				
			||||||
 | 
						export let imageAlt: string = 'Card image';
 | 
				
			||||||
 | 
						export let width: string = '300px';
 | 
				
			||||||
 | 
						export let height: string = '400px';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						let cardElement: HTMLDivElement;
 | 
				
			||||||
 | 
						let rotateX = 0;
 | 
				
			||||||
 | 
						let rotateY = 0;
 | 
				
			||||||
 | 
						let isHovered = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Derived shadow offsets
 | 
				
			||||||
 | 
						let shadowX = 0;
 | 
				
			||||||
 | 
						let shadowY = 0;
 | 
				
			||||||
 | 
						let shadowBlur = 20;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function handleMouseMove(event: MouseEvent) {
 | 
				
			||||||
 | 
							if (!cardElement) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const rect = cardElement.getBoundingClientRect();
 | 
				
			||||||
 | 
							const x = event.clientX - rect.left;
 | 
				
			||||||
 | 
							const y = event.clientY - rect.top;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const centerX = rect.width / 2;
 | 
				
			||||||
 | 
							const centerY = rect.height / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Calculate rotation based on cursor position (max tilt of 10 degrees)
 | 
				
			||||||
 | 
							rotateY = ((x - centerX) / centerX) * 10 * 2;
 | 
				
			||||||
 | 
							rotateX = ((centerY - y) / centerY) * 10 * 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Make shadow move opposite to tilt for a realistic lighting effect
 | 
				
			||||||
 | 
							shadowX = -rotateY * 0.7; // exaggerate slightly
 | 
				
			||||||
 | 
							shadowY = rotateX * 0.7;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function handleMouseEnter() {
 | 
				
			||||||
 | 
							isHovered = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function handleMouseLeave() {
 | 
				
			||||||
 | 
							isHovered = false;
 | 
				
			||||||
 | 
							rotateX = 0;
 | 
				
			||||||
 | 
							rotateY = 0;
 | 
				
			||||||
 | 
							shadowX = 0;
 | 
				
			||||||
 | 
							shadowY = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div
 | 
				
			||||||
 | 
						bind:this={cardElement}
 | 
				
			||||||
 | 
						class="cursor-pointer"
 | 
				
			||||||
 | 
						class:scale-[1.03]={isHovered}
 | 
				
			||||||
 | 
						style="
 | 
				
			||||||
 | 
							width: {width};
 | 
				
			||||||
 | 
							height: {height};
 | 
				
			||||||
 | 
							perspective: 1000px;
 | 
				
			||||||
 | 
							filter: drop-shadow({shadowX}px {shadowY}px 0px rgba(0, 0, 0, 0.5));
 | 
				
			||||||
 | 
						"
 | 
				
			||||||
 | 
						on:mousemove={handleMouseMove}
 | 
				
			||||||
 | 
						on:mouseenter={handleMouseEnter}
 | 
				
			||||||
 | 
						on:mouseleave={handleMouseLeave}
 | 
				
			||||||
 | 
						role="img"
 | 
				
			||||||
 | 
						aria-label={imageAlt}
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
						<img
 | 
				
			||||||
 | 
							src={imageSrc}
 | 
				
			||||||
 | 
							alt={imageAlt}
 | 
				
			||||||
 | 
							class="h-full w-full rounded-xl object-cover transition-transform duration-100 ease-out"
 | 
				
			||||||
 | 
							style="
 | 
				
			||||||
 | 
								transform: rotateX({rotateX}deg) rotateY({rotateY}deg);
 | 
				
			||||||
 | 
								transform-style: preserve-3d;
 | 
				
			||||||
 | 
							"
 | 
				
			||||||
 | 
						/>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue