ColorPicker

故事背景

项目里面需要一个像Winfrom里面那样的颜色选择器,如下图所示:

在网上看了一下。没有现成的东东可以拿来使用。大概查看了一下关于颜色的一些知识,想着没人种树,那就由我自己来种树,大家来乘凉好了。

设计过程

由于要考虑到手机上的效果,所以说这种向右展开的方式,不是太合适手机,所以最外层我考虑使用Pivot来存放基本颜色和自定义颜色这2页。

第一页是基本颜色,第二页是自定义的颜色,如下图。

ColorPicker这个控件,主要是由一个Button以及FlyoutBase.AttachedFlyout中的Flyout来组成的。

由Button的点击来控制Flyout的打开或者是关闭。

  1. <Button x:Name="ToggleButton" Padding="{TemplateBinding Padding}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}">
  2. <Grid Padding="{TemplateBinding Padding}" Background="#01010101">
  3. <Grid.ColumnDefinitions>
  4. <ColumnDefinition Width="*"/>
  5. <ColumnDefinition Width="auto"/>
  6. </Grid.ColumnDefinitions>
  7. <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
  8. <Rectangle.Fill>
  9. <!--failed to use TemplateBinding-->
  10. <SolidColorBrush Color="{Binding SelectedColor,RelativeSource={RelativeSource TemplatedParent}}"/>
  11. </Rectangle.Fill>
  12. </Rectangle>
  13. <TextBlock x:Name="ArrowPolygon" Foreground="{TemplateBinding Foreground}" Visibility="{TemplateBinding ArrowVisibility}" Grid.Column="" Text="" FontSize="{TemplateBinding FontSize}" FontFamily="Segoe UI Symbol" FontWeight="Normal" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5,0,5,0"/>
  14. </Grid>
  15. <FlyoutBase.AttachedFlyout>
  16. <Flyout x:Name="Flyout">
  17. <Flyout.FlyoutPresenterStyle>
  18. <Style TargetType="FlyoutPresenter">
  19. <Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled"/>
  20. <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled"/>
  21. <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/>
  22. <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
  23. <!--<Setter Property="MaxHeight" Value="NaN"/>
  24. <Setter Property="MaxWidth" Value="NaN"/>-->
  25. <Setter Property="MinHeight" Value=""/>
  26. <Setter Property="MinWidth" Value=""/>
  27. <Setter Property="Padding" Value="0,0,0,0"/>
  28. <Setter Property="Margin" Value="0,0,0,0"/>
  29. <Setter Property="BorderThickness" Value=""/>
  30. <Setter Property="Background" Value="White"/>
  31. <!--<Setter Property="BorderBrush" Value="#A4AFBA"/>-->
  32. <Setter Property="MaxWidth" Value="NaN"/>
  33. <Setter Property="MaxHeight" Value="NaN"/>
  34. <Setter Property="Background" Value="Transparent"/>
  35. <Setter Property="VerticalContentAlignment" Value="Center"/>
  36. <Setter Property="HorizontalContentAlignment" Value="Center"/>
  37. </Style>
  38. </Flyout.FlyoutPresenterStyle>
  39. <Grid Background="#FFD1DCE8" RequestedTheme="Light" BorderBrush="#A4AFBA" BorderThickness="" Width="{TemplateBinding FlyoutWidth}" Height="{TemplateBinding FlyoutHeight}">
  40. <Pivot x:Name="Pivot" Style="{StaticResource ColorPickerPivot}">
  41. <Pivot.Resources>
  42. <!--<Style TargetType="TextBlock">
  43. <Setter Property="Foreground" Value="Black"/>
  44. </Style>-->
  45. <Style TargetType="PivotHeaderItem" BasedOn="{StaticResource ColorPickerPivotHeaderItem}"/>
  46. <Style TargetType="PivotItem">
  47. <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
  48. <Setter Property="Margin" Value=""/>
  49. <Setter Property="Padding" Value=""/>
  50. <Setter Property="MinWidth" Value=""/>
  51. </Style>
  52. </Pivot.Resources>
  53. <PivotItem>
  54. <PivotItem.Header>
  55. <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Padding="">
  56. <Grid.ColumnDefinitions>
  57. <ColumnDefinition Width=""/>
  58. <ColumnDefinition/>
  59. </Grid.ColumnDefinitions>
  60. <Border Width="" Height="" Background="#FF97AEBF">
  61. <Grid>
  62. <Rectangle Height="" HorizontalAlignment="Left" VerticalAlignment="Top" Width="" Fill="#FFFF0000" Margin="1 1 0 0"/>
  63. <Rectangle Height="" HorizontalAlignment="Left" VerticalAlignment="Top" Width="" Fill="#FFFFC000" Margin="5 1 0 0"/>
  64. <Rectangle Height="" HorizontalAlignment="Left" VerticalAlignment="Top" Width="" Fill="#FFFFFF00" Margin="9 1 0 0"/>
  65. <Rectangle Height="" HorizontalAlignment="Left" VerticalAlignment="Top" Width="" Fill="#FF92D050" Margin="1 5 0 0"/>
  66. <Rectangle Height="" HorizontalAlignment="Left" VerticalAlignment="Top" Width="" Fill="#FF00B050" Margin="5 5 0 0"/>
  67. <Rectangle Height="" HorizontalAlignment="Left" VerticalAlignment="Top" Width="" Fill="#FF0C8242" Margin="9 5 0 0"/>
  68. <Rectangle Height="" HorizontalAlignment="Left" VerticalAlignment="Top" Width="" Fill="#FF0070C0" Margin="1 9 0 0"/>
  69. <Rectangle Height="" HorizontalAlignment="Left" VerticalAlignment="Top" Width="" Fill="#FF002060" Margin="5 9 0 0"/>
  70. <Rectangle Height="" HorizontalAlignment="Left" VerticalAlignment="Top" Width="" Fill="#FF7030A0" Margin="9 9 0 0"/>
  71. </Grid>
  72. </Border>
  73. <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" Text="基本颜色" TextWrapping="Wrap" Grid.Column="">
  74.  
  75. </TextBlock>
  76. </Grid>
  77. </PivotItem.Header>
  78. <StackPanel Orientation="Vertical">
  79. <Border Margin="0,5,0,0" HorizontalAlignment="Stretch" BorderBrush="#A4AFBA" BorderThickness="0,0,0,1" Height="">
  80. <TextBlock Margin="5,0" VerticalAlignment="Center">
  81. <Run Text="{Binding Title,RelativeSource={RelativeSource TemplatedParent}}"/>
  82. <Run Text=" - "/>
  83. <Run Text="基本颜色"/>
  84. </TextBlock>
  85. </Border>
  86. <local:ColorPickerItemsControl x:Name="BasicColorItems" MinHeight=""/>
  87. <Border Margin="0,5,0,0" BorderBrush="#A4AFBA" BorderThickness="0,0,0,1" HorizontalAlignment="Stretch" Height="">
  88. <TextBlock Margin="5,0" Text="最近使用颜色" VerticalAlignment="Center"/>
  89. </Border>
  90. <local:ColorPickerItemsControl x:Name="RecentColorItems" MinHeight=""/>
  91. </StackPanel>
  92. </PivotItem>
  93. <PivotItem>
  94. <PivotItem.Header>
  95. <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Padding="">
  96. <Grid.ColumnDefinitions>
  97. <ColumnDefinition Width=""/>
  98. <ColumnDefinition/>
  99. </Grid.ColumnDefinitions>
  100. <Ellipse Height="" Margin="0.5,-1,3,-1" Fill="#FFFFFFFF" Width=""/>
  101. <Ellipse Width="" Height="" Margin="0.5,-1,3,-1">
  102. <Ellipse.Fill>
  103. <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
  104. <GradientStop Color="#FFFF0000" Offset="0.1"/>
  105. <GradientStop Color="#00FF0000" Offset="0.5"/>
  106. </LinearGradientBrush>
  107. </Ellipse.Fill>
  108. </Ellipse>
  109. <Ellipse Height="" HorizontalAlignment="Stretch" Margin="0.5,-1,3,-1" VerticalAlignment="Stretch" Width="">
  110. <Ellipse.Fill>
  111. <LinearGradientBrush EndPoint="0.982999980449677,0.179000005125999" StartPoint="0.0879999995231628,0.753000020980835">
  112. <GradientStop Color="#FF079BF0" Offset="0.1"/>
  113. <GradientStop Color="#00079BF0" Offset="0.5"/>
  114. </LinearGradientBrush>
  115. </Ellipse.Fill>
  116. </Ellipse>
  117. <Ellipse Height="" HorizontalAlignment="Stretch" Margin="0.5,-1,3,-1" VerticalAlignment="Stretch" Width="">
  118. <Ellipse.Fill>
  119. <LinearGradientBrush EndPoint="0.136000007390976,0.174999997019768" StartPoint="0.843999981880188,0.822000026702881">
  120. <GradientStop Color="#FFF2F413" Offset="0.1"/>
  121. <GradientStop Color="#00F2F413" Offset="0.5"/>
  122. </LinearGradientBrush>
  123. </Ellipse.Fill>
  124. </Ellipse>
  125. <Ellipse Height="" HorizontalAlignment="Stretch" Margin="0.5,-1,3,-1" VerticalAlignment="Stretch" Width="" Visibility="Visible">
  126. <Ellipse.Fill>
  127. <LinearGradientBrush>
  128. <GradientStop Color="#00000000" Offset="0.772"/>
  129. <GradientStop Color="#4C000000" Offset=""/>
  130. </LinearGradientBrush>
  131. </Ellipse.Fill>
  132. </Ellipse>
  133. <Ellipse Height="" HorizontalAlignment="Stretch" Margin="-0.5,-1.5,2.5,-1.5" VerticalAlignment="Stretch" Width="" Stroke="#FF8AA3B5"/>
  134. <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" Text="自定义颜色" TextWrapping="Wrap" Grid.Column="">
  135. </TextBlock>
  136. </Grid>
  137. </PivotItem.Header>
  138. <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
  139. <Grid.RowDefinitions>
  140. <RowDefinition Height="auto"/>
  141. <RowDefinition Height="*"/>
  142. <RowDefinition Height="auto"/>
  143. <RowDefinition Height="auto"/>
  144. </Grid.RowDefinitions>
  145. <Grid.Resources>
  146. <Style TargetType="local:NumericTextBox">
  147. <Setter Property="InputScope" Value="Number"/>
  148. <Setter Property="ValueFormat" Value="F0"/>
  149. <Setter Property="Minimum" Value=""/>
  150. <Setter Property="Maximum" Value=""/>
  151. <Setter Property="MinWidth" Value=""/>
  152. <Setter Property="Margin" Value="5,0,0,0"/>
  153. <Setter Property="HorizontalContentAlignment" Value="Center"/>
  154. </Style>
  155. </Grid.Resources>
  156. <Border Margin="0,5,0,0" HorizontalAlignment="Stretch" BorderBrush="#A4AFBA" BorderThickness="0,0,0,1" Height="">
  157. <TextBlock Margin="5,0" VerticalAlignment="Center">
  158. <Run Text="{Binding Title,RelativeSource={RelativeSource TemplatedParent}}"/>
  159. <Run Text=" - "/>
  160. <Run Text="自定义颜色"/>
  161. </TextBlock>
  162. </Border>
  163. <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="" BorderBrush="#A4AFBA" BorderThickness="0,0,0,1">
  164. <Grid.ColumnDefinitions>
  165. <ColumnDefinition Width="*"/>
  166. <ColumnDefinition Width="auto"/>
  167. <ColumnDefinition Width="auto"/>
  168. </Grid.ColumnDefinitions>
  169. <ContentControl x:Name="ChoiceGridParent" Grid.Column="" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
  170. <Grid x:Name="ChoiceGrid" HorizontalAlignment="Stretch" Margin="5,5,0,5" VerticalAlignment="Stretch" >
  171. <!--<Grid.Background>
  172. <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
  173. <LinearGradientBrush.GradientStops>
  174. <GradientStop Offset="0.0" Color="White"/>
  175. <GradientStop Offset="" Color="#00FFFFFF"/>
  176. </LinearGradientBrush.GradientStops>
  177. </LinearGradientBrush>
  178. </Grid.Background>-->
  179. <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
  180. <Rectangle.Fill>
  181. <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
  182. <LinearGradientBrush.GradientStops>
  183. <GradientStop Offset="0.0" Color="White"/>
  184. <GradientStop Offset="" Color="#00FFFFFF"/>
  185. </LinearGradientBrush.GradientStops>
  186. </LinearGradientBrush>
  187. </Rectangle.Fill>
  188. </Rectangle>
  189. <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
  190. <Rectangle.Fill>
  191. <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
  192. <LinearGradientBrush.GradientStops>
  193. <GradientStop Offset="0.0" Color="#00000000"/>
  194. <GradientStop Offset="" Color="Black"/>
  195. </LinearGradientBrush.GradientStops>
  196. </LinearGradientBrush>
  197. </Rectangle.Fill>
  198. </Rectangle>
  199. <Canvas x:Name="PadCanvas">
  200. <Canvas x:Name="Indicator">
  201. <Ellipse Height="" Width="" Fill="Transparent" Stroke="#FFFFFFFF" StrokeThickness="" Margin="-3 -3 0 0" />
  202. <Ellipse Height="" Width="" Fill="Transparent" Stroke="#FF737373" Margin="-6 -6 0 0" />
  203. </Canvas>
  204. </Canvas>
  205. </Grid>
  206. </ContentControl>
  207. <Slider x:Name="Hue" Style="{StaticResource ColorPickerHueSlider}" Margin="5,5,0,5" Grid.Column="">
  208. <Slider.Background>
  209. <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
  210. <GradientStop Offset="0.0" Color="#FFFF0000"/>
  211. <GradientStop Offset="0.2" Color="#FFFFFF00"/>
  212. <GradientStop Offset="0.4" Color="#FF00FF00"/>
  213. <GradientStop Offset="0.6" Color="#FF0000FF"/>
  214. <GradientStop Offset="0.8" Color="#FFFF00FF"/>
  215. <GradientStop Offset="1.0" Color="#FFFF0000"/>
  216. </LinearGradientBrush>
  217. </Slider.Background>
  218. </Slider>
  219. <Slider x:Name="Alpha" Style="{StaticResource ColorPickerAlphaSlider}" Margin="" Grid.Column="">
  220. <Slider.Background>
  221. <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
  222. <GradientStop Color="Black" Offset=""/>
  223. <GradientStop Color="Transparent" Offset=""/>
  224. </LinearGradientBrush>
  225. </Slider.Background>
  226. </Slider>
  227. </Grid>
  228.  
  229. <Grid Margin="0,0,5,0" Padding="0,0,0,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="" BorderBrush="#A4AFBA" BorderThickness="0,0,0,1">
  230. <Grid.ColumnDefinitions>
  231. <ColumnDefinition Width="*"/>
  232. <ColumnDefinition Width="*"/>
  233. <ColumnDefinition Width="*"/>
  234. <ColumnDefinition Width="*"/>
  235. </Grid.ColumnDefinitions>
  236. <local:NumericTextBox x:Name="AColor" Grid.Column="">
  237. <local:NumericTextBox.Header>
  238. <TextBlock Text="透明度(A)" HorizontalAlignment="Center"/>
  239. </local:NumericTextBox.Header>
  240. </local:NumericTextBox>
  241. <local:NumericTextBox x:Name="RColor" Grid.Column="" >
  242. <local:NumericTextBox.Header>
  243. <TextBlock Text="红(R)" HorizontalAlignment="Center"/>
  244. </local:NumericTextBox.Header>
  245. </local:NumericTextBox>
  246. <local:NumericTextBox x:Name="GColor" Grid.Column="" >
  247. <local:NumericTextBox.Header>
  248. <TextBlock Text="绿(G)" HorizontalAlignment="Center"/>
  249. </local:NumericTextBox.Header>
  250. </local:NumericTextBox>
  251. <local:NumericTextBox x:Name="BColor" Grid.Column="" >
  252. <local:NumericTextBox.Header>
  253. <TextBlock Text="蓝(B)" HorizontalAlignment="Center"/>
  254. </local:NumericTextBox.Header>
  255. </local:NumericTextBox>
  256. </Grid>
  257. <Grid Grid.Row="" Margin="">
  258. <Grid.ColumnDefinitions>
  259. <ColumnDefinition Width="*"/>
  260. <ColumnDefinition Width="auto"/>
  261. </Grid.ColumnDefinitions>
  262. <Grid HorizontalAlignment="Stretch" Margin="0,0,10,0">
  263. <local:TransparentBackground/>
  264. <Rectangle x:Name="CustomColorRectangle" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
  265. <Rectangle.Fill>
  266. <SolidColorBrush Color="{Binding CurrentCustomColor,RelativeSource={RelativeSource TemplatedParent}}"/>
  267. </Rectangle.Fill>
  268. <ToolTipService.ToolTip>
  269. <ToolTip>
  270. <Binding Converter="{StaticResource ColorToStringConverter}" Path="CurrentCustomColor" RelativeSource="{RelativeSource TemplatedParent}"/>
  271. </ToolTip>
  272. </ToolTipService.ToolTip>
  273. </Rectangle>
  274. </Grid>
  275. <Button x:Name="CustomColorOkButton" Grid.Column="" Content="确定" VerticalAlignment="Center" HorizontalAlignment="Right"/>
  276. </Grid>
  277. </Grid>
  278. </PivotItem>
  279. </Pivot>
  280. <Button x:Name="CloseButton" Content="关闭" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin=""/>
  281. </Grid>
  282. </Flyout>
  283. </FlyoutBase.AttachedFlyout>
  284. <ToolTipService.ToolTip>
  285. <ToolTip>
  286. <Binding Path="SelectedColor" RelativeSource="{RelativeSource TemplatedParent}" Converter="{StaticResource ColorToStringConverter}"/>
  287. </ToolTip>
  288. </ToolTipService.ToolTip>
  289. </Button>

