如何解决使用 CSS 在图像周围环绕文本并使其表现得像背景图像
我正在使用 shape-outside 为网站提供一种“杂志”的感觉。每个页面都有一个人的新图像,文字环绕着那个人。外部造型完美而简单!唯一的问题是我不知道如何制作它,因此一列(左)中的文本设置高度而不是图像(右)。
以这个例子为例:
https://jsfiddle.net/kvzmw0sy/22/
或者原始代码
HTML:
<div class="container">
<img class="image" src="https://res.cloudinary.com/dq6tqnvbh/image/upload/v1552834755/5a366dd97df550.5130252915135165055159.png">
<div class="text">
Lorem ipsum dolor sit amet,consectetur adipiscing elit. Integer vestibulum rhoncus orci nec iaculis. Cras tempor aliquam sem,id accumsan nibh mollis nec. Sed eget dui pulvinar,iaculis nibh vitae,molestie metus. Aliquam tortor leo,laoreet a felis quis,ultricies dignissim mauris. Etiam quis consectetur nibh. In soDales et ex at malesuada. Phasellus et arcu eleifend,interdum ex eu,bibendum magna.
</div>
</div>
<div class="footer">
</div>
CSS:
.image {
float: right;
max-width: 200px;
height: auto;
shape-outside: url(https://res.cloudinary.com/dq6tqnvbh/image/upload/v1552834755/5a366dd97df550.5130252915135165055159.png);
}
.footer {
width:100%;
height:50px;
border: 2px solid green
}
我得到的是这个:
但是,我想要的是这个(看看图像如何在页脚后面):
基本上我希望它像背景图像一样工作。
我尝试了绝对位置,但它破坏了文本换行。我不认为我可以用背景图片来做到这一点。所以到目前为止我唯一的解决方案是使用 JS 获取左侧的高度并将其应用到带有 overflow:hidden
的容器中,我真的很想避免这种情况。
解决方法
应用于容器的新 overflow:clip
将完成这项工作
import SwiftUI
import CoreData
extension User{
//You need a variable you can access with your section "title" or "name"
//This defines what you want to find in common
@objc
var firstLetterLastName: String{
lastName?.first?.description ?? ""
}
}
class UserListViewModel: NSObject,ObservableObject {
//This uses the PersistenceController from the standard Xcode setup
let persistenceController = PersistenceController.previewAware()
//This contains your sections and objects/values
@Published var fetchedResultsController: NSFetchedResultsController<User>?
override init() {
super.init()
setupController()
}
func setupController() {
do{
//sectionNameKeyPath is where you tell the controller where to find the variable that you want to group
fetchedResultsController = try retrieveFetchedController(sortDescriptors: nil,predicate: nil,sectionNameKeyPath: #keyPath(User.firstLetterLastName))
}catch{
print(error)
}
}
//I put this here so sample a delete. It works a little different
func deleteObject(object: User) {
persistenceController.container.viewContext.delete(object)
save()
}
func addSample() {
let newUser = User(context: persistenceController.container.viewContext)
newUser.firstName = ["Peter","Emily","Grace","Ruby","Chloe","James"].randomElement()!
newUser.lastName = ["Smith","Hughes","Scott","Brown","Turner","Simpson","Blue"].randomElement()!
save()
}
func save() {
do {
if persistenceController.container.viewContext.hasChanges{
try persistenceController.container.viewContext.save()
}else{
}
} catch {
print(error)
}
}
}
//Most of the extensions mostly comes from the CoreData Programming Guide
//https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html#//apple_ref/doc/uid/TP40001075-CH8-SW1
extension UserListViewModel: NSFetchedResultsControllerDelegate{
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
fetchedResultsController = fetchedResultsController
}
}
//MARK: FetchedResultsController setup
extension UserListViewModel{
func retrieveFetchedController(sortDescriptors: [NSSortDescriptor]?,predicate: NSPredicate?,sectionNameKeyPath: String) throws -> NSFetchedResultsController<User> {
return try initFetchedResultsController(sortDescriptors: sortDescriptors,predicate: predicate,sectionNameKeyPath: sectionNameKeyPath)
}
private func initFetchedResultsController(sortDescriptors: [NSSortDescriptor]?,sectionNameKeyPath: String) throws -> NSFetchedResultsController<User> {
fetchedResultsController = getFetchedResultsController(sortDescriptors: sortDescriptors,sectionNameKeyPath: sectionNameKeyPath)
fetchedResultsController!.delegate = self
do {
try fetchedResultsController!.performFetch()
return fetchedResultsController!
} catch {
print( error)
throw error
}
}
func getFetchedResultsController(sortDescriptors: [NSSortDescriptor]?,sectionNameKeyPath: String) -> NSFetchedResultsController<User> {
return NSFetchedResultsController(fetchRequest: getEntityFetchRequest(sortDescriptors: sortDescriptors,predicate: predicate),managedObjectContext: persistenceController.container.viewContext,sectionNameKeyPath: sectionNameKeyPath,cacheName: nil)
}
private func getEntityFetchRequest(sortDescriptors: [NSSortDescriptor]?,predicate: NSPredicate?) -> NSFetchRequest<User>
{
let fetchRequest: NSFetchRequest<User> = User.fetchRequest()
fetchRequest.includesPendingChanges = false
//This part helps with efficiency.
//Maybe a little lazy loading SwiftUI does not slow down
//as much with large data sets when I use this setup
fetchRequest.fetchBatchSize = 20
if sortDescriptors != nil{
fetchRequest.sortDescriptors = sortDescriptors
}else{
fetchRequest.sortDescriptors = [NSSortDescriptor(key: #keyPath(User.lastName),ascending: true)]
}
if predicate != nil{
fetchRequest.predicate = predicate
}
return fetchRequest
}
}
//Here is a sample View
struct UserListView: View {
@StateObject var vm: UserListViewModel = UserListViewModel()
var body: some View {
NavigationView{
if vm.fetchedResultsController?.sections != nil{
List{
ForEach(vm.fetchedResultsController!.sections!.indices){idx in
let section = vm.fetchedResultsController!.sections![idx]
UserListSectionView(objects: section.objects as? [User] ?? [],sectionName: section.name).environmentObject(vm)
}
}.toolbar(content: {
ToolbarItem(placement: .navigation,content: {
Button(action: {
vm.addSample()
},label: {
Image(systemName: "plus")
})
})
})
}else{
Image(systemName: "empty")
}
}
}
}
struct UserListSectionView: View {
@EnvironmentObject var vm: UserListViewModel
let objects: [User]
var sectionName: String
var body: some View {
Section(header: Text(sectionName),content: {
ForEach(objects,id: \.self){obj in
let user = obj as User
HStack{
Text(user.firstName.bound)
Text(user.lastName.bound)
}
.listRowBackground(Color(UIColor.systemBackground))
}.onDelete(perform: deleteItems)
})
}
//Here is the difference with deleting.
//The IndexSet is for the section.objects not all the users
private func deleteItems(offsets: IndexSet) {
withAnimation {
let objs = offsets.map { objects[$0] }
for obj in objs{
vm.deleteObject(object: obj)
}
}
}
}
struct UserListView_Previews: PreviewProvider {
static var previews: some View {
NavigationView{
UserListView()
}
}
}
.image {
float: right;
max-width: 200px;
height: auto;
shape-outside: url(https://res.cloudinary.com/dq6tqnvbh/image/upload/v1552834755/5a366dd97df550.5130252915135165055159.png);
}
.footer {
width: 100%;
height: 50px;
border: 2px solid green
}
/* .text{
shape-outside: url(https://www.pngjoy.com/pngl/69/1501951_stars-star-images-birthday-png-hd-png-download.png);
} */
.container {
overflow: clip;
}
为了获得更好的支持,您可以改用剪辑路径:
<div class="container">
<img class="image" src="https://res.cloudinary.com/dq6tqnvbh/image/upload/v1552834755/5a366dd97df550.5130252915135165055159.png">
<div class="text">
Lorem ipsum dolor sit amet,consectetur adipiscing elit. Integer vestibulum rhoncus orci nec iaculis. Cras tempor aliquam sem,id accumsan nibh mollis nec. Sed eget dui pulvinar,iaculis nibh vitae,molestie metus. Aliquam tortor leo,laoreet a felis
quis,ultricies dignissim mauris. Etiam quis consectetur nibh. In sodales et ex at malesuada. Phasellus et arcu eleifend,interdum ex eu,bibendum magna.
</div>
</div>
<div class="footer">
</div>
.image {
float: right;
max-width: 200px;
height: auto;
shape-outside: url(https://res.cloudinary.com/dq6tqnvbh/image/upload/v1552834755/5a366dd97df550.5130252915135165055159.png);
}
.footer {
width: 100%;
height: 50px;
border: 2px solid green
}
.container {
clip-path: inset(0);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。