MySlider.xaml.vb 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. Public Class MySlider
  2. '基础
  3. Public Uuid As Integer = GetUuid()
  4. Public Event Change(sender As Object, user As Boolean)
  5. Public Event PreviewChange(sender As Object, e As RouteEventArgs)
  6. '自定义属性
  7. Private _MaxValue As Integer = 100
  8. Public Property MaxValue As Integer
  9. Get
  10. Return _MaxValue
  11. End Get
  12. Set(value As Integer)
  13. If value = _MaxValue Then Exit Property
  14. _MaxValue = value
  15. RefreshWidth(Nothing, Nothing)
  16. End Set
  17. End Property
  18. Private ChangeByKey As Boolean = False
  19. Private _Value As Integer = 0
  20. Public Property Value As Integer
  21. Get
  22. Return _Value
  23. End Get
  24. Set(newValue As Integer)
  25. Try
  26. newValue = MathRange(newValue, 0, MaxValue)
  27. If _Value = newValue Then Exit Property
  28. '触发 Preview 事件,修改新值
  29. Dim OldValue = _Value
  30. _Value = newValue
  31. If AniControlEnabled = 0 Then
  32. Dim e = New RouteEventArgs(False)
  33. RaiseEvent PreviewChange(Me, e)
  34. If e.Handled Then
  35. _Value = OldValue
  36. DragStop()
  37. Exit Property
  38. End If
  39. End If
  40. If IsLoaded AndAlso AniControlEnabled = 0 Then
  41. If ActualWidth < 16 Then Exit Property
  42. Dim NewWidth As Double = _Value / MaxValue * (ActualWidth - 16)
  43. Dim DeltaProcess As Double = Math.Abs(LineFore.Width / (ActualWidth - 16) - _Value / MaxValue)
  44. Dim Time As Double = (1 - Math.Pow(1 - DeltaProcess, 3)) * 300 + If(ChangeByKey, 100, 0)
  45. AniStart({
  46. AaWidth(LineFore, Math.Max(0, NewWidth + If(NewWidth < 0.5, 0, 0.5)) - LineFore.Width, Time,, If(Time > 50, New AniEaseOutFluent, New AniEaseLinear)),
  47. AaWidth(LineBack, Math.Max(0, ActualWidth - 16 - NewWidth + If(ActualWidth - 16 - NewWidth < 0.5, 0, 0.5)) - LineBack.Width, Time,, If(Time > 50, New AniEaseOutFluent, New AniEaseLinear)),
  48. AaX(ShapeDot, NewWidth - ShapeDot.Margin.Left, Time,, If(Time > 50, New AniEaseOutFluent, New AniEaseLinear))
  49. }, "MySlider Progress " & Uuid)
  50. Else
  51. RefreshWidth(Nothing, Nothing)
  52. End If
  53. If AniControlEnabled = 0 Then RaiseEvent Change(Me, False)
  54. Catch ex As Exception
  55. Log(ex, "滑动条进度改变出错", LogLevel.Hint)
  56. End Try
  57. End Set
  58. End Property
  59. Private Sub RefreshWidth(sender As Object, e As SizeChangedEventArgs) Handles Me.SizeChanged
  60. If Not IsNothing(e) Then PanMain.Width = e.NewSize.Width
  61. AniStop("MySlider Progress " & Uuid)
  62. Dim NewWidth As Double = _Value / MaxValue * (ActualWidth - 16)
  63. LineFore.Width = Math.Max(0, NewWidth + If(NewWidth < 0.5, 0, 0.5))
  64. LineBack.Width = Math.Max(0, ActualWidth - 16 - NewWidth + If(ActualWidth - 16 - NewWidth < 0.5, 0, 0.5))
  65. SetLeft(ShapeDot, NewWidth)
  66. End Sub
  67. '拖动
  68. Public GetHintText As [Delegate]
  69. Private Sub DragStart(sender As Object, e As MouseButtonEventArgs) Handles Me.MouseLeftButtonDown
  70. e.Handled = True '防止 ScrollViewer 失焦问题
  71. DragControl = Me
  72. FrmMain.DragDoing()
  73. AniStart({
  74. AaScaleTransform(ShapeDot, 0.8 - CType(ShapeDot.RenderTransform, ScaleTransform).ScaleX, 75,, New AniEaseOutFluent)
  75. }, "MySlider Scale " & Uuid)
  76. '更新 Popup
  77. If GetHintText IsNot Nothing Then
  78. TextHint.Text = GetHintText.DynamicInvoke(Value)
  79. Popup.IsOpen = True
  80. AniStop("MySlider KeyPopup " & Uuid)
  81. End If
  82. End Sub
  83. Public Sub DragDoing()
  84. Dim Percent As Double = MathRange((Mouse.GetPosition(PanMain).X - 8) / (ActualWidth - 16), 0, 1)
  85. Dim NewValue As Integer = Percent * MaxValue
  86. If Not NewValue = Value Then
  87. Value = NewValue
  88. End If
  89. '更新 Popup
  90. If GetHintText IsNot Nothing Then TextHint.Text = GetHintText.DynamicInvoke(NewValue)
  91. End Sub
  92. Public Sub DragStop()
  93. RefreshColor()
  94. AniStart({
  95. AaScaleTransform(ShapeDot, 1 - CType(ShapeDot.RenderTransform, ScaleTransform).ScaleX, 200,, New AniEaseOutFluent)
  96. }, "MySlider Scale " & Uuid)
  97. If GetHintText IsNot Nothing Then Popup.IsOpen = False
  98. End Sub
  99. '指向动画
  100. Private Sub RefreshColor() Handles Me.IsEnabledChanged, Me.MouseEnter, Me.MouseLeave
  101. Try
  102. '判断当前颜色
  103. Dim ColorName As String
  104. Dim AnimationTime As Integer
  105. If IsEnabled Then
  106. If IsMouseOver OrElse (Not IsNothing(DragControl) AndAlso DragControl.Equals(Me)) Then
  107. ColorName = "ColorBrush3"
  108. AnimationTime = 100
  109. Else
  110. ColorName = "ColorBrush1"
  111. AnimationTime = 200
  112. End If
  113. Else
  114. ColorName = "ColorBrushGray4"
  115. AnimationTime = 200
  116. End If
  117. '触发颜色动画
  118. If IsLoaded AndAlso AniControlEnabled = 0 Then '防止默认属性变更触发动画
  119. '有动画
  120. AniStart({AaColor(Me, BorderBrushProperty, ColorName, AnimationTime)}, "MySlider Color " & Uuid)
  121. Else
  122. '无动画
  123. AniStop("MySlider Color " & Uuid)
  124. SetResourceReference(BorderBrushProperty, ColorName)
  125. End If
  126. Catch ex As Exception
  127. Log(ex, "滑动条颜色改变出错")
  128. End Try
  129. End Sub
  130. '按键改变
  131. Public Property ValueByKey As UInteger = 1
  132. Private Sub MySlider_MouseEnter() Handles Me.MouseEnter
  133. Focus() '确保按键能改变值
  134. End Sub
  135. Private Sub MySlider_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
  136. '拒绝一边拖动一边用按键改变
  137. If ReferenceEquals(Me, DragControl) Then Exit Sub
  138. '改变值
  139. If e.Key = Key.Left Then
  140. ChangeByKey = True
  141. Value -= ValueByKey
  142. ChangeByKey = False
  143. e.Handled = True
  144. ElseIf e.Key = Key.Right Then
  145. ChangeByKey = True
  146. Value += ValueByKey
  147. ChangeByKey = False
  148. e.Handled = True
  149. Else
  150. Exit Sub
  151. End If
  152. '更新 Popup
  153. If GetHintText IsNot Nothing Then
  154. TextHint.Text = GetHintText.DynamicInvoke(Value)
  155. Popup.IsOpen = True
  156. AniStop("MySlider KeyPopup " & Uuid)
  157. AniStart(AaCode(Sub() Popup.IsOpen = False, 700 * AniSpeed), "MySlider KeyPopup " & Uuid)
  158. End If
  159. End Sub
  160. End Class