通过重写Pivot的模板我们可以轻松得到PiovtHeaderItem 在下面的效果(修改Header和PivotItemPresenter的行号)

Pivot部分模板代码如下,注意蓝色部分:

  1. <Grid x:Name="PivotLayoutElement">
  2. <Grid.RowDefinitions>
  3. <RowDefinition Height="*" />
  4. <RowDefinition Height="Auto" />
  5. </Grid.RowDefinitions>
  6. <Grid.ColumnDefinitions>
  7. <ColumnDefinition Width="Auto" />
  8. <ColumnDefinition Width="*" />
  9. <ColumnDefinition Width="Auto" />
  10. </Grid.ColumnDefinitions>
  11. <Grid.RenderTransform>
  12. <CompositeTransform x:Name="PivotLayoutElementTranslateTransform" />
  13. </Grid.RenderTransform>
  14. <ContentPresenter Grid.Row="1"
  15. x:Name="LeftHeaderPresenter"
  16. Content="{TemplateBinding LeftHeader}"
  17. ContentTemplate="{TemplateBinding LeftHeaderTemplate}"
  18. HorizontalAlignment="Stretch"
  19. VerticalAlignment="Stretch" />
  20. <ContentControl Grid.Row="1"
  21. x:Name="HeaderClipper"
  22. Grid.Column=""
  23. UseSystemFocusVisuals="False"
  24. HorizontalContentAlignment="Stretch">
  25. <ContentControl.Clip>
  26. <RectangleGeometry x:Name="HeaderClipperGeometry" />
  27. </ContentControl.Clip>
  28. <Grid Background="Transparent" BorderBrush="#A4AFBA" BorderThickness="0,1,0,0">
  29. <PivotHeaderPanel x:Name="StaticHeader" Visibility="Collapsed" />
  30. <PivotHeaderPanel x:Name="Header">
  31. <PivotHeaderPanel.RenderTransform>
  32. <TransformGroup>
  33. <CompositeTransform x:Name="HeaderTranslateTransform" />
  34. <CompositeTransform x:Name="HeaderOffsetTranslateTransform" />
  35. </TransformGroup>
  36. </PivotHeaderPanel.RenderTransform>
  37. </PivotHeaderPanel>
  38. </Grid>
  39. </ContentControl>
  40. <Button Grid.Row="1"
  41. x:Name="PreviousButton"
  42. Grid.Column=""
  43. Template="{StaticResource PreviousTemplate}"
  44. Width=""
  45. Height=""
  46. UseSystemFocusVisuals="False"
  47. Margin="{ThemeResource PivotNavButtonMargin}"
  48. IsTabStop="False"
  49. IsEnabled="False"
  50. HorizontalAlignment="Left"
  51. VerticalAlignment="Top"
  52. Opacity=""
  53. Background="Transparent" />
  54. <Button Grid.Row="1"
  55. x:Name="NextButton"
  56. Grid.Column=""
  57. Template="{StaticResource NextTemplate}"
  58. Width=""
  59. Height=""
  60. UseSystemFocusVisuals="False"
  61. Margin="{ThemeResource PivotNavButtonMargin}"
  62. IsTabStop="False"
  63. IsEnabled="False"
  64. HorizontalAlignment="Right"
  65. VerticalAlignment="Top"
  66. Opacity=""
  67. Background="Transparent" />
  68. <ContentPresenter Grid.Row="1"
  69. x:Name="RightHeaderPresenter"
  70. Grid.Column=""
  71. Content="{TemplateBinding RightHeader}"
  72. ContentTemplate="{TemplateBinding RightHeaderTemplate}"
  73. HorizontalAlignment="Stretch"
  74. VerticalAlignment="Stretch" />
  75. <ItemsPresenter x:Name="PivotItemPresenter" Grid.Row="0" Grid.ColumnSpan="">
  76. <ItemsPresenter.RenderTransform>
  77. <TransformGroup>
  78. <TranslateTransform x:Name="ItemsPresenterTranslateTransform" />
  79. <CompositeTransform x:Name="ItemsPresenterCompositeTransform" />
  80. </TransformGroup>
  81. </ItemsPresenter.RenderTransform>
  82. </ItemsPresenter>
  83. </Grid>

