2010-02-16 31 views
10

Tôi có một gradient thay đổi màu sắc của nó, tôi muốn văn bản bên trong màu sắc phải luôn hiển thị.Bàn chải phủ định WPF 'ma thuật'?

Tôi thực hiện động hơn nếu có bất kỳ tài nguyên nào khác ngoài hộp; Tôi muốn một 'bàn chải ma thuật' phủ nhận màu sắc.

Bất kỳ thử nghiệm nào?

+0

Bạn có thể cung cấp ví dụ về cách bạn thay đổi màu của gradient không? –

+0

Đó là vấn đề. Tôi muốn có một bàn chải động, không tĩnh. – Shimmy

+0

Bạn có ý nghĩa gì bởi năng động? Bạn chỉ định các màu khác nhau trong mã? Chúng thay đổi như là một phần của hoạt ảnh? Bạn chỉ đơn giản có nghĩa là bạn sử dụng DynamicResource thay vì StaticResource? –

Trả lời

6

Vâng, đảo màu có thể được thực hiện dưới dạng hiệu ứng bitmap, nhưng có cách đơn giản hơn.

Thực hiện một Grid đó sẽ là container cho 3 tấm đứa trẻ để những tấm đứa trẻ sẽ chồng chéo nhau hoàn toàn:

Đặt văn bản mà bạn muốn nó trong một bảng mà có một nền Transparent (họ làm bằng cách mặc định). Đặt tên bảng này là 'mặt nạ'.

Tạo một bảng khác gọi là 'mainbackground' và đặt nó làm gradient chính làm nền của nó. Đặt bảng này sau bảng điều khiển 'mặt nạ' để nó bao gồm văn bản

