Я использую библиотеку VariableBlur в Swift, чтобы создать размытие над представлением моей коллекции под областью строки состояния как таковое:
Я пытаюсь понять, как сделать размытие темнее?
В библиотеке используется CIFilter
, но я не знаю, что изменить, чтобы сделать его темнее. Я уже пробовал изменить UIBlurEffect(style: .regular)
на .dark
, но это не имело никакого значения.
А значок color0
на ciGradientFilter
уже установлен на черный цвет. На самом деле, изменение его на красный или любой другой цвет не имеет никакого значения.
Существующий makeGradientImage
уже создает градиентное изображение, причем color0
установлен на черный цвет, как вы заметили. Существующий код использует это как маску, но вы можете отобразить это изображение в своем собственном CALayer
, который добавляется как родственный backdropLayer
.
open class VariableBlurUIView: UIVisualEffectView {
let darkLayer = CALayer()
public init(maxBlurRadius: CGFloat = 20, direction: VariableBlurDirection = .blurredTopClearBottom, startOffset: CGFloat = 0) {
super.init(effect: UIBlurEffect(style: .regular))
// ...
let gradientImage = makeGradientImage(startOffset: startOffset, direction: direction)
variableBlur.setValue(maxBlurRadius, forKey: "inputRadius")
variableBlur.setValue(gradientImage, forKey: "inputMaskImage")
variableBlur.setValue(true, forKey: "inputNormalizeEdges")
let backdropLayer = subviews.first?.layer
backdropLayer?.filters = [variableBlur]
darkLayer.contents = gradientImage
darkLayer.zPosition = -1
backdropLayer?.superLayer?.addSublayer(darkLayer)
for subview in subviews.dropFirst() {
subview.alpha = 0
}
}
open override func layoutSublayers(of layer: CALayer) {
darkLayer.frame = subviews.first?.layer.frame ?? .zero
}
// ...
}
Параллельное сравнение:
к сожалению, он все еще показывает внезапную прозрачную линию. В приложении «Фото» этой проблемы нет.
в конечном итоге эта линия перемещается на половину высоты. Сначала вы можете не увидеть линию, но если вы посмотрите на нее на белом фоне, я думаю, вы ее заметите. Это не видно на изображении, которое вы используете в своем ответе. Линия присутствует, даже если мы отключим размытие. Градиент является причиной проблемы. Интересно, могу ли я установить градиент так, чтобы он был более темным в первой трети и менее темным в дальнейшем?
@sudoExclamationExclamation Ну, это было бы darkLayer.locations = [0.0, 0.3333333]
, но я сомневаюсь, что это что-то изменит. Идея сделать этот слой родственным слоем состоит в том, чтобы на darkLayer
также влияло размытие, которое, как я ожидаю, удалит линию. Попробуйте использовать полностью черный слой вместо CAGradientLayer
. Оно должно быть размытым, но есть ли еще линия?
@sudoExclamationExclamation На самом деле мне вообще не нужно использовать CAGradientLayer
. Существующий метод makeGradientImage
уже создает градиент от черного к прозрачному. Просто покажите это обычным CALayer
! Я обновил ответ.
ваш способ использования существующего метода makeGradientImage
сработал хорошо! Вместо этого я также смог изменить значение color0
с black
на CIColor(color: UIColor.black.withAlphaComponent(0.7))
для более утонченного вида. Спасибо!
//import CoreImage
func applyVariableBlurAndDarken(to image: UIImage) -> UIImage? {
guard let ciImage = CIImage(image: image) else { return nil }
// Apply VariableBlur Filter
let variableBlurFilter = CIFilter(name: "CIMaskedVariableBlur")!
variableBlurFilter.setValue(ciImage, forKey: kCIInputImageKey)
variableBlurFilter.setValue(10.0, forKey: "inputRadius") // Adjust the blur radius as needed
guard let blurredImage = variableBlurFilter.outputImage else { return nil }
// Apply Color Controls to darken the image
let colorControlsFilter = CIFilter(name: "CIColorControls")!
colorControlsFilter.setValue(blurredImage, forKey: kCIInputImageKey)
colorControlsFilter.setValue(-0.5, forKey: kCIInputBrightnessKey) // Reduce brightness to darken
colorControlsFilter.setValue(1.2, forKey: kCIInputContrastKey) // Optional: increase contrast
guard let darkenedImage = colorControlsFilter.outputImage else { return nil }
// Render the final image
let context = CIContext()
guard let cgImage = context.createCGImage(darkenedImage, from: darkenedImage.extent) else { return nil }
return UIImage(cgImage: cgImage)
}
// Usage
if let image = UIImage(named: "your_image_name") {
let processedImage = applyVariableBlurAndDarken(to: image)
// Now you can use the processedImage
}
Это применение его к статическому изображению. Библиотека VariableBlurView
, которую я использую, позволяет в реальном времени размывать прокручиваемый UICollectionView. Знаешь, как я могу это сделать?
Привет, попробуйте решение ниже :)
/*To adjust the darkness of a real-time blur effect over a scrolling UICollectionView using the VariableBlurView*/
импортировать UIKit импортировать CoreImage импортировать VariableBlurView
класс DarkenedVariableBlurView: VariableBlurView {
override func applyBlurEffect() {
super.applyBlurEffect()
// Access the existing CIFilter used for blurring
guard let blurFilter = self.currentBlurFilter else { return }
// Create a CIColorControls filter to adjust brightness and contrast
let colorControlsFilter = CIFilter(name: "CIColorControls")!
colorControlsFilter.setValue(blurFilter.outputImage, forKey: kCIInputImageKey)
colorControlsFilter.setValue(-0.5, forKey: kCIInputBrightnessKey) // Darkening effect
colorControlsFilter.setValue(1.2, forKey: kCIInputContrastKey) // Increase contrast
// Apply the filter chain and update the view's content
if let darkenedOutput = colorControlsFilter.outputImage {
self.updateView(with: darkenedOutput)
}
}
private func updateView(with image: CIImage) {
let context = CIContext()
if let cgImage = context.createCGImage(image, from: image.extent) {
self.layer.contents = cgImage
}
}
}
/* Замените VariableBlurView на свой собственный DarkenedVariableBlurView: Используйте класс DarkenedVariableBlurView в представлении, которое перекрывает ваш UICollectionView.*/
//Если VariableBlurView уже обновляется в режиме реального времени по мере прокрутки представления коллекции, то ваш пользовательский фильтр должен применяться динамически без дополнительного кода. Если нет, убедитесь, что ваше представление обновлено в методе делегата ScrollViewDidScroll:
расширение YourViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if let blurView = yourCustomBlurView as? DarkenedVariableBlurView {
blurView.applyBlurEffect()
}
}
}
пожалуйста, попробуйте это :)
Разве это не будет крайне низкой производительностью, поскольку каждый раз при вызове scrollViewDidScroll
происходит переделка?
Знаете ли вы, почему на конце градиента внизу появляется внезапная прозрачная линия вместо гладкой? Это сложно показать, но более очевидно при прокрутке и когда контент под ним светлый. Например, с белым цветом это очень очевидно: i.imgur.com/dADDkLt.jpeg