这个色块就比较简单了,通过Just Color Picker 把Winform 里面的颜色都给搞出来,通过ItemsControl把他们都布局在一块。

最近使用颜色,这个就是记录最近你点击修改的颜色,我这里用了一个帮助类来进行管理。

  1. internal static class ColorPickerColorHelper
  2. {
  3. const string ColorPickerRecentColorsKey = "ColorPickerRecentColors.json";
  4. private static ObservableCollection<Color> RecentColors;
  5. //private static List<Color> systemColors;
  6. //private static List<Color> basicColors;
  7. private static bool hasLoadedRecentColors;
  8.  
  9. //public static List<Color> BasicColors
  10. //{
  11. // get
  12. // {
  13. // return basicColors;
  14. // }
  15. //}
  16.  
  17. static ColorPickerColorHelper()
  18. {
  19. //basicColors = new List<Color>();
  20. RecentColors = new ObservableCollection<Color>();
  21. //systemColors = new List<Color>();
  22. //foreach (var color in typeof(Colors).GetRuntimeProperties())
  23. //{
  24. // basicColors.Add((Color)color.GetValue(null));
  25. //}
  26.  
  27. }
  28.  
  29. public static async Task<ObservableCollection<Color>> GetRecentColorsAsync()
  30. {
  31. if (!hasLoadedRecentColors)
  32. {
  33. hasLoadedRecentColors = true;
  34. RecentColors = await GetRecentColorsAsyncInternal();
  35. var temp = await GetRecentColorsAsyncInternal();
  36. if (temp != null)
  37. {
  38. RecentColors = temp;
  39. }
  40. }
  41. return RecentColors;
  42. }
  43.  
  44. public async static Task SetRecentColorsAsync(Color color)
  45. {
  46. if (RecentColors != null)
  47. {
  48. if (RecentColors.LastOrDefault() == color)
  49. {
  50. return;
  51. }
  52. RecentColors.Add(color);
  53. if (RecentColors.Count > )
  54. {
  55. RecentColors.RemoveAt();
  56. }
  57. await SaveRecentColorsAsync();
  58. }
  59. }
  60.  
  61. private static async Task<ObservableCollection<Color>> GetRecentColorsAsyncInternal()
  62. {
  63. var jsonText = await StorageHelper.ReadFileAsync(ColorPickerRecentColorsKey);
  64. return JsonConvert.DeserializeObject<ObservableCollection<Color>>(jsonText);
  65. }
  66.  
  67. private static async Task SaveRecentColorsAsync()
  68. {
  69. string jsonText = "";
  70.  
  71. if (RecentColors.Count > )
  72. {
  73. jsonText = JsonConvert.SerializeObject(RecentColors);
  74. }
  75. await StorageHelper.WriteFileAsync(ColorPickerRecentColorsKey, jsonText);
  76. }
  77. }
  78. }

