前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Silverlight实现类似Mac Dock特效

Silverlight实现类似Mac Dock特效

作者头像
卡尔曼和玻尔兹曼谁曼
发布2019-01-25 15:17:23
5790
发布2019-01-25 15:17:23
举报

首先,看一下最终的效果图。我采用的开发环境是Visual Studio 2010。

其实,这里要点,主要有两个,一个是计算鼠标位置到每个图像子元素中心位置的函数,另一个是计算放大倍数,放大倍数是鼠标位置到到每个图像子元素中心位置的距离的,具体如下:

下面是计算标位置到每个图像子元素中心位置的距离二次函数

代码语言:javascript
复制
/// <summary>
/// 计算鼠标位置到SilverDockItem元素的中心距离
/// </summary>
/// <param name="mouseArgs">The <see cref="MouseButtonEventArgs"/> instance containing the event data.</param>
/// <param name="target">The target.</param>
/// <returns></returns>
private double CalculateDistance(MouseEventArgs mouseArgs, SilverDockItem target)
{
	double mouseX = mouseArgs.GetPosition(target).X - (target.ActualWidth / 2);
	double mouseY = mouseArgs.GetPosition(target).Y - (target.ActualHeight / 2);
	double distance = Math.Sqrt(mouseX * mouseX + mouseY * mouseY);
	return distance;
}

下面是计算放大的倍数

代码语言:javascript
复制
/// <summary>
/// 计算SilverDockItem元素的放大倍数
/// </summary>
/// <param name="maxZoom">放大倍数上限,即最大的放大倍数</param>
/// <param name="maxDistance">感知长度,超过这个距离后放大倍数保持在1</param>
/// <param name="distanceToItem">鼠标到目标Item中心的距离</param>
/// <returns></returns>
private double Zoom(double maxZoom, double maxDistance, double distanceToItem)
{
	//计算放大的倍数,这里放大倍数和鼠标到SilverDockItem元素的中心距离为二次函数关系
	double zoom = (maxZoom * (distanceToItem - maxDistance) * (distanceToItem - maxDistance)) / (maxDistance * maxDistance + 1);

	//如果计算放大倍数小于1,返回1,即不进行放大也不缩小
	//也就是说鼠标到子元素中心距离大于一定值时就不进行缩放了
	if (zoom < 1)
	{
		return 1;
	}
	else
	{
		return zoom;
	}
}

具体开发过程如下:

1. 新建图像子元素SilverDockItem,代码如下:

代码语言:javascript
复制
<UserControl x:Class="SilverControl.SilverDockItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" Height="60" Width="60" SizeChanged="UserControl_SizeChanged">
    
    <Grid x:Name="LayoutRoot">
        <Rectangle d:DesignHeight="60" d:DesignWidth="60"  MouseMove="Rectangle_MouseMove" MouseLeave="Rectangle_MouseLeave">
            <Rectangle.Fill>
                <ImageBrush x:Name="ContentImage" Stretch="Fill" />
            </Rectangle.Fill>
        </Rectangle>
    </Grid>
</UserControl>
代码语言:javascript
复制
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;

namespace SilverControl
{
    public partial class SilverDockItem : UserControl
    {
        public static readonly double ORIGNSIZE = 60;
        
        //宿主容器,即容纳SilverDock元素的父控件
        internal SilverDock Dock { get; set; }

        public SilverDockItem(String uri)
        {
            InitializeComponent();
            //设置图像的ImageSource依赖属性,即要显示的图像元素
            //下面两句是同样的效果
            //ContentImage.SetValue(ImageBrush.ImageSourceProperty, new BitmapImage(new Uri(uri, UriKind.Relative)));
            ContentImage.ImageSource = new BitmapImage(new Uri(uri, UriKind.Relative));
        }

        /// <summary>
        /// 计算SilverDockItem元素的放大倍数
        /// </summary>
        /// <param name="maxZoom">放大倍数上限,即最大的放大倍数</param>
        /// <param name="maxDistance">感知长度,超过这个距离后放大倍数保持在1</param>
        /// <param name="distanceToItem">鼠标到目标Item中心的距离</param>
        /// <returns></returns>
        private double Zoom(double maxZoom, double maxDistance, double distanceToItem)
        {
            //计算放大的倍数,这里放大倍数和鼠标到SilverDockItem元素的中心距离为二次函数关系
            double zoom = (maxZoom * (distanceToItem - maxDistance) * (distanceToItem - maxDistance)) / (maxDistance * maxDistance + 1);

            //如果计算放大倍数小于1,返回1,即不进行放大也不缩小
            //也就是说鼠标到子元素中心距离大于一定值时就不进行缩放了
            if (zoom < 1)
            {
                return 1;
            }
            else
            {
                return zoom;
            }
        }

