利用Clip制作打洞效果
起因
如上篇博文所说,连线原型需要在中间文字上下各留15像素的空白。设计师完成原型之后,问我有没有办法实现,我说,我能想到两种实现方式。其中一种就是上篇博文所说的OpacityMask。第二种就是使用Clip了。下面是效果图:

代码实现
Clip
Clip定义在UIElement中,类型为Geometry 。MSDN中的解释是获取或设置用于定义元素内容边框的几何图形。实际上不光可以在边框处留住空白,在UI元素里面留出空白也是可以的,只要定义好相关的形状。
矩形空洞
在一个大矩形中去除一个小矩形就行了。
主要代码在RectangleHoleConverter中,代码如下:
namespace HoleWithClip
{
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media; /// <summary>
/// 矩形空洞的转换器
/// </summary>
public class RectangleHoleConverter : IMultiValueConverter
{
/// <summary>
/// 转换成矩形空洞
/// </summary>
/// <param name="values">
/// 转换值列表,第一个表示起始宽度,第二个表示起始高度,
/// 第三个表示总宽度,第四个表示总高度
/// 第五个表示宿主宽度,第六个表示宿主宽度
/// </param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null || values.Length != 6 || values.HaveNullItem()
|| !values.IsAllInstanceOfType(typeof(double)))
{
return DependencyProperty.UnsetValue;
} var maskStartWidth = (double)values[0];
var maskStartHeight = (double)values[1];
var maskTotalWidth = (double)values[2];
var maskTotalHeight = (double)values[3];
var hostWidth = (double)values[4];
var hostHeight = (double)values[5];
if (hostWidth == 0.0 || hostHeight == 0.0)
{
return null;
} var maskRectangle = new RectangleGeometry(new Rect(new Size(hostWidth, hostHeight)));
var maskEllipse = new RectangleGeometry(new Rect(
new Point(maskStartWidth, maskStartHeight),
new Size(maskTotalWidth, maskTotalHeight)));
var combinedGeometry = Geometry.Combine(maskRectangle, maskEllipse, GeometryCombineMode.Exclude, null); return combinedGeometry;
} public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return new[] { Binding.DoNothing };
}
}
}
其中用到了两个扩展方法如下:
namespace HoleTest
{
using System;
using System.Collections.Generic;
using System.Linq; public static class EnumerableExtension
{
/// <summary>
/// 枚举器中是否存在null条目
/// </summary>
/// <typeparam name="T">元素类型</typeparam>
/// <param name="enumerable">元素枚举</param>
/// <returns>存在null条目返回true,否则返回false</returns>
public static bool HaveNullItem<T>(this IEnumerable<T> enumerable)
{
return enumerable.Any(item => item == null);
} /// <summary>
/// 枚举器中是否全为指定类型的实例
/// </summary>
/// <typeparam name="T">元素类型</typeparam>
/// <param name="enumerable">元素枚举</param>
/// <returns>全为指定类型的实例返回true,否则返回false</returns>
public static bool IsAllInstanceOfType<T>(this IEnumerable<T> enumerable, Type type)
{
return enumerable.All(item => type.IsInstanceOfType(item));
}
}
}
椭圆形空洞
跟矩形空洞类似,在大的矩形中间排除一个椭圆。
主要代码在EllipseHoleConverter中,代码如下:
namespace HoleWithClip
{
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media; /// <summary>
/// 椭圆形空洞的转换器
/// </summary>
public class EllipseHoleConverter : IMultiValueConverter
{
/// <summary>
/// 转换成矩形空洞
/// </summary>
/// <param name="values">
/// 转换值列表,第一个表示起始宽度,第二个表示起始高度,
/// 第三个表示总宽度,第四个表示总高度
/// 第五个表示宿主宽度,第六个表示宿主宽度
/// </param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null || values.Length != 6 || values.HaveNullItem()
|| !values.IsAllInstanceOfType(typeof(double)))
{
return DependencyProperty.UnsetValue;
} var maskEllipseCenterX = (double)values[0];
var maskEllipseCenterY = (double)values[1];
var maskRadiusX = (double)values[2];
var maskRadiusY = (double)values[3];
var hostWidth = (double)values[4];
var hostHeight = (double)values[5];
if (hostWidth == 0.0 || hostHeight == 0.0)
{
return null;
} var maskRectangle = new RectangleGeometry(new Rect(new Size(hostWidth, hostHeight)));
var maskEllipse = new EllipseGeometry(
new Point(maskEllipseCenterX, maskEllipseCenterY),
maskRadiusX,
maskRadiusY);
var combinedGeometry = Geometry.Combine(maskRectangle, maskEllipse, GeometryCombineMode.Exclude, null); return combinedGeometry;
} public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return new[] { Binding.DoNothing };
}
}
}
不规则空洞
我们各种Shape中最常用的是Path,因为许多复杂的效果能够在设计工具中绘制成Path。与此类似,Geometry中最强大的还是PathGeometry。上面图片中的五角形就是将Path数据转换成PathGeometry的。XAML代码如下:
<Border Width="180"
Height="180"
Margin="3"
Background="Aquamarine">
<Border Background="LightPink" Clip="M90.000003,0.5 L111.12693,68.873594 L179.50001,68.871913 L124.18408,111.12744 L145.31405,179.49999 L90.000003,137.24175 L34.685959,179.49999 L55.815923,111.12744 L0.50000013,68.871913 L68.87308,68.873594 z" />
</Border>
话说,只看XAML代码真看不出这是什么鬼东西。
下载链接
博客园:HoleWithClip
OpacityMask与Clip区别
可以看出,通过OpacityMask和Clip都能实现打洞效果。但是通过OpactiyMask实现的效果在空洞中间会引发相应的事件,而Clip则不会,原因是在于UIElement中作命中测试考虑到了Clip的存在。应根据实际需求选择不同的实现方式。
利用Clip制作打洞效果的更多相关文章
- 利用OpacityMask制作打洞效果
起因 项目上存在一个连线功能,在设计的原型中,在连线中间文字上下各有15像素的空白.接手的同事觉得没思路,问我能不能在不影响连线后面的背景情况下解决该问题.我就抽了点时间给他写了个Demo.回家后趁热 ...
- 利用css3制作毛玻璃的效果
忙里偷闲,最近又在看许多比较酷炫的效果.现在基于jquery的插件比较多,但是很多插件的兼容性不是太好,所以原生的才是王道.在日常当中,毛玻璃已经不常见了,那是一个很久远年代的东西了.诺,下面就是毛玻 ...
- 分享一个利用HTML5制作的海浪效果代码
在前面简单讲述了一下HTML里的Canvas,这次根据Canvas完成了“海浪效果”(水波上升). (O(∩_∩)O哈哈哈~作者我能看这个动画看一下午) 上升水波.gif 动画分析构成:贝塞尔曲线画布 ...
- flash8中利用遮罩制作图片切换效果
http://www.56.com/w73/play_album-aid-8642763_vid-NDY5ODU2Mzg.html
- 利用TabHost制作QQ客户端标签栏效果(低版本QQ)
学习一定要从基础学起,只有有一个好的基础,我们才会变得更加的perfect 下面小编将利用TabHost制作QQ客户端标签栏效果(这个版本的QQ是在前几年发布的)…. 首先我们看一下效果: 看到这个界 ...
- 纯代码利用CSS3 圆角边框和盒子阴影 制作 iphone 手机效果
原文:纯代码利用CSS3 圆角边框和盒子阴影 制作 iphone 手机效果 大家好,我是小强老师. 今天我们看下CSS3最为简单的两个属性. css3给我们带来了很多视觉的感受和变化,以前的图片做的事 ...
- 利用CSS3制作淡入淡出动画效果
CSS3新增动画属性“@-webkit-keyframes”,从字面就可以看出其含义——关键帧,这与Flash中的含义一致. 利用CSS3制作动画效果其原理与Flash一样,我们需要定义关键帧处的状态 ...
- 利用FluidMoveBehavior制作出手机通讯录平滑的效果
最近学习Blend,原来Blend制作动画等效果非常棒.下面演示一下FluidMoveBehavior应用,利用Blend中行为中的FluidMoveBehavior制作出手机通讯录平滑的效果 1.在 ...
- WPF设置VistualBrush的Visual属性制作图片放大镜效果
原文:WPF设置VistualBrush的Visual属性制作图片放大镜效果 效果图片:原理:设置VistualBrush的Visual属性,利用它的Viewbox属性进行缩放. XAML代码:// ...
随机推荐
- Maven的安装使用以及 Maven+Spring hello world example
关于Maven Maven是一个用于项目构建的工具,通过它便捷的管理项目的生命周期.即项目的jar包依赖,开发,测试,发布打包. 做过.NET的人应该会联想到Nuget,是的Maven其实就是java ...
- 跨平台的 SQL 客户端
The major update to SQL client was to move to the .NET Core networking libraries instead of the nati ...
- java File.mkdirs和mkdir区别
File f = new File("e://xxx//yyy"); System.out.println(f.mkdirs());//生成所有目录,一般来说,这个方法稳健性更好, ...
- Wechat4j之Hello world——使用wechat4j快速开发java版微信公众号
Wechat4j是一个开源的java微信开发框架,是目前最简单易用的java微信开发框架. 项目地址:https://github.com/sword-org/wechat4j Wechat4j.ja ...
- 经典实用jQuery soChange幻灯片实例演示
soChange一款多很经典的幻灯片的jQuery插件. 实例预览 引入文件 <link rel="stylesheet" type="text/css" ...
- MapGIS转Shp文件的单位问题
在MapGIS浏览查看一下数据,各种不习惯:用mapgis自带的转shp功能,属性表会出错:利用名为map2shp的试用版软件可将mapgis格式的数据较为良好转成shp格式.但经常会遇到一个单位问题 ...
- android notification 传值关键
android notification 传值关键在 onNewIntent方法里获取 @Override protected void onCreate(Bundle savedInstanceSt ...
- Web应用程序系统的多用户权限控制设计及实现-用户模块【7】
前五章均是从整体上讲述了Web应用程序的多用户权限控制实现流程,本章讲述Web权限管理系统的基本模块-用户模块.用户模块涉及到的数据表为用户表. 1.1用户域 为了更规范和方便后期系统的二次开发和维护 ...
- iOS开发 使用RMStore简化内购代码 + 内购买订单验证
现在很多的app里面都添加了应用内购买,网上关于苹果证书的生成和设置的教程比较多,这里就不多赘述了,推荐几个个人觉得说的比较详细的网址: http://www.jianshu.com/p/86ac7d ...
- iOS之UI--指示器HUD的创建和设置
指示器的创建和设置 渐变动画 描述: 使用label就能制作指示器,原理:就是让label以动画的形式慢慢显示和消失 最好是半透明的 指示器有时候也被称为:HUD,遮盖,蒙版 思路步骤: 1.先在st ...