第二页是自定义的色盘

这里用到HSL 色彩模式,之前不了解的小伙伴可以先去看一下,RGB→HSL 和 HSL→RGB转换的算法也有。

 HSL通道  透明度通道   这个2个我用到了Slider控件,当然模板我重新写了一下

 你可以通过拖拽、点击、键盘上下左右来微调颜色数值,这个属于比较简单的拖拽实现,Ellipse通过计算得出它的位置。

 当然你可以通过直接设置ARGB来设置颜色。这个输入框,我设计成了NumericTextBox继承于TextBox控件,支持Format

  1. public class NumericTextBox : TextBox
  2. {
  3.  
  4. private bool _isChangingTextWithCode;
  5. private bool _isChangingValueWithCode;
  6. private const double Epsilon = .;
  7.  
  8. public event EventHandler ValueChanged;
  9. public double Value
  10. {
  11. get { return (double)GetValue(ValueProperty); }
  12. set { SetValue(ValueProperty, value); }
  13. }
  14.  
  15. // Using a DependencyProperty as the backing store for Value. This enables animation, styling, binding, etc...
  16. public static readonly DependencyProperty ValueProperty =
  17. DependencyProperty.Register("Value", typeof(double), typeof(NumericTextBox), new PropertyMetadata(0.0, new PropertyChangedCallback(OnValueChanged)));
  18.  
  19. private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  20. {
  21. (d as NumericTextBox).UpdateValueText();
  22. (d as NumericTextBox).OnValueChanged();
  23. }
  24.  
  25. public string ValueFormat
  26. {
  27. get { return (string)GetValue(ValueFormatProperty); }
  28. set { SetValue(ValueFormatProperty, value); }
  29. }
  30.  
  31. // Using a DependencyProperty as the backing store for ValueFormat. This enables animation, styling, binding, etc...
  32. public static readonly DependencyProperty ValueFormatProperty =
  33. DependencyProperty.Register("ValueFormat", typeof(string), typeof(NumericTextBox), new PropertyMetadata("F0"));
  34.  
  35. public double Minimum
  36. {
  37. get { return (double)GetValue(MinimumProperty); }
  38. set { SetValue(MinimumProperty, value); }
  39. }
  40.  
  41. // Using a DependencyProperty as the backing store for Minimum. This enables animation, styling, binding, etc...
  42. public static readonly DependencyProperty MinimumProperty =
  43. DependencyProperty.Register("Minimum", typeof(double), typeof(NumericTextBox), new PropertyMetadata(double.MinValue));
  44.  
  45. public double Maximum
  46. {
  47. get { return (double)GetValue(MaximumProperty); }
  48. set { SetValue(MaximumProperty, value); }
  49. }
  50.  
  51. // Using a DependencyProperty as the backing store for Maximum. This enables animation, styling, binding, etc...
  52. public static readonly DependencyProperty MaximumProperty =
  53. DependencyProperty.Register("Maximum", typeof(double), typeof(NumericTextBox), new PropertyMetadata(double.MaxValue));
  54.  
  55. public NumericTextBox()
  56. {
  57. Text = this.Value.ToString(CultureInfo.CurrentCulture);
  58. TextChanged += this.OnValueTextBoxTextChanged;
  59. KeyDown += this.OnValueTextBoxKeyDown;
  60. PointerExited += this.OnValueTextBoxPointerExited;
  61. }
  62.  
  63. private void OnValueTextBoxPointerExited(object sender, PointerRoutedEventArgs e)
  64. {
  65.  
  66. }
  67.  
  68. private void OnValueTextBoxKeyDown(object sender, KeyRoutedEventArgs e)
  69. {
  70.  
  71. }
  72.  
  73. private void OnValueTextBoxTextChanged(object sender, TextChangedEventArgs e)
  74. {
  75. this.UpdateValueFromText();
  76. }
  77.  
  78. protected override void OnGotFocus(RoutedEventArgs e)
  79. {
  80. base.OnGotFocus(e);
  81. }
  82.  
  83. protected override void OnLostFocus(RoutedEventArgs e)
  84. {
  85. this.UpdateValueFromText();
  86. base.OnLostFocus(e);
  87. }
  88.  
  89. private void UpdateValueText()
  90. {
  91. _isChangingTextWithCode = true;
  92. this.Text = this.Value.ToString(this.ValueFormat);
  93. this.SelectionStart = this.Text.Length;
  94. _isChangingTextWithCode = false;
  95. }
  96.  
  97. private void OnValueChanged()
  98. {
  99. if (ValueChanged != null)
  100. {
  101. ValueChanged(null, null);
  102. }
  103. }
  104.  
  105. private bool UpdateValueFromText()
  106. {
  107. if (_isChangingTextWithCode)
  108. {
  109. return false;
  110. }
  111.  
  112. double val;
  113.  
  114. if (double.TryParse(this.Text, NumberStyles.Any, CultureInfo.CurrentUICulture, out val) ||
  115. Calculator.TryCalculate(this.Text, out val))
  116. {
  117. _isChangingValueWithCode = true;
  118. if (val < Minimum)
  119. {
  120. val = Minimum;
  121. }
  122. if (val > Maximum)
  123. {
  124. val = Maximum;
  125. }
  126.  
  127. this.Value = val;
  128.  
  129. UpdateValueText();
  130.  
  131. _isChangingValueWithCode = false;
  132.  
  133. return true;
  134. }
  135. else
  136. {
  137. if (this.Text == "")
  138. {
  139. this.Value = Minimum;
  140. }
  141. UpdateValueText();
  142.  
  143. }
  144.  
  145. return false;
  146. }
  147.  
  148. private bool SetValueAndUpdateValidDirections(double value)
  149. {
  150. // Range coercion is handled by base class.
  151. var oldValue = this.Value;
  152. if (value < Minimum)
  153. {
  154. value = Minimum;
  155. }
  156. if (value > Maximum)
  157. {
  158. value = Maximum;
  159. }
  160. this.Value = value;
  161. if (value < Minimum || value > Maximum)
  162. {
  163. UpdateValueText();
  164. }
  165. //this.SetValidIncrementDirection();
  166.  
  167. return Math.Abs(this.Value - oldValue) > Epsilon;
  168. }
  169. }

 最后这个色块就是显示的最终的颜色,点击确认会生产自定义的颜色。这里说一下透明色的效果是怎么做成的。