        /// <summary>
        /// 计算鼠标位置到SilverDockItem元素的中心距离
        /// </summary>
        /// <param name="mouseArgs">The <see cref="MouseButtonEventArgs"/> instance containing the event data.</param>
        /// <param name="target">The target.</param>
        /// <returns></returns>
        private double CalculateDistance(MouseEventArgs mouseArgs, SilverDockItem target)
        {
            double mouseX = mouseArgs.GetPosition(target).X - (target.ActualWidth / 2);
            double mouseY = mouseArgs.GetPosition(target).Y - (target.ActualHeight / 2);
            double distance = Math.Sqrt(mouseX * mouseX + mouseY * mouseY);
            return distance;
        }

        /// <summary>
        /// Handles the MouseMove event of the Rectangle control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
        private void Rectangle_MouseMove(object sender, MouseEventArgs e)
        {
            foreach (var item in Dock.items)
            {
                double distance = CalculateDistance(e, item);
                double zoom = Zoom(Dock.MaxZoom, Dock.MaxDistance, distance);
                item.Width = zoom * Dock.Size;
                item.Height = zoom * Dock.Size;
            }
        }

        /// <summary>
        /// Handles the MouseLeave event of the Rectangle control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
        private void Rectangle_MouseLeave(object sender, MouseEventArgs e)
        {
            foreach (var item in Dock.items)
            {
                item.Width = ORIGNSIZE;
                item.Height = ORIGNSIZE;
            }
        }

        /// <summary>
        /// Handles the SizeChanged event of the UserControl control.
        /// 当每个SilverDockItem元素的大小改变时,动态修改其承载元素StackPanel的长度,可以可以确保StackPanel始终居中显示
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="SizeChangedEventArgs"/> instance containing the event data.</param>
        private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            double totalWidth = 0;
            foreach (var item in Dock.items)
            {
                totalWidth += item.Width;
            }
            Dock.ContentPanel.Width = totalWidth;
        }
    }
}

2.新建承载的StackPanel,代码如下:

代码语言:javascript
复制
<UserControl x:Class="SilverControl.SilverDock"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" Height="100" Width="900" BorderBrush="Black" BorderThickness="1">
    
    <Grid x:Name="LayoutRoot">
    	<Rectangle Fill="#55000000" Stroke="Black" RadiusX="9" RadiusY="9">
    		<Rectangle.Effect>
    			<DropShadowEffect/>
    		</Rectangle.Effect>
    	</Rectangle>
        <StackPanel x:Name="ContentPanel" Orientation="Horizontal" />
    </Grid>
</UserControl>
代码语言:javascript
复制
using System.Collections.Generic;
using System.Windows.Controls;

namespace SilverControl
{
    public partial class SilverDock : UserControl
    {
        internal List<SilverDockItem> items = new List<SilverDockItem>();

        public double Size { get; set; } //SilverDockItem子元素的尺寸,这里SilverDockItem长宽相等
        public double MaxDistance { get; set; } //感知长度,超过这个距离后放大倍数保持在1
        public double MaxZoom { get; set; } //放大倍数上限,即最大的放大倍数

        public SilverDock()
        {
            InitializeComponent();
        }


        /// <summary>
        /// 给SilverDock工具条动态添加子元素item
        /// </summary>
        /// <param name="item">SilverDockItem子元素</param>
        public void AddItem(SilverDockItem item)
        {
            item.Dock = this;
            item.Height = Size;
            item.Width = Size;
            items.Add(item);
            ContentPanel.Children.Add(item);
        }

        /// <summary>
        /// 从SilverDock工具条中移除SilverDockItem子元素
        /// </summary>
        /// <param name="item">SilverDockItem子元素</param>
        public void RemoveItem(SilverDockItem item)
        {
            items.Remove(item);
            ContentPanel.Children.Remove(item);
        }
    }
}

3.主页面MainPage,代码如下:

代码语言:javascript
复制
<UserControl x:Class="SilverControl.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">

    </Grid>
</UserControl>
代码语言:javascript
复制
using System.Windows.Controls;


namespace SilverControl
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();


            SilverDock silverDock = new SilverDock();
            silverDock.MaxZoom = 1.5;
            silverDock.MaxDistance = 600;
            silverDock.Size = 60;
            silverDock.Size = 60;
            LayoutRoot.Children.Add(silverDock);


            for (int i = 0; i <= 13; i++ )
            {
                SilverDockItem item = new SilverDockItem("images/" + i + ".png");
                silverDock.AddItem(item);
            }
        }
    }
}

有需要源码的同学可以从我的网盘下载。源码下载地址如下:http://yunpan.cn/QI7KHpACMfiXa

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2014年04月09日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档