Tạo một bảng khác có tên là 'đảo ngược' và cho độ dốc ngược lại. Đối với mỗi giá trị màu trong gradient chính, đặt giá trị màu này ngược lại (ví dụ: nếu một màu là #FF0000, hãy đặt #00FFFF). Bạn có thể tạo hiệu ứng cho gradient này giống như bạn có thể tạo hiệu ứng đầu tiên, chỉ với các giá trị ngược lại. Sau đó, bạn đặt OpacityMask của bảng này thành VisualBrush và đặt thuộc tính 's Visual thành {Binding ElementName=mask}.

<Grid> 
    <Grid.Resources> 
     <local:MyColorConverter x:Key="colorConverter" /> 
    </Grid.Resources> 
    <Grid 
     Name="mask"> 
     <TextBlock 
      Name="mytext" 
      HorizontalAlignment="Center" 
      VerticalAlignment="Center" 
      FontSize="32" 
      Foreground="White" 
      FontWeight="Bold">Blah blah blah</TextBlock> 
    </Grid> 

    <Grid Name="mainbackground"> 
     <Grid.Background> 
      <LinearGradientBrush 
       ColorInterpolationMode="ScRgbLinearInterpolation" 
       EndPoint="1,0"> 
       <GradientStop x:Name="stop1" 
        Color="#FF0000" 
        Offset="0" /> 
       <GradientStop x:Name="stop2" 
        Color="#00FF00" 
        Offset="0.5" /> 
       <GradientStop x:Name="stop3" 
        Color="#0000FF" 
        Offset="1" /> 
      </LinearGradientBrush> 
     </Grid.Background> 
    </Grid> 

    <Grid Name="invertedforeground"> 
     <Grid.Background> 
      <LinearGradientBrush 
       ColorInterpolationMode="ScRgbLinearInterpolation" 
       EndPoint="1,0"> 
       <GradientStop 
        Color="{Binding ElementName=stop1, Path=Color, Converter={StaticResource colorConverter}}" 
        Offset="0" /> 
       <GradientStop 
        Color="{Binding ElementName=stop2, Path=Color, Converter={StaticResource colorConverter}}" 
        Offset="0.5" /> 
       <GradientStop 
        Color="{Binding ElementName=stop3, Path=Color, Converter={StaticResource colorConverter}}" 
        Offset="1" /> 
      </LinearGradientBrush> 
     </Grid.Background> 
     <Grid.OpacityMask> 
      <VisualBrush 
       Visual="{Binding ElementName=mask}" /> 
     </Grid.OpacityMask> 
    </Grid> 
</Grid> 

Bạn có thể sử dụng trình chuyển đổi ràng buộc và giá trị để bạn chỉ cần tạo hoạt ảnh cho một gradient và đơn vị khác chỉ theo sau.


Edit: tôi đã cố gắng thiết lập một bàn chải Foreground ngược cho các văn bản, nhưng nó sẽ dính vào tọa độ của TextBlock, vì vậy tôi trở lại là giải pháp trước đây của việc sử dụng các văn bản như một OpacityMask.


Chỉnh sửa 2: tôi thêm ví dụ sử dụng một tùy chỉnh IValueConverter và ràng buộc màu gradient văn bản để gradient gốc. Bạn cũng có thể sử dụng liên kết và bộ chuyển đổi ở đâu đó cao hơn, chẳng hạn như thuộc tính Background của thuộc tính Background và bộ chuyển đổi lấy cọ vẽ đầu vào và trả về một bàn chải gradient khác (điều này cho phép bạn tạo một gradient với cấu hình khác với bản gốc).

+0

+1 để đồng bộ hóa bố cục của gradient bằng cách sử dụng OpacityMask. Hai cân nhắc bổ sung: 1. Bàn chải đảo ngược có thể được tính từ bàn chải nền trước bằng cách sử dụng ràng buộc với một IValueConverter hơn là làm theo cách thủ công. 2. Tính toán màu sắc khó khăn hơn so với đảo ngược màu thẳng, ví dụ đảo ngượC# 808080 cho bạn số 7F7F7F gần như giống hệt nhau. –

+1

# 1: Thật vậy nó có thể. Tôi nghĩ tôi sẽ cho thấy sự ràng buộc, ít nhất. # 2: Đó là định nghĩa của sự đảo ngược; chuyển đổi màu xám thành màu xám. Quyết định thiết kế để sử dụng một gradient trên văn bản để phân biệt nó với một gradient nền là một nền tảng sinh sản cho các trường hợp cạnh ở nơi đầu tiên. OP đã không cung cấp cho chúng tôi nhiều thông tin để đơn giản hóa câu trả lời của chúng tôi. –

8

Joel đưa ra một câu trả lời tuyệt vời về cách căn chỉnh bàn chải gradient. Tôi muốn chạm vào sự phức tạp của việc tự động tạo ra một bàn chải gradient mới được đảm bảo để có thể nhìn thấy được so với cái cũ.

Trong các màu WPF được lập mô hình ba chiều, vì nó yêu cầu ba số (như R/G/B hoặc H/S/B) để xác định màu WPF, không tính thành phần alpha. Một tô màu gradient có thể được xem như một đường dẫn tiến hành từ một điểm màu này sang một điểm màu khác trong không gian màu ba chiều. Để tạo ra một gradient đảo ngược tương phản tại mọi điểm yêu cầu tạo ra một đường dẫn bổ sung mà tại điểm không đến "quá gần" với đường dẫn ban đầu. "Quá gần" cho mục đích này là bất kỳ hai màu nào khó cho mắt người phân biệt. Đây là thực tế chủ quan.4% số người mù màu sẽ có cách giải thích khác "quá gần" so với những người không mù màu.

Đối với người không mù màu, nơi "quá gần" được xác định hợp lý, sẽ luôn có nhiều đường dẫn thỏa mãn tiêu chí. Trong trường hợp này cần có các tiêu chí bổ sung để quyết định tiêu chuẩn nào là "tốt hơn". Ví dụ: văn bản có nên tương phản mạnh nhất có thể với nền hay không, hoặc nó có cùng màu sắc chung nhất không? Mặt khác, một định nghĩa thận trọng về "quá gần" khiến cho nhận thức về màu sắc của mọi người trong tài khoản như "độ chói phải khác nhau ít nhất 25%" sẽ gặp phải vấn đề ngược lại: Độ dốc duy nhất thỏa mãn điều kiện tại mỗi điểm phải thực sự bị gián đoạn, đó là nó phải nhảy từ một màu đến một màu xa tất cả cùng một lúc. Hãy xem xét, ví dụ, gradient đơn giản từ đen sang trắng. Nếu chỉ có độ sáng là tham gia nền tương phản phải có một gián đoạn nếu không nó sẽ phù hợp tại một số điểm.

Vì những lý do này, việc tạo một thuật toán chung để tạo ra một nền tương phản là một nghệ thuật nhiều hơn là khoa học. Nhiều thuật toán có thể được sử dụng và các thuật toán khác nhau sẽ phù hợp trong các tình huống khác nhau.

Thuật toán đơn giản đã được sử dụng cho mục đích này là giữ màu sắc và độ bão hòa giống với độ dốc và đặt độ sáng thành (luminance + 50%) mod 100%. Thuật toán này không tạo ra kết quả rất thẩm mỹ trong hầu hết các trường hợp, tuy nhiên, và nó không bao giờ có sự thay đổi độ sáng trên 50%. Một sửa đổi của thuật toán này là đảo ngược hoặc thay đổi giá trị màu sắc và độ bão hòa.

Thuật toán đơn giản hơn để tính độ sáng tương phản là luminance>50% ? 0% : 100%. Điều này cũng có thể có vấn đề về thẩm mỹ.

Điểm mấu chốt ở đây là không có câu trả lời đúng nào để đảo ngược màu gradient của bạn. Nhưng nếu bạn đã có một thuật toán để làm điều đó, bằng cách sử dụng kỹ thuật mặt nạ mờ đục của Joel cùng với một ràng buộc và một IValueConverter mà thực hiện thuật toán của bạn sẽ làm các trick.

+1

+1: Câu trả lời của bạn chính xác là những gì tôi muốn viết ngay sau khi đọc cách tiếp cận "chống đối" của Joel. Giới thiệu tuyệt vời về các vấn đề về không gian màu! – quetzalcoatl

Các vấn đề liên quan