让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
// )
// )
}
}
增加一个外发光效果代码
//
// JoinVipCard2.swift
// mc skin
//
// Created by martin on 2025/5/22.
// Copyright © 2025 edgewise. All rights reserved.
//
import SwiftUI
struct JoinVipCard2: View {
@Environment(\.colorScheme) var colorScheme
@State private var isGlowing = false
var body: some View {
ZStack{
VStack(alignment: .leading, spacing: 15) {
// 钻石闪烁效果
HStack {
Spacer()
Text("✨💎✨")
.font(.system(size: 12))
.opacity(0.8)
.scaleEffect(1.0)
.animation(
Animation.easeInOut(duration: 2)
.repeatForever(autoreverses: true),
value: UUID()
)
}
// // 用户信息
// HStack {
// Circle()
// .fill(Color.gray.opacity(0.3))
// .frame(width: 40, height: 40)
//
// VStack(alignment: .leading) {
// Text("CrystalKnight")
// .font(.system(size: 12, weight: .bold))
// .foregroundColor(.green)
//
// Text("10分钟前")
// .font(.system(size: 8))
// .foregroundColor(.gray)
// }
// }
// 内容
VStack(alignment: .leading, spacing: 8) {
Text("💎 钻石VIP闪亮登场!")
.font(.system(size: 10, weight: .bold))
VStack(alignment: .leading, spacing: 4) {
Text("⚡ 无限下载次数")
Text("🎨 AI皮肤定制服务")
Text("🌈 专属钻石光效")
Text("🎪 优先客服支持")
}
.font(.system(size: 10))
}
.foregroundStyle(.white)
// 统计信息
HStack(spacing: 20) {
HStack(spacing: 5) {
Text("💎")
Text("钻石特权")
}
HStack(spacing: 5) {
Text("⚡")
Text("无限制访问")
}
}
.font(.system(size: 8))
.foregroundColor(.gray)
}
}
.frame(width:320, height:160)
.padding(20)
.background(
// LinearGradient(
// gradient: Gradient(colors: [
// colorScheme == .dark ? Color(hex: "FF8C00") : Color(hex: "FFA500"),
// colorScheme == .dark ? Color(hex: "FFA500") : Color(hex: "FFD700"),
// colorScheme == .dark ? Color(hex: "FFD700") : Color(hex: "FFFF00")
// ]),
// startPoint: .topLeading,
// endPoint: .bottomTrailing
// )
)
.cornerRadius(12)
.overlay(
RoundedRectangle(cornerRadius: 12)
.stroke(Color(hex: "ffd400"), lineWidth: 3)
)
.shadow(
color: Color(hex: "ffd400").opacity(isGlowing ? 0.8 : 0.3),
radius: isGlowing ? 20 : 10,
x: 0,
y: 0
)
.onAppear {
// 创建1Hz的定时器
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
withAnimation(.easeInOut(duration: 0.5)) {
isGlowing.toggle()
}
}
}
}
}
// 颜色扩展
extension Color {
init(hex: String) {
let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
var int: UInt64 = 0
Scanner(string: hex).scanHexInt64(&int)
let a, r, g, b: UInt64
switch hex.count {
case 3: // RGB (12-bit)
(a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
case 6: // RGB (24-bit)
(a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
case 8: // ARGB (32-bit)
(a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
default:
(a, r, g, b) = (1, 1, 1, 0)
}
self.init(
.sRGB,
red: Double(r) / 255,
green: Double(g) / 255,
blue: Double(b) / 255,
opacity: Double(a) / 255
)
}
}
struct JoinVipCard2_Previews: PreviewProvider {
static var previews: some View {
Group {
JoinVipCard2()
.preferredColorScheme(.light)
.previewDisplayName("Light Mode")
JoinVipCard2()
.preferredColorScheme(.dark)
.previewDisplayName("Dark Mode")
}
.padding()
// .background(.black)
}
}