[UWP]分享一個基於HSV色輪的調色板應用
1. 前言
上一篇文章介紹了HSV色輪,這次分享一個基於HSV色輪的調色板應用,應用地址:ColorfulBox - Microsoft Store
2. 功能
ColorfulBox是Adobe 色輪的簡單模仿,只實現了最基本的功能,UI也沒那麽好看,也沒用MVVM框架。
2.1 HSV色輪
這個應用最好玩的地方在於分布於HSV色輪上的各個點(ColorPoint)以及可以通過拖動它們改變顏色。ColorPoint的基本結構如下(不是完整代碼):
public class ColorPoint : DependencyObject, INotifyPropertyChanged
{
public event EventHandler<PropertyEventArgs> ColorChanged;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnColorChanged(Color oldValue, Color newValue)
{
ColorChanged?.Invoke(this, new PropertyEventArgs(nameof(Color), oldValue, newValue));
}
private Color _color;
/// <summary>
/// 獲取或設置 Color 的值
/// </summary>
public Color Color
{
get { return _color; }
set
{
if (_color == value)
return;
var oldValue = _color;
_color = value;
OnPropertyChanged ("Color");
ColorChanged?.Invoke(this, new PropertyEventArgs(nameof(Color), oldValue, _color));
}
}
}
由於Color是一個struct,UWP沒辦法監視struct的值改變事件,所以才使用ColorPoint來包裝Color及其它功能。
色輪本身是一個ListView,這樣比直接繼承Control少寫很多代碼,尤其是SelectedItem相關的代碼還挺無趣的。雖然色輪從外表看不出是個ListView,改改ControlTemplate,再配合GetContainerForItemOverride()
和PrepareContainerForItemOverride(DependencyObject element, object item)
兩個函數,可以讓ListView完全改頭換面。熟悉XAML的開發者應該都不會對這兩個ItemsControl中的關鍵函數感到陌生。
<Style TargetType="local:HsvWheelColorPalette">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:HsvWheelColorPalette">
<Grid Background="{TemplateBinding Background}">
<Image Source="ms-appx:///Assets/Wheel.png" />
<ItemsPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle"
Value="{StaticResource HsvWheelColorPointVisualStyle}" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
protected override DependencyObject GetContainerForItemOverride()
{
return new ColorPointVisual();
}
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
if (element is ColorPointVisual visual)
{
visual.ManipulationStarted -= OnColorPointVisualDragStarted;
visual.ManipulationStarted += OnColorPointVisualDragStarted;
visual.ManipulationDelta -= OnColorPointVisualDragDelta;
visual.ManipulationDelta += OnColorPointVisualDragDelta;
}
var colorPoint = item as ColorPoint;
colorPoint.ColorChanged -= OnColorChanged;
colorPoint.ColorChanged += OnColorChanged;
}
在UWP中拖動的代碼變得很簡潔,這次直接在PrepareContainerForItemOverride(DependencyObject element, object item)
為ColorPointVisual訂閱拖動的事件。至於ColorPointVisual的布局,只需要轉換Color為HsvColor,再計算距離中心點的角度(Hue)和距離(Saturation)就可以得出,為了不和ListView的代碼耦合,盡量使用Binding:
<TransformGroup>
<TranslateTransform X="{Binding TranslateX, Source={StaticResource SaturationAndRadiusToTransformXBridge}}" />
<RotateTransform Angle="{Binding Color, Converter={StaticResource ColorToAngleConverter}}" />
</TransformGroup>
2.2 後續功能
Hsv色輪是整個應用中最有趣的部分,之後只需要按部就班添加各種色彩規則(目前只有Analogous,即類比)和輸出的顏色模型。由於開源這個應用的目的是作為一個用於學習的應用,不想添加太多功能讓這個項目的代碼變得復雜。
2.3 已知的問題
Hsv色輪中各個ColorPoint拖動並不是太平滑,這是因為Hsv顏色只能表示360 * 100 = 36000 種顏色,而Hsv色輪上有πr^2 個像素點,它們之間做不到完全匹配。雖然已經想到解決方案,不過暫時沒太大興致解決。
3. 結語
前面提到ColorfulBox是一個用於學習的應用,不會有太多復雜的技術,暫時連MVVM都不會有。將來添加功能也會很謹慎(主要看心情),希望代碼不會膨脹得太誇張吧。
題外話,UWP一直缺少一個ColorPicker控件,而微軟將在Fall Update (1709)中提供新的控件ColorPicker,同樣基於HSV色輪。等了這麽久終於等到了。
4. 參考
色論 _ 色彩配置 - Adobe Color CC
操作事件
5. 源碼
Colorful-Box
[UWP]分享一個基於HSV色輪的調色板應用