在我们VS里面当把颜色设置为Transparent的时候,效果是如下图

其实就是添加了些灰色的Rect,知道效果,怎么做就简单了,代码如下

  1. public class TransparentBackground : Grid
  2. {
  3.  
  4. public double SquareWidth
  5. {
  6. get { return (double)GetValue(SquareWidthProperty); }
  7. set { SetValue(SquareWidthProperty, value); }
  8. }
  9.  
  10. // Using a DependencyProperty as the backing store for SquareWidth. This enables animation, styling, binding, etc...
  11. public static readonly DependencyProperty SquareWidthProperty =
  12. DependencyProperty.Register("SquareWidth", typeof(double), typeof(TransparentBackground), new PropertyMetadata(4.0, new PropertyChangedCallback(OnUpdateSquares)));
  13.  
  14. private static void OnUpdateSquares(DependencyObject d, DependencyPropertyChangedEventArgs e)
  15. {
  16. (d as TransparentBackground).UpdateSquares();
  17. }
  18.  
  19. public Brush SquareBrush
  20. {
  21. get { return (Brush)GetValue(SquareBrushProperty); }
  22. set { SetValue(SquareBrushProperty, value); }
  23. }
  24.  
  25. // Using a DependencyProperty as the backing store for SquareBrush. This enables animation, styling, binding, etc...
  26. public static readonly DependencyProperty SquareBrushProperty =
  27. DependencyProperty.Register("SquareBrush", typeof(Brush), typeof(TransparentBackground), new PropertyMetadata(new SolidColorBrush(Color.FromArgb(0xFF, 0xd7, 0xd7, 0xd7)), new PropertyChangedCallback(OnUpdateSquares)));
  28.  
  29. public Brush AlternatingSquareBrush
  30. {
  31. get { return (Brush)GetValue(AlternatingSquareBrushProperty); }
  32. set { SetValue(AlternatingSquareBrushProperty, value); }
  33. }
  34.  
  35. // Using a DependencyProperty as the backing store for AlternatingSquareBrush. This enables animation, styling, binding, etc...
  36. public static readonly DependencyProperty AlternatingSquareBrushProperty =
  37. DependencyProperty.Register("AlternatingSquareBrush", typeof(Brush), typeof(TransparentBackground), new PropertyMetadata(new SolidColorBrush(Colors.White), new PropertyChangedCallback(OnUpdateSquares)));
  38.  
  39. public TransparentBackground()
  40. {
  41. HorizontalAlignment = HorizontalAlignment.Stretch;
  42. VerticalAlignment = VerticalAlignment.Stretch;
  43. //this.SizeChanged += (s, e) =>
  44. //{
  45.  
  46. // if (e.NewSize != e.PreviousSize)
  47. // {
  48. // UpdateSquares();
  49. // }
  50. //};
  51. }
  52.  
  53. Size pre = Size.Empty;
  54. protected override Size ArrangeOverride(Size finalSize)
  55. {
  56. if (pre != finalSize)
  57. {
  58. UpdateSquares(finalSize);
  59. pre = finalSize;
  60. }
  61.  
  62. return base.ArrangeOverride(finalSize);
  63. }
  64.  
  65. private void UpdateSquares(Size? finalSize = null)
  66. {
  67.  
  68. Size size = finalSize == null ? new Size(this.ActualWidth, this.ActualHeight) : finalSize.Value;
  69. //size = new Size(this.ActualWidth, this.ActualHeight);
  70. this.Children.Clear();
  71. for (int x = ; x < size.Width / SquareWidth; x++)
  72. {
  73. for (int y = ; y < size.Height / SquareWidth; y++)
  74. {
  75. var rectangle = new Rectangle();
  76. rectangle.Fill = ((x % == && y % == ) || (x % == && y % == )) ? SquareBrush : AlternatingSquareBrush;
  77. rectangle.Width = Math.Max(, Math.Min(SquareWidth, size.Width - x * SquareWidth));
  78. rectangle.Height = Math.Max(, Math.Min(SquareWidth, size.Height - y * SquareWidth));
  79.  
  80. rectangle.Margin = new Thickness(x * SquareWidth, y * SquareWidth, , );
  81. rectangle.HorizontalAlignment = HorizontalAlignment.Left;
  82. rectangle.VerticalAlignment = VerticalAlignment.Top;
  83. this.Children.Add(rectangle);
  84. }
  85. }
  86.  
  87. }
  88. }

