swiftui实现vip card的样式方案
让claude生成一些样式参考, 让后让它转换为swiftui 代码如下。这个是claude3.7给的方案,html转换到swiftui还原度没那么好,今天出了claude4, 可能效果更好。
代码如下:
//
// JoinVipCard.swift
// mc skin
//
// Created by martin on 2025/5/22.
// Copyright © 2025 edgewise. All rights reserved.
//
import SwiftUI
// MARK: - VIP卡片主组件
struct VIPFeedCard: View {
let vipType: VIPType
let username: String
let timeAgo: String
let avatarURL: String?
var body: some View {
VStack(spacing: 0) {
switch vipType {
case .flame:
FlameVIPCard(username: username, timeAgo: timeAgo, avatarURL: avatarURL)
case .lava:
LavaVIPCard(username: username, timeAgo: timeAgo, avatarURL: avatarURL)
case .gold:
GoldVIPCard(username: username, timeAgo: timeAgo, avatarURL: avatarURL)
case .rainbow:
RainbowVIPCard(username: username, timeAgo: timeAgo, avatarURL: avatarURL)
}
}
.background(Color.black.opacity(0.1))
.cornerRadius(8)
.padding(.horizontal, 16)
.padding(.vertical, 8)
}
}
// MARK: - VIP类型枚举
enum VIPType {
case flame // 烈焰VIP
case lava // 熔岩VIP
case gold // 黄金VIP
case rainbow // 彩虹VIP
}
// MARK: - 烈焰VIP卡片
struct FlameVIPCard: View {
let username: String
let timeAgo: String
let avatarURL: String?
@State private var glowIntensity: Double = 0.5
@State private var shimmerOffset: CGFloat = -200
var body: some View {
ZStack {
// 主背景渐变
LinearGradient(
colors: [
Color(red: 1.0, green: 0.55, blue: 0.0),
Color(red: 1.0, green: 0.65, blue: 0.0),
Color(red: 1.0, green: 0.5, blue: 0.0)
],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
// 闪光扫过效果
LinearGradient(
colors: [
Color.clear,
Color.white.opacity(0.3),
Color.clear
],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
.offset(x: shimmerOffset)
.animation(
Animation.linear(duration: 2)
.repeatForever(autoreverses: false),
value: shimmerOffset
)
VStack(alignment: .leading, spacing: 12) {
// 用户信息行
HStack {
// 头像
AsyncImage(url: URL(string: avatarURL ?? "")) { image in
image
.resizable()
.interpolation(.none) // 像素风格
} placeholder: {
Rectangle()
.fill(Color.gray.opacity(0.6))
}
.frame(width: 40, height: 40)
.border(Color.gray.opacity(0.8), width: 1)
VStack(alignment: .leading, spacing: 2) {
HStack {
Text(username)
.font(.custom("Menlo", size: 10))
.foregroundColor(.green)
Text("🔥 烈焰VIP")
.font(.custom("Menlo", size: 7))
.foregroundColor(.white)
.padding(.horizontal, 6)
.padding(.vertical, 2)
.background(Color(red: 1.0, green: 0.27, blue: 0.0))
.border(Color(red: 1.0, green: 0.15, blue: 0.0), width: 1)
}
Text(timeAgo)
.font(.custom("Menlo", size: 6))
.foregroundColor(.gray)
}
Spacer()
}
// 内容文本
VStack(alignment: .leading, spacing: 6) {
Text("🔥 恭喜开通烈焰VIP会员!")
.font(.custom("Menlo", size: 9))
.fontWeight(.bold)
.foregroundColor(.black)
VStack(alignment: .leading, spacing: 3) {
Text("✨ 解锁全部高级皮肤库")
Text("🧡 专属烈焰标识闪耀登场")
Text("🚀 优先体验最新功能")
Text("🎁 每月赠送专属皮肤礼包")
}
.font(.custom("Menlo", size: 8))
.foregroundColor(.black)
}
// 统计信息
HStack(spacing: 15) {
Text("🔥 烈焰特权已激活")
Text("🌟 等级提升至 LV.MAX")
}
.font(.custom("Menlo", size: 7))
.foregroundColor(.black.opacity(0.8))
}
.padding(16)
// 浮动粒子效果
ForEach(0..<3, id: \.self) { index in
ParticleView(delay: Double(index))
}
}
.border(Color(red: 1.0, green: 0.4, blue: 0.0), width: 2)
.shadow(color: Color(red: 1.0, green: 0.55, blue: 0.0).opacity(glowIntensity), radius: 10)
.onAppear {
// 启动动画
withAnimation(Animation.easeInOut(duration: 3).repeatForever()) {
glowIntensity = 1.0
}
withAnimation(Animation.linear(duration: 2).repeatForever(autoreverses: false)) {
shimmerOffset = 200
}
}
}
}
// MARK: - 熔岩VIP卡片
struct LavaVIPCard: View {
let username: String
let timeAgo: String
let avatarURL: String?
@State private var glowPulse: Double = 0.7
var body: some View {
ZStack {
// 熔岩渐变背景
LinearGradient(
colors: [
Color(red: 0.8, green: 0.33, blue: 0.0),
Color(red: 1.0, green: 0.55, blue: 0.0),
Color(red: 1.0, green: 0.7, blue: 0.28)
],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
VStack(alignment: .leading, spacing: 12) {
// 用户信息行
HStack {
AsyncImage(url: URL(string: avatarURL ?? "")) { image in
image
.resizable()
.interpolation(.none)
} placeholder: {
Rectangle().fill(Color.gray.opacity(0.6))
}
.frame(width: 40, height: 40)
.border(Color.gray.opacity(0.8), width: 1)
VStack(alignment: .leading, spacing: 2) {
Text(username)
.font(.custom("Menlo", size: 10))
.foregroundColor(.green)
Text(timeAgo)
.font(.custom("Menlo", size: 6))
.foregroundColor(.gray)
}
Spacer()
}
// 内容
VStack(alignment: .leading, spacing: 6) {
HStack {
Text("🧡")
.font(.custom("Menlo", size: 10))
.scaleEffect(1.2)
.animation(
Animation.easeInOut(duration: 1)
.repeatForever(autoreverses: true),
value: glowPulse
)
Text("熔岩之力!开通熔岩VIP会员!")
.font(.custom("Menlo", size: 9))
.fontWeight(.bold)
.foregroundColor(.white)
}
VStack(alignment: .leading, spacing: 3) {
Text("🌋 专属熔岩光环效果")
Text("🎭 解锁传奇级皮肤收藏")
Text("🧡 加入熔岩VIP专属讨论群")
Text("🏆 参与熔岩VIP专属活动资格")
}
.font(.custom("Menlo", size: 8))
.foregroundColor(.white)
}
// 统计信息
HStack(spacing: 15) {
Text("🌋 999+ 皮肤已解锁")
Text("🔥 熔岩圈子邀请中")
}
.font(.custom("Menlo", size: 7))
.foregroundColor(.white.opacity(0.9))
}
.padding(16)
}
.border(Color(red: 1.0, green: 0.4, blue: 0.0), width: 2)
.shadow(color: Color(red: 1.0, green: 0.55, blue: 0.0).opacity(glowPulse), radius: 15)
.onAppear {
withAnimation(Animation.easeInOut(duration: 2).repeatForever(autoreverses: true)) {
glowPulse = 1.0
}
}
}
}
// MARK: - 黄金VIP卡片
struct GoldVIPCard: View {
let username: String
let timeAgo: String
let avatarURL: String?
@State private var sparkleOpacity: Double = 0.5
@State private var sparkleScale: CGFloat = 1.0
var body: some View {
ZStack {
// 黄金渐变背景
LinearGradient(
colors: [
Color(red: 0.72, green: 0.53, blue: 0.04),
Color(red: 1.0, green: 0.84, blue: 0.0),
Color(red: 1.0, green: 1.0, blue: 0.6)
],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
VStack(alignment: .leading, spacing: 12) {
// 用户信息行
HStack {
AsyncImage(url: URL(string: avatarURL ?? "")) { image in
image
.resizable()
.interpolation(.none)
} placeholder: {
Rectangle().fill(Color.gray.opacity(0.6))
}
.frame(width: 40, height: 40)
.border(Color.gray.opacity(0.8), width: 1)
VStack(alignment: .leading, spacing: 2) {
Text(username)
.font(.custom("Menlo", size: 10))
.foregroundColor(.green)
Text(timeAgo)
.font(.custom("Menlo", size: 6))
.foregroundColor(.gray)
}
Spacer()
// 闪电装饰
Text("⚡💎⚡")
.font(.custom("Menlo", size: 8))
.foregroundColor(.yellow)
.opacity(sparkleOpacity)
.scaleEffect(sparkleScale)
}
// 内容
VStack(alignment: .leading, spacing: 6) {
Text("⚡ 黄金VIP闪耀登场!")
.font(.custom("Menlo", size: 9))
.fontWeight(.bold)
.foregroundColor(.black)
VStack(alignment: .leading, spacing: 3) {
Text("⚡ 无限下载次数")
Text("🎨 AI皮肤定制服务")
Text("💛 专属黄金光效")
Text("🎪 优先客服支持")
}
.font(.custom("Menlo", size: 8))
.foregroundColor(.black)
}
// 统计信息
HStack(spacing: 15) {
Text("💛 黄金特权")
Text("⚡ 无限制访问")
}
.font(.custom("Menlo", size: 7))
.foregroundColor(.black.opacity(0.8))
}
.padding(16)
}
.border(Color(red: 1.0, green: 0.76, blue: 0.03), width: 2)
.shadow(color: Color.yellow.opacity(0.8), radius: 10)
.onAppear {
withAnimation(Animation.easeInOut(duration: 2).repeatForever(autoreverses: true)) {
sparkleOpacity = 1.0
sparkleScale = 1.2
}
}
}
}
// MARK: - 彩虹VIP卡片
struct RainbowVIPCard: View {
let username: String
let timeAgo: String
let avatarURL: String?
@State private var rainbowOffset: CGFloat = 0
var body: some View {
ZStack {
// 彩虹流动背景
LinearGradient(
colors: [
.red, .orange, .yellow, .green, .blue, .purple
],
startPoint: .leading,
endPoint: .trailing
)
.offset(x: rainbowOffset)
.animation(
Animation.linear(duration: 3)
.repeatForever(autoreverses: false),
value: rainbowOffset
)
VStack(alignment: .leading, spacing: 12) {
// 用户信息行
HStack {
AsyncImage(url: URL(string: avatarURL ?? "")) { image in
image
.resizable()
.interpolation(.none)
} placeholder: {
Rectangle().fill(Color.gray.opacity(0.6))
}
.frame(width: 40, height: 40)
.border(Color.gray.opacity(0.8), width: 1)
VStack(alignment: .leading, spacing: 2) {
HStack {
Text(username)
.font(.custom("Menlo", size: 10))
.foregroundColor(.green)
Text("限量版")
.font(.custom("Menlo", size: 6))
.foregroundColor(.white)
.padding(.horizontal, 4)
.padding(.vertical, 1)
.background(
LinearGradient(
colors: [.red, .pink],
startPoint: .leading,
endPoint: .trailing
)
)
}
Text(timeAgo)
.font(.custom("Menlo", size: 6))
.foregroundColor(.gray)
}
Spacer()
}
// 内容
VStack(alignment: .leading, spacing: 6) {
Text("🌈 彩虹至尊VIP震撼开启!")
.font(.custom("Menlo", size: 9))
.fontWeight(.bold)
.foregroundColor(.white)
.shadow(color: .black.opacity(0.5), radius: 1)
VStack(alignment: .leading, spacing: 3) {
Text("🎪 独家彩虹皮肤系列")
Text("🎊 专属彩虹称号")
Text("🎁 限时彩虹礼包")
Text("🌟 终身VIP特权")
}
.font(.custom("Menlo", size: 8))
.foregroundColor(.white)
.shadow(color: .black.opacity(0.3), radius: 1)
}
// 统计信息
HStack(spacing: 15) {
Text("🌈 彩虹效果")
Text("🎉 限量发售")
}
.font(.custom("Menlo", size: 7))
.foregroundColor(.white.opacity(0.9))
}
.padding(16)
}
.border(Color.white, width: 2)
.shadow(color: .purple.opacity(0.6), radius: 15)
.onAppear {
withAnimation(Animation.linear(duration: 3).repeatForever(autoreverses: false)) {
rainbowOffset = 100
}
}
}
}
// MARK: - 粒子效果组件
struct ParticleView: View {
let delay: Double
@State private var yOffset: CGFloat = 0
@State private var opacity: Double = 0.7
@State private var rotation: Double = 0
var body: some View {
Rectangle()
.fill(Color.yellow)
.frame(width: 4, height: 4)
.opacity(opacity)
.offset(y: yOffset)
.rotationEffect(.degrees(rotation))
.position(
x: CGFloat.random(in: 50...250),
y: CGFloat.random(in: 50...150)
)
.onAppear {
withAnimation(
Animation.easeInOut(duration: 3)
.repeatForever(autoreverses: true)
.delay(delay)
) {
yOffset = -10
opacity = 1.0
rotation = 180
}
}
}
}
// MARK: - 预览和使用示例
struct VIPFeedCard_Previews: PreviewProvider {
static var previews: some View {
ScrollView {
VStack(spacing: 20) {
VIPFeedCard(
vipType: .flame,
username: "DragonSlayer_2024",
timeAgo: "刚刚",
avatarURL: nil
)
VIPFeedCard(
vipType: .lava,
username: "MasterBuilder",
timeAgo: "5分钟前",
avatarURL: nil
)
VIPFeedCard(
vipType: .gold,
username: "CrystalKnight",
timeAgo: "10分钟前",
avatarURL: nil
)
VIPFeedCard(
vipType: .rainbow,
username: "RainbowWarrior",
timeAgo: "15分钟前",
avatarURL: nil
)
}
.padding()
}
// .background(
// LinearGradient(
// colors: [
// Color(red: 0.1, green: 0.1, blue: 0.18),
// Color(red: 0.09, green: 0.13, blue: 0.24)
// ],
// startPoint: .top,
// endPoint: .bottom
// )
// )
}
}