wpf实现3d导航
框架支持.net4 至 .net8;
visual studio 2022;
animationnavigationbar3d 带有 3d 效果的导航栏控件的样式。包含多个 animationnavigationbar3ditem ,通过 uniformgrid 进行排列,超出显示区域的项可以滚动查看。
animationnavigationbar3ditem 继承 listbboxitem 是 3d 导航栏中的每个项。使用 viewport3d 来创建一个具有 3d 效果的容器,当鼠标移入或移出时,旋转动画来改变项的外观。它包含一个正面 background 和一个背面 contentback ,可以显示不同的内容。使用可以根据需要自定义内容,如果在每个项中只设置了正面内容而没有设置背面内容,那么背面会自动克隆 getxmlreader 并显示与正面相同的内容。
getxmlreader 用于通过将 uielement 对象转换为 xml 字符串,再将其转换回 uielement 对象,实现对 uielement 对象的克隆。
实现代码
1)新增 animationnavigationbar3d.cs 代码如下:
public class animationnavigationbar3d : listbox
{
static animationnavigationbar3d()
{
defaultstylekeyproperty.overridemetadata(typeof(animationnavigationbar3d),
new frameworkpropertymetadata(typeof(animationnavigationbar3d)));
}
protected override bool isitemitsowncontaineroverride(object item)
{
return item is animationnavigationbar3ditem;
}
protected override dependencyobject getcontainerforitemoverride()
{
return new animationnavigationbar3ditem();
}
}
2)新增 animationnavigationbar3ditem.cs 代码如下:
public class animationnavigationbar3ditem : listboxitem
{
public static readonly dependencyproperty fillproperty =
dependencyproperty.register("fill", typeof(brush), typeof(animationnavigationbar3ditem),
new propertymetadata(null));
public static readonly dependencyproperty contentbackproperty =
dependencyproperty.register("contentback", typeof(object), typeof(animationnavigationbar3ditem),
new propertymetadata(null));
static animationnavigationbar3ditem()
{
defaultstylekeyproperty.overridemetadata(typeof(animationnavigationbar3ditem),
new frameworkpropertymetadata(typeof(animationnavigationbar3ditem)));
}
public override void onapplytemplate()
{
base.onapplytemplate();
if (contentback == null)
contentback = controlshelper.getxmlreader(content);
}
/// <summary>
/// color fore
/// </summary>
public brush fill
{
get => (brush)getvalue(fillproperty);
set => setvalue(fillproperty, value);
}
/// <summary>
/// the content after the mouse is moved in
/// </summary>
public object contentback
{
get => (object)getvalue(contentbackproperty);
set => setvalue(contentbackproperty, value);
}
}
3)新增 animationnavigationbar3d.xaml 代码如下:
<resourcedictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:wpfdevelopers.controls">
<resourcedictionary.mergeddictionaries>
<resourcedictionary source="basic/controlbasic.xaml" />
<resourcedictionary source="basic/animations.xaml" />
</resourcedictionary.mergeddictionaries>
<style
x:key="wd.animationnavigationbar3ditem"
basedon="{staticresource wd.controlbasicstyle}"
targettype="{x:type controls:animationnavigationbar3ditem}">
<setter property="width" value="80" />
<setter property="height" value="80" />
<setter property="horizontalcontentalignment" value="center" />
<setter property="verticalcontentalignment" value="center" />
<setter property="foreground" value="{dynamicresource wd.windowforegroundcolorbrush}" />
<setter property="template">
<setter.value>
<controltemplate targettype="{x:type controls:animationnavigationbar3ditem}">
<viewport3d width="{templatebinding height}" height="{templatebinding width}">
<viewport3d.triggers>
<eventtrigger routedevent="mouseenter">
<beginstoryboard>
<storyboard storyboard.targetname="axis3d" storyboard.targetproperty="angle">
<doubleanimation
easingfunction="{staticresource wd.cubiceaseinout}"
to="90"
duration="00:00:1" />
</storyboard>
</beginstoryboard>
</eventtrigger>
<eventtrigger routedevent="mouseleave">
<beginstoryboard>
<storyboard storyboard.targetname="axis3d" storyboard.targetproperty="angle">
<doubleanimation
easingfunction="{staticresource wd.cubiceaseinout}"
to="0"
duration="00:00:1" />
</storyboard>
</beginstoryboard>
</eventtrigger>
</viewport3d.triggers>
<viewport3d.camera>
<orthographiccamera
lookdirection="0,0,-100"
position="0,0,100"
updirection="0,1,0" />
</viewport3d.camera>
<viewport3d.children>
<modelvisual3d>
<modelvisual3d.content>
<ambientlight color="{dynamicresource wd.backgroundcolor}" />
</modelvisual3d.content>
</modelvisual3d>
<containeruielement3d>
<containeruielement3d.transform>
<rotatetransform3d>
<rotatetransform3d.rotation>
<axisanglerotation3d
x:name="axis3d"
angle="0"
axis="1 0 0" />
</rotatetransform3d.rotation>
</rotatetransform3d>
</containeruielement3d.transform>
<viewport2dvisual3d>
<viewport2dvisual3d.material>
<diffusematerial viewport2dvisual3d.isvisualhostmaterial="true" />
</viewport2dvisual3d.material>
<viewport2dvisual3d.geometry>
<meshgeometry3d
positions="-1,1,1 -1,-1,1 1,-1,1 1,1,1"
texturecoordinates="0,0 0,1 1,1 1,0"
triangleindices="0 1 2 0 2 3" />
</viewport2dvisual3d.geometry>
<border
width="110"
height="110"
background="{templatebinding background}"
cornerradius="0,0,0,0">
<contentpresenter
x:name="part_contentpresenter"
horizontalalignment="{templatebinding horizontalcontentalignment}"
verticalalignment="{templatebinding verticalcontentalignment}"
snapstodevicepixels="{templatebinding snapstodevicepixels}"
textelement.foreground="{templatebinding foreground}" />
</border>
</viewport2dvisual3d>
<viewport2dvisual3d>
<viewport2dvisual3d.material>
<diffusematerial viewport2dvisual3d.isvisualhostmaterial="true" />
</viewport2dvisual3d.material>
<viewport2dvisual3d.geometry>
<meshgeometry3d
positions="-1,1,1 1,1,1 1,1,-1 -1,1,-1"
texturecoordinates="0,0 0,1 1,1 1,0"
triangleindices="0 1 2 0 2 3" />
</viewport2dvisual3d.geometry>
<border
width="110"
height="110"
background="{templatebinding fill}"
cornerradius="0,0,0,0"
rendertransformorigin="0.5,0.5">
<border.rendertransform>
<transformgroup>
<rotatetransform angle="90" />
</transformgroup>
</border.rendertransform>
<contentpresenter
horizontalalignment="{templatebinding horizontalcontentalignment}"
verticalalignment="{templatebinding verticalcontentalignment}"
content="{binding contentback, relativesource={relativesource ancestortype={x:type controls:animationnavigationbar3ditem}}}"
snapstodevicepixels="{templatebinding snapstodevicepixels}"
textelement.foreground="{templatebinding foreground}" />
</border>
</viewport2dvisual3d>
</containeruielement3d>
</viewport3d.children>
</viewport3d>
</controltemplate>
</setter.value>
</setter>
</style>
<style
x:key="wd.animationnavigationbar3d"
basedon="{staticresource wd.controlbasicstyle}"
targettype="{x:type controls:animationnavigationbar3d}">
<setter property="template">
<setter.value>
<controltemplate targettype="{x:type controls:animationnavigationbar3d}">
<border
background="{templatebinding background}"
borderbrush="{templatebinding borderbrush}"
borderthickness="{templatebinding borderthickness}"
snapstodevicepixels="{templatebinding snapstodevicepixels}"
uselayoutrounding="{templatebinding uselayoutrounding}">
<scrollviewer verticalscrollbarvisibility="auto">
<itemspresenter />
</scrollviewer>
</border>
</controltemplate>
</setter.value>
</setter>
<setter property="itemspanel">
<setter.value>
<itemspaneltemplate>
<uniformgrid columns="{binding items.count, relativesource={relativesource ancestortype={x:type controls:animationnavigationbar3d}}}" />
</itemspaneltemplate>
</setter.value>
</setter>
</style>
<style basedon="{staticresource wd.animationnavigationbar3ditem}" targettype="{x:type controls:animationnavigationbar3ditem}" />
<style basedon="{staticresource wd.animationnavigationbar3d}" targettype="{x:type controls:animationnavigationbar3d}" />
</resourcedictionary>
4)新增 getxmlreader.cs 代码如下:
public static object getxmlreader(object content)
{
var originalcontent = content as uielement;
string contentxaml = xamlwriter.save(originalcontent);
using (stringreader stringreader = new stringreader(contentxaml))
{
using (xmlreader xmlreader = xmlreader.create(stringreader))
{
object clonedcontent = xamlreader.load(xmlreader);
if (clonedcontent is uielement clonedelement)
{
return clonedelement;
}
}
}
return null;
}
5)新增 animationnavigationbar3d.xaml 示例代码如下:
<wd:animationnavigationbar3d verticalalignment="bottom">
<wd:animationnavigationbar3ditem background="#e21854" fill="#fd3574">
<stackpanel verticalalignment="center">
<path
width="40"
height="40"
data="{staticresource wd.smileyoutlinegeometry}"
fill="{dynamicresource wd.windowforegroundcolorbrush}"
stretch="uniform" />
<textblock horizontalalignment="center" text="emoji" />
</stackpanel>
</wd:animationnavigationbar3ditem>
<wd:animationnavigationbar3ditem background="#41a545" fill="#5eeca6">
<stackpanel verticalalignment="center">
<path
width="40"
height="40"
data="{staticresource wd.busgeometry}"
fill="{dynamicresource wd.windowforegroundcolorbrush}"
stretch="uniform" />
<textblock horizontalalignment="center" text="bus" />
</stackpanel>
</wd:animationnavigationbar3ditem>
<wd:animationnavigationbar3ditem background="#0a58f0" fill="#3a7dfe">
<stackpanel verticalalignment="center">
<path
width="40"
height="40"
data="{staticresource wd.friendgeometry}"
fill="{dynamicresource wd.windowforegroundcolorbrush}"
stretch="uniform" />
<textblock horizontalalignment="center" text="friend" />
</stackpanel>
</wd:animationnavigationbar3ditem>
<wd:animationnavigationbar3ditem background="#5f0574" fill="#8e1fa4">
<stackpanel verticalalignment="center">
<path
width="40"
height="40"
data="{staticresource wd.alarmclockgeometry}"
fill="{dynamicresource wd.windowforegroundcolorbrush}"
stretch="uniform" />
<textblock horizontalalignment="center" text="clock" />
</stackpanel>
</wd:animationnavigationbar3ditem>
<wd:animationnavigationbar3ditem background="#1f0355" fill="#5b31ad">
<wd:animationnavigationbar3ditem.content>
<stackpanel verticalalignment="center">
<path
width="40"
height="40"
data="{staticresource wd.buildingregulargeometry}"
fill="{dynamicresource wd.windowforegroundcolorbrush}"
stretch="uniform" />
<textblock horizontalalignment="center" text="regular" />
</stackpanel>
</wd:animationnavigationbar3ditem.content>
<wd:animationnavigationbar3ditem.contentback>
<stackpanel verticalalignment="center">
<path
width="40"
height="40"
data="{staticresource wd.buildingregulargeometry}"
fill="{dynamicresource wd.windowforegroundcolorbrush}"
stretch="uniform" />
<textblock horizontalalignment="center" text="建筑" />
</stackpanel>
</wd:animationnavigationbar3ditem.contentback>
</wd:animationnavigationbar3ditem>
</wd:animationnavigationbar3d>效果图

以上就是基于wpf实现3d导航栏控件的详细内容,更多关于wpf导航的资料请关注代码网其它相关文章!
发表评论