这样子我们整个控件就差不多了。

扩展

由于项目里面,一个页面上需要有很多个这样的控件,感觉如果有10个需要选择颜色的地方,就要有10个实例的话,比较傻,固做以下的扩展。

添加了

Owner 属性-作为ColorPicker 颜色改变的接受源
PlacementTarget 属性- 作为ColorPicker 弹出的Target

Show 方法- 能够使用代码显示ColorPicker

用法如下:

前台Xaml

  1. <control:ColorPicker x:Name="colorPicker" Width="" Height="" Opacity="" Closed="colorPicker_Closed" SelectedColorChanged="colorPicker_SelectedColorChanged" Placement="BottomCenter" HorizontalAlignment="Center" VerticalAlignment="Top" SelectedColor="Transparent" ArrowVisibility="Visible"/>
  2.  
  3. <Rectangle x:Name="rectangle1" Width="" Height="" Margin="" Fill="Green" Tapped="Rectangle_Tapped"/>
  4.  
  5. <Rectangle x:Name="rectangle2" Width="" Height="" Margin="" Fill="Yellow" Tapped="Rectangle_Tapped"/>

后台cs

  1. private void Rectangle_Tapped(object sender, TappedRoutedEventArgs e)
  2. {
  3. colorPicker.Placement = AdvancedFlyoutPlacementMode.RightCenter;
  4. colorPicker.PlacementTarget = (sender as FrameworkElement);
  5. colorPicker.Owner = sender;
  6. colorPicker.Show();
  7.  
  8. }
  9.  
  10. private void colorPicker_SelectedColorChanged(object sender, EventArgs e)
  11. {
  12. if (colorPicker.Owner!=null)
  13. {
  14. (colorPicker.Owner as Rectangle).Fill = new SolidColorBrush(colorPicker.SelectedColor);
  15. colorPicker.Owner = null;
  16. }
  17. }
  18.  
  19. private void colorPicker_Closed(object sender, object e)
  20. {
  21. colorPicker.PlacementTarget = null;
  22. }

总结

其实ColorPicker这个控件总体来说还是比较简单的,搞清楚UI 和HSL算法就ok。对了Colorpicker是固定了主题Light和大小的,黑色主题太丑了,而且会使色块看着及其不爽,所以背景和主题以及大小我都是写死了的。

AdvancedFlyout

背景
做这个东西,是被微软逼的。

10586 和 14393上面Flyout这个控件 行为上有很大区别。
主要问题是在10586上面,不能支持同时2个Flyout打开,就是说打开一个。再打开下一个的时候会关闭上一个。

没办法,只有自己搞一个。

AdvancedFlyoutBase/AdvancedFlyout

