react-native-blur-vibe 0.1.11 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -33,7 +33,7 @@ class BlurVibeView(context: Context) : ReactViewGroup(context) {
33
33
 
34
34
  init {
35
35
  setWillNotDraw(false)
36
- super.setBackgroundColor(Color.TRANSPARENT)
36
+ // DO NOT call setBackgroundColor — see BlurVibeViewApi31 for explanation.
37
37
  }
38
38
 
39
39
  // ── Lifecycle ──────────────────────────────────────────────────────────────
@@ -137,8 +137,10 @@ class BlurVibeView(context: Context) : ReactViewGroup(context) {
137
137
  // ── Helpers ────────────────────────────────────────────────────────────────
138
138
 
139
139
  private fun mapBlurAmount(amount: Float): Float {
140
+ // Linear 0→1, 100→25 (RenderScript max kernel is 25)
141
+ // With 3 blur rounds this gives equivalent spread to Api31's 120px single-pass
140
142
  val t = amount.coerceIn(0f, 100f) / 100f
141
- return t * t * 25f
143
+ return (1f + t * 24f) // 1–25 linear, rounds=3 gives wide spread
142
144
  }
143
145
 
144
146
  private fun findBlurRoot(): ViewGroup? {
@@ -117,7 +117,12 @@ class BlurVibeViewApi31(context: Context) : ReactViewGroup(context) {
117
117
 
118
118
  init {
119
119
  setWillNotDraw(false)
120
- super.setBackgroundColor(Color.TRANSPARENT)
120
+ // DO NOT call setBackgroundColor here.
121
+ // ReactViewGroup manages its own ReactViewBackgroundDrawable which handles
122
+ // all RN style props: borderRadius, borderColor, borderWidth, opacity,
123
+ // backgroundColor, shadow, elevation etc.
124
+ // Calling super.setBackgroundColor() replaces that drawable with a plain
125
+ // ColorDrawable — destroying all style prop handling.
121
126
  }
122
127
 
123
128
  // ── Lifecycle ──────────────────────────────────────────────────────────────
@@ -219,18 +224,24 @@ class BlurVibeViewApi31(context: Context) : ReactViewGroup(context) {
219
224
  nodeCanvas.drawBitmap(bitmap, 0f, 0f, null)
220
225
  renderNode.endRecording()
221
226
 
222
- // ④ Apply GPU blur + tint as a chained RenderEffect (single GPU pass)
223
- val radius = blurRadiusFromAmount(blurAmount)
224
- val blurEffect = RenderEffect.createBlurEffect(radius, radius, Shader.TileMode.MIRROR)
227
+ // ④ Apply GPU blur + tint as chained RenderEffects
228
+ // Double-pass blur: two Gaussian passes = wider spread kernel
229
+ // Equivalent to sqrt(2) wider sigma — gives frosted-glass light diffusion
230
+ // CLAMP tile mode: no edge reflection artifacts
231
+ val radius = blurRadiusFromAmount(blurAmount)
232
+ val pass1 = RenderEffect.createBlurEffect(radius, radius, Shader.TileMode.CLAMP)
233
+ val pass2 = RenderEffect.createBlurEffect(radius * 0.5f, radius * 0.5f, Shader.TileMode.CLAMP)
234
+ val doubleBlur = RenderEffect.createChainEffect(pass2, pass1) // pass1 first, then pass2
235
+
225
236
  renderNode.setRenderEffect(
226
237
  if (Color.alpha(overlayColor) > 0) {
227
238
  RenderEffect.createChainEffect(
228
239
  RenderEffect.createColorFilterEffect(
229
240
  BlendModeColorFilter(overlayColor, BlendMode.SRC_ATOP)
230
241
  ),
231
- blurEffect
242
+ doubleBlur
232
243
  )
233
- } else blurEffect
244
+ } else doubleBlur
234
245
  )
235
246
 
236
247
  invalidate()
@@ -394,8 +405,16 @@ class BlurVibeViewApi31(context: Context) : ReactViewGroup(context) {
394
405
  }
395
406
  }
396
407
 
397
- private fun blurRadiusFromAmount(amount: Float): Float =
398
- ((amount / 100f).let { it * it } * 25f).coerceIn(1f, 25f)
408
+ private fun blurRadiusFromAmount(amount: Float): Float {
409
+ // Linear mapping: 0→1px, 10→13px, 25→31px, 50→61px, 75→91px, 100→120px
410
+ // These values match CSS backdrop-filter feel:
411
+ // blurAmount=10 ≈ backdrop-blur-sm (4px CSS = ~13px GPU after downsample)
412
+ // blurAmount=25 ≈ backdrop-blur-md (12px CSS ≈ 31px GPU)
413
+ // blurAmount=50 ≈ backdrop-blur-xl (24px CSS ≈ 61px GPU)
414
+ // blurAmount=100 ≈ backdrop-blur-3xl (64px CSS = fully frosted glass)
415
+ val t = amount.coerceIn(0f, 100f) / 100f
416
+ return (1f + t * 119f) // 1–120 linear
417
+ }
399
418
 
400
419
  private fun findBlurRoot(): ViewGroup? {
401
420
  var p = parent
@@ -33,9 +33,17 @@ internal class LegacyBlurController(
33
33
  ) {
34
34
 
35
35
  companion object {
36
- private const val DOWNSAMPLE_FACTOR = 4f
37
- private const val BLUR_RADIUS = 8f
38
- private const val BLUR_ROUNDS = 2
36
+ // DOWNSAMPLE_FACTOR = 2: capture at 1/4 pixels (less than before).
37
+ // Less downsampling = higher quality capture = crisper blur result.
38
+ // The blur hides pixel detail so 1/4 is the sweet spot.
39
+ private const val DOWNSAMPLE_FACTOR = 2f
40
+
41
+ // Default radius when blurAmount maps here.
42
+ // The actual radius per frame comes from view.blurRadius set by setBlurAmount().
43
+ private const val BLUR_RADIUS = 25f // max RenderScript kernel
44
+
45
+ // 3 rounds: more passes = wider spread = true frosted glass feel
46
+ private const val BLUR_ROUNDS = 3
39
47
  }
40
48
 
41
49
  // ── Bitmap pool ────────────────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-blur-vibe",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "React Native package implementing Blur View in iOS and Android",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/module/index.js",