1. 程式人生 > >[UWP]分享一個基於HSV色輪的調色板應用

[UWP]分享一個基於HSV色輪的調色板應用

set pick sse 分享圖片 ride eof protect cti tco

原文:[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色輪的調色板應用