把微软的FlyoutBase/Floyout 属性方法都搞过来,我们自己用Popup来实现。

  1. /// <summary>
  2. /// to solve issue that can't open two flyouts in 10586.
  3. /// </summary>
  4. [ContentProperty(Name = nameof(Content))]
  5. public class AdvancedFlyout : AdvancedFlyoutBase
  6. {
  7. public UIElement Content { get; set; }
  8. /// <summary>
  9. /// FlyoutPresenter Style
  10. /// </summary>
  11. public Style FlyoutPresenterStyle { get; set; }
  12.  
  13. protected override Control CreatePresenter()
  14. {
  15. var fp = base.CreatePresenter() as FlyoutPresenter;
  16. if (FlyoutPresenterStyle != null)
  17. {
  18. fp.Style = FlyoutPresenterStyle;
  19. }
  20. fp.Content = Content;
  21. return fp;
  22. }
  23. }

主要的实现在于控制Popup的位置。
AdvancedFlyoutBase 里面我添加了

FlyoutBase 没有的三个属性:
IsLightDismissEnabled

VerticalOffset

HorizontalOffset

这3个属性都是Popup的。主要是在Placement的基准上再给于用户微调的权利。PlacementMode是一个枚举,比微软的分的更细。

  1. public enum AdvancedFlyoutPlacementMode
  2. {
  3. TopLeft = ,
  4. TopCenter,
  5. TopRight,
  6.  
  7. BottomLeft,
  8. BottomCenter,
  9. BottomRight,
  10.  
  11. LeftTop,
  12. LeftCenter,
  13. LeftBottom,
  14.  
  15. RightTop,
  16. RightCenter,
  17. RightBottom,
  18.  
  19. FullScreen,
  20. CenterScreen,
  21. }

我们在ShowAt方法中来实现计算Popup的具体位置

  1. public void ShowAt(FrameworkElement placementTarget)
  2. {
  3. if (Opening != null)
  4. {
  5. Opening(this, null);
  6. }
  7.  
  8. if (_popup == null)
  9. {
  10. _popup = new Popup();
  11. _popup.ChildTransitions = new TransitionCollection() { new PopupThemeTransition() };
  12. _popup.Opened += _popup_Opened;
  13. _popup.Closed += _popup_Closed;
  14. _popup.Child = CreatePresenter();
  15. }
  16. reCalculatePopupPosition = !CalculatePopupPosition(placementTarget);
  17. _popup.IsLightDismissEnabled = IsLightDismissEnabled;
  18. this.placementTarget = placementTarget;
  19. if (reCalculatePopupPosition || FlyoutPresenter.Style == null)
  20. {
  21. _popup.Opacity = ;
  22. }
  23.  
  24. _popup.HorizontalOffset += HorizontalOffset;
  25. _popup.VerticalOffset += VerticalOffset;
  26.  
  27. _popup.IsOpen = true;
  28. }

其中CalculatePopupPosition 是我们的重中之重。

我们计算Popup的位置需要参考下面几样:

1.PlacementTarget在页面上的位置
其实就是控件相对于Window的位置,由以下代码获得

  1. var placementTargetRect = placementTarget.TransformToVisual(Window.Current.Content as FrameworkElement).TransformBounds(new Rect(, , placementTarget.ActualWidth, placementTarget.ActualHeight));

2.弹出页面的大小

FlyoutPresenter的实际大小,由以下代码获得

  1. var fp = FlyoutPresenter;
  2. fp.Width = double.NaN;
  3. fp.Height = double.NaN;
  4. if (fp.DesiredSize == fpSize)
  5. {
  6. fp.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
  7. }
  8.  
  9. fpSize = fp.DesiredSize;

3.Window 的大小

  1. var windowSize = new Size(Window.Current.Bounds.Width, Window.Current.Bounds.Height);

有了之上3个参考数据,那么我们就很容易来计算出Popup显示的位置,

下面以Top为例:

  1. private bool TryHandlePlacementTop(Rect placementTargetRect, Size fpSize, Size windowSize)
  2. {
  3. if (placementTargetRect.Y - fpSize.Height < )
  4. {
  5. return false;
  6. }
  7.  
  8. double x = ;
  9.  
  10. _popup.VerticalOffset = placementTargetRect.Y - fpSize.Height;
  11.  
  12. if (fpSize.Width > windowSize.Width)
  13. {
  14. _popup.HorizontalOffset = ;
  15. return true;
  16. }
  17.  
  18. switch (Placement)
  19. {
  20. case AdvancedFlyoutPlacementMode.TopLeft:
  21. x = placementTargetRect.X;
  22. break;
  23. case AdvancedFlyoutPlacementMode.TopCenter:
  24. x = placementTargetRect.X + placementTargetRect.Width / - fpSize.Width / ;
  25. if (x < )
  26. {
  27. x = ;
  28. }
  29. break;
  30. case AdvancedFlyoutPlacementMode.TopRight:
  31. x = placementTargetRect.X + placementTargetRect.Width - fpSize.Width;
  32. if (x < )
  33. {
  34. x = ;
  35. }
  36. break;
  37. default:
  38. goto case AdvancedFlyoutPlacementMode.TopCenter;
  39. }
  40.  
  41. if (x + fpSize.Width > windowSize.Width)
  42. {
  43. x = windowSize.Width - fpSize.Width;
  44. }
  45.  
  46. _popup.HorizontalOffset = x;
  47. return true;
  48. }

如果target控件上面的空间不够,那么肯定我们不能把Popup放上面,故return false,再尝试把Popup放在其他方位上。

如果可以放的话,我们再按照是Left,Center,Right的参考位置来计算,注意我们要考虑到Window的大小,不能超出Window。

最终Top的代码如下图

  1. case AdvancedFlyoutPlacementMode.TopLeft:
  2. case AdvancedFlyoutPlacementMode.TopCenter:
  3. case AdvancedFlyoutPlacementMode.TopRight:
  4. if (!TryHandlePlacementTop(placementTargetRect, fpSize, windowSize))
  5. {
  6. if (!TryHandlePlacementBottom(placementTargetRect, fpSize, windowSize))
  7. {
  8. if (!TryHandlePlacementLeft(placementTargetRect, fpSize, windowSize))
  9. {
  10. if (!TryHandlePlacementRight(placementTargetRect, fpSize, windowSize))
  11. {
  12. TryHandlePlacementCenterScreen(fpSize, windowSize);
  13. }
  14. }
  15. }
  16. }
  17.  
  18. break;

在开发过程中发现

如果在Popup Open之前计算FlyoutPresenter的大小,

可能导致Size不正确,如果没有给FlyoutPresenter 赋Style,这个时候还不会使用默认FlyoutPresenter 的样式,Pading,Margin这些参数还没得到赋值。

或者抛异常,比如FlyoutPresenter内部是Pivot的时候会抛异常。

所以我增加了容错。

在计算出错或者FlyoutPresenter的Style 为Null的时候,讲Popup的Opacity设置为0,

并且在Popup Open之后 重写计算位置,然后把Popup Opacity设置1.

  1. if (reCalculatePopupPosition || FlyoutPresenter.Style == null)
  2. {
  3. _popup.Opacity = ;
  4. }
  5.  
  6. private void _popup_Opened(object sender, object e)
  7. {
  8. //DesiredSize was not right when style was null before opened
  9. //we should re-calcuatePopupPosition after FlyoutPresenter get default values from default style or app resource style
  10. if (FlyoutPresenter.Style == null || reCalculatePopupPosition)
  11. {
  12. CalculatePopupPosition(placementTarget);
  13. _popup.HorizontalOffset += HorizontalOffset;
  14. _popup.VerticalOffset += VerticalOffset;
  15. _popup.Opacity = ;
  16. }
  17.  
  18. if (Opened != null)
  19. {
  20. Opened(this, e);
  21. }
  22.  
  23. }

这样就解决位置不对的问题。。其实我在使用Flyout的时候也遇到过显示的位置从左上角 跳到正确位置的情况,估计跟我这个原因一样。。估计微软也做了容错。不过没把Opacity设置一下。

总结

其实在开发中,有时间去抱怨微软版本控件有问题,不如静下心来想想其他办法,也需会比微软更好的版本,也更容易方便我们自定义。

开源有益,源码GitHub地址

最后放上2个控件在项目里面的合体照。

UWP 颜色选择器(ColorPicker) 和 自定义的Flyout(AdvancedFlyout)的更多相关文章

  1. 基于vue的颜色选择器color-picker

    项目中有用到颜色选择器的童鞋们可以看过来了 关于color-picker的jquery的插件是有蛮多,不过vue组件没有吧,反正我没有找到, 虽然element-ui里面有这个,但是你愿意为了一个小功 ...

  2. 自定义实现简单的Android颜色选择器(附带源码)

    在写Android App过程中需要一个简单的颜色选择器,Android自带的ColorPicker和网上的一些ColorPicker都太高端了,都实现了颜色渐变功能,我要的不需要那么复杂,只想提供几 ...

  3. 【canvas系列】用canvas实现一个colorpicker(类似PS的颜色选择器)

    每个浏览器都有自己的特点,比如今天要做的colorpicker就是,一千个浏览器,一千个哈姆雷特,一千个colorpicker.今天canvas系列就用canvas做一个colorpicker. ** ...

  4. HTML5的input color系统颜色选择器

    前两天,我写了一篇<推荐两款jQuery色盘选择器>介绍,那是使用JavaScript实现的色盘,今天我给大家介绍HTML5的色盘选择器.HTML5有一个input类型为color,即颜色 ...

  5. Android 颜色渲染(一) 颜色选择器 ColorPickerDialog剖析

    版权声明:本文为博主原创文章,未经博主允许不得转载. Android 颜色选择器之ColorPickerDialog剖析 有这样一个需求,可以让用户自定义背景颜色,这就需要提供一个颜色选择器给用户. ...

  6. Android圆环形颜色选择器:HoloColorPicker

    HoloColorPicker实现圆环形颜色选择器,可以改变颜色饱和度来选择颜色.选择颜色时,可以用手指沿着圆环滑动一个滑块,从而选择颜色. 添加以下XML至你的布局中: ? 1 2 3 4 < ...

  7. 10个精选的颜色选择器Javascript脚本及其jQuery插件

     Color picker即颜色选择器使我们在web开发中可能经常用到的组件,今天我们特意精选了10个超酷的颜色选择器实现,其中包括了javascript脚本 实现及其传说中的jQuery插件实现 ...

  8. 基于vue的颜色选择器vue-color-picker

    项目中有用到颜色选择器的童鞋们可以看过来了 关于color-picker的jquery的插件是有蛮多,不过vue组件没有吧,反正我没有找到, 虽然element-ui里面有这个,但是你愿意为了一个小功 ...

  9. html 颜色选择器 亲测,很好用

    @*以下 是测试html 颜色选择器的*@ @*<a href="#" mce_href="#" onclick="initColorPicke ...

随机推荐

  1. 各种主流浏览器CSS、BUG兼容

    1.div的垂直居中问题 vertical-align:middle;将行距增加到和整个DIV一样高 line-height:200px;然后插入文字,就垂直居中了.缺点是要控制内容不要换行.---- ...

  2. 异常详细信息: System.ComponentModel.Win32Exception: 拒绝访问。

    本地win7 本地正常,服务器win2008r2,服务器报错! 异常详细信息: System.ComponentModel.Win32Exception: 拒绝访问. 拒绝访问. 说明: 执行当前 W ...

  3. [HttpPost]和[AcceptVerbs(HttpVerbs.Post)]区别

    1.共同点:[HttpPost]和[AcceptVerbs(HttpVerbs.Post)]都是只接受POST请求过来的数据. 2.不同点:在MVC中如果想一个action既可以回应POST请求也可以 ...

  4. 语言模型kenlm的训练及使用

    一.背景 近期研究了一下语言模型,同事推荐了一个比较好用的工具包kenlm,记录下使用过程. 二.使用kenlm训练 n-gram 1.工具介绍:http://kheafield.com/code/k ...

  5. C# WinForm 技巧:控件截图

    Point screenPoint = 控件.PointToScreen(new Point()); Rectangle rect = new Rectangle(screenPoint, chart ...

  6. leetcode算法分类

    利用堆栈:http://oj.leetcode.com/problems/evaluate-reverse-polish-notation/http://oj.leetcode.com/problem ...

  7. jQuery所支持的css样式

    jQuery所支持的css样式 backgroundPosition borderWidth borderBottomWidth borderLeftWidth borderRightWidth bo ...

  8. 【学习笔记】C语言之词法规则

    一.字符 标准并没有规定C环境必须使用特定的字符集,但是它规定了字符集必须包含英语所有的大小写字母,数字0到9,以及下面的字符: ! # % ^ & * ( ) _ – + =  / . ? ...

  9. 第一届山东省ACM——Phone Number(java)

    Description We know that if a phone number A is another phone number B’s prefix, B is not able to be ...

  10. Python 自动化入门 day1复习

    一.Python介绍 Python是1989年圣诞节期间龟叔创造的一种解释型语言. 最新的TIOBE排行榜 目前Python主要应用领域: 云计算: 云计算最火的语言, 典型应用OpenStack W ...